Skip to content

Commit

Permalink
Merge branch 'main' into update-soroban-rpc-crate
Browse files Browse the repository at this point in the history
  • Loading branch information
psheth9 committed Mar 9, 2024
2 parents 9940365 + 7e543f3 commit 75a806c
Show file tree
Hide file tree
Showing 15 changed files with 369 additions and 1,612 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dependency-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- run: rustup update
- uses: actions/setup-go@v3
with:
go-version: 1.21
go-version: 1.22
- run: scripts/check-dependencies.bash
validate-rust-git-rev-deps:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Setup GO
uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f # version v3.3.0
with:
go-version: '>=1.21.0'
go-version: '>=1.22.1'

- name: Build libpreflight
run: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/soroban-rpc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-22.04]
go: [1.21]
go: [1.22]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:
# because it uses apt-get and some OSs (e.g. windows) don't have it
- uses: actions/setup-go@v3
with:
go-version: 1.21
go-version: 1.22

- run: |
rustup target add ${{ matrix.rust_target }}
Expand Down Expand Up @@ -106,7 +106,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-22.04]
go: [1.21]
go: [1.22]
test: ['.*CLI.*', '^Test(([^C])|(C[^L])|(CL[^I])).*$']
runs-on: ${{ matrix.os }}
env:
Expand Down
30 changes: 15 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,25 @@ version = "20.3.3"
rust-version = "1.74.0"

[workspace.dependencies.soroban-env-host]
version = "=20.2.1"
# git = "https://github.com/stellar/rs-soroban-env"
# rev = "1bfc0f2a2ee134efc1e1b0d5270281d0cba61c2e"
version = "=20.2.2"
git = "https://github.com/stellar/rs-soroban-env"
rev = "8c9ab83c406bd86f56d52eae3e39dccf6b45b3da"
# path = "../rs-soroban-env/soroban-env-host"

[workspace.dependencies.soroban-simulation]
version = "=20.2.1"
# git = "https://github.com/stellar/rs-soroban-env"
# rev = "1bfc0f2a2ee134efc1e1b0d5270281d0cba61c2e"
version = "=20.2.2"
git = "https://github.com/stellar/rs-soroban-env"
rev = "8c9ab83c406bd86f56d52eae3e39dccf6b45b3da"
# path = "../rs-soroban-env/soroban-simulation"

[workspace.dependencies.soroban-spec]
version = "=20.3.1"
# git = "https://github.com/stellar/rs-soroban-sdk"
# rev = "4aef54ff9295c2fca4c5b9fbd2c92d0ff99f67de"
version = "=20.4.0"
git = "https://github.com/stellar/rs-soroban-sdk"
rev = "89efc3c211d41f1ab143bed0a09cd6af353bb098"
# path = "../rs-soroban-sdk/soroban-spec"

[workspace.dependencies.soroban-spec-rust]
version = "=20.3.1"
version = "=20.3.2"
# git = "https://github.com/stellar/rs-soroban-sdk"
# rev = "4aef54ff9295c2fca4c5b9fbd2c92d0ff99f67de"
# path = "../rs-soroban-sdk/soroban-spec-rust"
Expand All @@ -46,17 +46,17 @@ git = "https://github.com/stellar/soroban-cli"
rev = "a59f5f421a27bab71472041fc619dd8b0d1cf902"

[workspace.dependencies.soroban-sdk]
version = "=20.3.1"
# git = "https://github.com/stellar/rs-soroban-sdk"
# rev = "4aef54ff9295c2fca4c5b9fbd2c92d0ff99f67de"
version = "=20.4.0"
git = "https://github.com/stellar/rs-soroban-sdk"
rev = "89efc3c211d41f1ab143bed0a09cd6af353bb098"

[workspace.dependencies.soroban-token-sdk]
version = "=20.3.1"
version = "=20.3.2"
# git = "https://github.com/stellar/rs-soroban-sdk"
# rev = "4aef54ff9295c2fca4c5b9fbd2c92d0ff99f67de"

[workspace.dependencies.soroban-ledger-snapshot]
version = "=20.3.1"
version = "=20.3.2"
# git = "https://github.com/stellar/rs-soroban-sdk"
# rev = "4aef54ff9295c2fca4c5b9fbd2c92d0ff99f67de"

Expand Down
66 changes: 16 additions & 50 deletions cmd/crates/stellar-rpc-client/src/txn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,21 +317,10 @@ pub fn assemble(
let classic_tx_fee: u64 = crate::DEFAULT_TRANSACTION_FEES.into();

// Choose larger of existing fee or inclusion + resource fee.
let base_tx_fee: u64 = tx
.fee
.max(
u32::try_from(classic_tx_fee + simulation.min_resource_fee)
.map_err(|_| Error::LargeFee(simulation.min_resource_fee + classic_tx_fee))?,
)
.into(); // invariant: base_tx_fee <= u32::MAX

// Pad the total fee by up to 15% for a bit of wiggle room.
//
// We know for a fact because of the .min() call that we will not exceed
// U32_MAX, but we can't get clippy to shut the fuck up for this single
// line, so we have a redundant error check anyway.
tx.fee = u32::try_from((base_tx_fee * 115 / 100).min(u64::from(u32::MAX)))
.map_err(|_| Error::LargeFee(base_tx_fee))?;
tx.fee = tx.fee.max(
u32::try_from(classic_tx_fee + simulation.min_resource_fee)
.map_err(|_| Error::LargeFee(simulation.min_resource_fee + classic_tx_fee))?,
);

tx.operations = vec![op].try_into()?;
tx.ext = TransactionExt::V1(transaction_data);
Expand Down Expand Up @@ -628,7 +617,7 @@ mod tests {

// validate it auto updated the tx fees from sim response fees
// since it was greater than tx.fee
assert_eq!(247, result.fee);
assert_eq!(215, result.fee);

// validate it updated sorobantransactiondata block in the tx ext
assert_eq!(TransactionExt::V1(transaction_data()), result.ext);
Expand Down Expand Up @@ -735,62 +724,39 @@ mod tests {
#[test]
fn test_assemble_transaction_overflow_behavior() {
//
// Test three separate cases:
//
// 1. Given a near-max (U32_MAX) resource fee, ensure the "wiggle room"
// doesn't cause an overflow due to correct math order.
// (Specifically, do U32_MAX - 15% - 100 - 1, so the final fee is
// U32_MAX-1.)
//
// 2. Given a large resource fee that WILL exceed on its own with the
// inclusion fee, ensure the overflow is caught with an error rather
// than silently ignored.
//
// 3. Given a max resource fee that exceeds U32_MAX *only with* wiggle
// room, ensure the overflow is ignored and we cap on the max.
// Test two separate cases:
//
// 1. Given a near-max (u32::MAX - 100) resource fee make sure the tx
// fee does not overflow after adding the base inclusion fee (100).
// 2. Given a large resource fee that WILL exceed u32::MAX with the
// base inclusion fee, ensure the overflow is caught with an error
// rather than silently ignored.
let txn = single_contract_fn_transaction();
let mut response = simulation_response();

// sanity check so these can be adjusted if the above helper changes
assert_eq!(txn.fee, 100, "modified txn.fee: update the math below");

// 1: wiggle room math overflows but result fits
let mut resource_fee = (u64::from(u32::MAX) * 85 / 100) - 100 - 1;
assert_eq!(resource_fee, 3_650_722_099);
response.min_resource_fee = resource_fee;
response.min_resource_fee = (u32::MAX - 100).into();

match assemble(&txn, &response) {
Ok(asstxn) => {
let expected = (resource_fee + 100) * 115 / 100;
assert_eq!(asstxn.fee, u32::try_from(expected).unwrap());
let expected = u32::MAX;
assert_eq!(asstxn.fee, expected);
}
r => panic!("expected success, got: {r:#?}"),
}

// 2: combo overflows, should throw
resource_fee = u64::from(u32::MAX);
assert_eq!(resource_fee, 4_294_967_295);
response.min_resource_fee = resource_fee;
response.min_resource_fee = (u32::MAX - 99).into();

match assemble(&txn, &response) {
Err(Error::LargeFee(fee)) => {
let expected = resource_fee + 100;
let expected = u64::from(u32::MAX) + 1;
assert_eq!(expected, fee, "expected {expected} != {fee} actual");
}
r => panic!("expected LargeFee error, got: {r:#?}"),
}

// 2: combo works but wiggle room overflows, should cap
resource_fee = u64::from(u32::MAX) * 90 / 100;
assert_eq!(resource_fee, 3_865_470_565);
response.min_resource_fee = resource_fee;

match assemble(&txn, &response) {
Ok(asstxn) => {
assert_eq!(asstxn.fee, u32::MAX);
}
r => panic!("expected success, got: {r:#?}"),
}
}
}
2 changes: 1 addition & 1 deletion cmd/soroban-rpc/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21-bullseye as build
FROM golang:1.22-bullseye as build
ARG RUST_TOOLCHAIN_VERSION=stable
ARG REPOSITORY_VERSION

Expand Down
55 changes: 21 additions & 34 deletions cmd/soroban-rpc/internal/preflight/preflight.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package preflight

import (
"context"
"errors"
"fmt"
"runtime/cgo"
"time"
Expand Down Expand Up @@ -36,7 +35,7 @@ type snapshotSourceHandle struct {
}

const (
defaultInstructionLeeway uint64 = 3000000
defaultInstructionLeeway uint64 = 0
)

// SnapshotSourceGet takes a LedgerKey XDR in base64 string and returns its matching LedgerEntry XDR in base64 string
Expand Down Expand Up @@ -150,6 +149,23 @@ func GetPreflight(ctx context.Context, params PreflightParameters) (Preflight, e
}
}

func getLedgerInfo(params PreflightParameters) (C.ledger_info_t, error) {
simulationLedgerSeq, err := getSimulationLedgerSeq(params.LedgerEntryReadTx)
if err != nil {
return C.ledger_info_t{}, err
}

li := C.ledger_info_t{
network_passphrase: C.CString(params.NetworkPassphrase),
sequence_number: C.uint32_t(simulationLedgerSeq),
protocol_version: 20,
timestamp: C.uint64_t(time.Now().Unix()),
// Current base reserve is 0.5XLM (in stroops)
base_reserve: 5_000_000,
}
return li, nil
}

func getFootprintTtlPreflight(params PreflightParameters) (Preflight, error) {
opBodyXDR, err := params.OpBody.MarshalBinary()
if err != nil {
Expand All @@ -164,17 +180,16 @@ func getFootprintTtlPreflight(params PreflightParameters) (Preflight, error) {
handle := cgo.NewHandle(snapshotSourceHandle{params.LedgerEntryReadTx, params.Logger})
defer handle.Delete()

simulationLedgerSeq, err := getSimulationLedgerSeq(params.LedgerEntryReadTx)
li, err := getLedgerInfo(params)
if err != nil {
return Preflight{}, err
}

res := C.preflight_footprint_ttl_op(
C.uintptr_t(handle),
C.uint64_t(params.BucketListSize),
opBodyCXDR,
footprintCXDR,
C.uint32_t(simulationLedgerSeq),
li,
)

FreeGoXDR(opBodyCXDR)
Expand Down Expand Up @@ -206,46 +221,18 @@ func getInvokeHostFunctionPreflight(params PreflightParameters) (Preflight, erro
return Preflight{}, err
}
sourceAccountCXDR := CXDR(sourceAccountXDR)

hasConfig, stateArchivalConfig, _, err := db.GetLedgerEntry(params.LedgerEntryReadTx, xdr.LedgerKey{
Type: xdr.LedgerEntryTypeConfigSetting,
ConfigSetting: &xdr.LedgerKeyConfigSetting{
ConfigSettingId: xdr.ConfigSettingIdConfigSettingStateArchival,
},
})
if err != nil {
return Preflight{}, err
}
if !hasConfig {
return Preflight{}, errors.New("state archival config setting missing in ledger storage")
}

simulationLedgerSeq, err := getSimulationLedgerSeq(params.LedgerEntryReadTx)
li, err := getLedgerInfo(params)
if err != nil {
return Preflight{}, err
}

stateArchival := stateArchivalConfig.Data.MustConfigSetting().MustStateArchivalSettings()
li := C.ledger_info_t{
network_passphrase: C.CString(params.NetworkPassphrase),
sequence_number: C.uint32_t(simulationLedgerSeq),
protocol_version: 20,
timestamp: C.uint64_t(time.Now().Unix()),
// Current base reserve is 0.5XLM (in stroops)
base_reserve: 5_000_000,
min_temp_entry_ttl: C.uint(stateArchival.MinTemporaryTtl),
min_persistent_entry_ttl: C.uint(stateArchival.MinPersistentTtl),
max_entry_ttl: C.uint(stateArchival.MaxEntryTtl),
}

handle := cgo.NewHandle(snapshotSourceHandle{params.LedgerEntryReadTx, params.Logger})
defer handle.Delete()
resourceConfig := C.resource_config_t{
instruction_leeway: C.uint64_t(params.ResourceConfig.InstructionLeeway),
}
res := C.preflight_invoke_hf_op(
C.uintptr_t(handle),
C.uint64_t(params.BucketListSize),
invokeHostFunctionCXDR,
sourceAccountCXDR,
li,
Expand Down
14 changes: 12 additions & 2 deletions cmd/soroban-rpc/internal/preflight/preflight_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ var contractCostParams = func() *xdr.ContractCostParams {
for i := 0; i < 23; i++ {
result = append(result, xdr.ContractCostParamEntry{
Ext: xdr.ExtensionPoint{},
ConstTerm: 0,
LinearTerm: 0,
ConstTerm: xdr.Int64((i + 1) * 10),
LinearTerm: xdr.Int64(i),
})
}

Expand Down Expand Up @@ -190,6 +190,16 @@ var mockLedgerEntriesWithoutTTLs = []xdr.LedgerEntry{
},
},
},
{
LastModifiedLedgerSeq: 2,
Data: xdr.LedgerEntryData{
Type: xdr.LedgerEntryTypeConfigSetting,
ConfigSetting: &xdr.ConfigSettingEntry{
ConfigSettingId: xdr.ConfigSettingIdConfigSettingBucketlistSizeWindow,
BucketListSizeWindow: &[]xdr.Uint64{100, 200},
},
},
},
}

// Adds ttl entries to mockLedgerEntriesWithoutTTLs
Expand Down
6 changes: 3 additions & 3 deletions cmd/soroban-rpc/internal/test/simulate_transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func TestSimulateTransactionSucceeds(t *testing.T) {
// for test purposes, the most deterministic way to assert the resulting fee is expected value in test scope, is to capture
// the resulting fee from current preflight output and re-plug it in here, rather than try to re-implement the cost-model algo
// in the test.
ResourceFee: 132146,
ResourceFee: 118357,
}

// First, decode and compare the transaction data so we get a decent diff if it fails.
Expand Down Expand Up @@ -546,7 +546,7 @@ func TestSimulateInvokeContractTransactionSucceeds(t *testing.T) {
require.Contains(t, metrics, "soroban_rpc_json_rpc_request_duration_seconds_count{endpoint=\"simulateTransaction\",status=\"ok\"} 3")
require.Contains(t, metrics, "soroban_rpc_preflight_pool_request_ledger_get_duration_seconds_count{status=\"ok\",type=\"db\"} 3")
require.Contains(t, metrics, "soroban_rpc_preflight_pool_request_ledger_get_duration_seconds_count{status=\"ok\",type=\"all\"} 3")
require.Contains(t, metrics, "soroban_rpc_preflight_pool_request_ledger_entries_fetched_sum 67")
require.Contains(t, metrics, "soroban_rpc_preflight_pool_request_ledger_entries_fetched_sum 60")
}

func TestSimulateTransactionError(t *testing.T) {
Expand Down Expand Up @@ -1130,7 +1130,7 @@ func TestSimulateSystemEvent(t *testing.T) {
// for test purposes, the most deterministic way to assert the resulting fee is expected value in test scope, is to capture
// the resulting fee from current preflight output and re-plug it in here, rather than try to re-implement the cost-model algo
// in the test.
assert.InDelta(t, 100980, int64(transactionData.ResourceFee), 5000)
assert.InDelta(t, 85360, int64(transactionData.ResourceFee), 5000)
assert.InDelta(t, 104, uint32(transactionData.Resources.WriteBytes), 15)
require.GreaterOrEqual(t, len(response.Events), 3)
}
Loading

0 comments on commit 75a806c

Please sign in to comment.