From 1f1ef114b1d765f648a3f74565aef033a2349195 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 16 Oct 2023 15:25:46 +0200 Subject: [PATCH 01/14] Bump dependencies --- .github/workflows/soroban-rpc.yml | 2 +- Cargo.lock | 22 +++++++++---------- Cargo.toml | 12 +++++----- .../internal/test/docker-compose.yml | 2 +- go.mod | 7 +++--- go.sum | 8 +++---- 6 files changed, 26 insertions(+), 27 deletions(-) diff --git a/.github/workflows/soroban-rpc.yml b/.github/workflows/soroban-rpc.yml index 99dc6fc40..98ed89f91 100644 --- a/.github/workflows/soroban-rpc.yml +++ b/.github/workflows/soroban-rpc.yml @@ -112,7 +112,7 @@ jobs: env: SOROBAN_RPC_INTEGRATION_TESTS_ENABLED: true SOROBAN_RPC_INTEGRATION_TESTS_CAPTIVE_CORE_BIN: /usr/bin/stellar-core - PROTOCOL_20_CORE_DEBIAN_PKG_VERSION: 19.13.1-1481.3acf6dd26.focal + PROTOCOL_20_CORE_DEBIAN_PKG_VERSION: 19.14.1-1529.fcbbad4ce.focal steps: - uses: actions/checkout@v3 with: diff --git a/Cargo.lock b/Cargo.lock index 658160012..0c6f50d4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2518,7 +2518,7 @@ dependencies = [ [[package]] name = "soroban-env-common" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-env?rev=8c63bff68a15d79aca3a705ee6916a68db57b7e6#8c63bff68a15d79aca3a705ee6916a68db57b7e6" +source = "git+https://github.com/stellar/rs-soroban-env?rev=91f44778389490ad863d61a8a90ac9875ba6d8fd#91f44778389490ad863d61a8a90ac9875ba6d8fd" dependencies = [ "arbitrary", "crate-git-revision 0.0.6", @@ -2535,7 +2535,7 @@ dependencies = [ [[package]] name = "soroban-env-guest" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-env?rev=8c63bff68a15d79aca3a705ee6916a68db57b7e6#8c63bff68a15d79aca3a705ee6916a68db57b7e6" +source = "git+https://github.com/stellar/rs-soroban-env?rev=91f44778389490ad863d61a8a90ac9875ba6d8fd#91f44778389490ad863d61a8a90ac9875ba6d8fd" dependencies = [ "soroban-env-common", "static_assertions", @@ -2544,7 +2544,7 @@ dependencies = [ [[package]] name = "soroban-env-host" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-env?rev=8c63bff68a15d79aca3a705ee6916a68db57b7e6#8c63bff68a15d79aca3a705ee6916a68db57b7e6" +source = "git+https://github.com/stellar/rs-soroban-env?rev=91f44778389490ad863d61a8a90ac9875ba6d8fd#91f44778389490ad863d61a8a90ac9875ba6d8fd" dependencies = [ "backtrace", "ed25519-dalek 2.0.0", @@ -2567,7 +2567,7 @@ dependencies = [ [[package]] name = "soroban-env-macros" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-env?rev=8c63bff68a15d79aca3a705ee6916a68db57b7e6#8c63bff68a15d79aca3a705ee6916a68db57b7e6" +source = "git+https://github.com/stellar/rs-soroban-env?rev=91f44778389490ad863d61a8a90ac9875ba6d8fd#91f44778389490ad863d61a8a90ac9875ba6d8fd" dependencies = [ "itertools 0.10.5", "proc-macro2", @@ -2585,7 +2585,7 @@ version = "20.0.0-rc4" [[package]] name = "soroban-ledger-snapshot" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=0992413f9b05e5bfb1f872bce99e89d9129b2e61#0992413f9b05e5bfb1f872bce99e89d9129b2e61" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=729ed3ac5fe8600a3245d5816eadd3c95ab2eb54#729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" dependencies = [ "serde", "serde_json", @@ -2597,7 +2597,7 @@ dependencies = [ [[package]] name = "soroban-native-sdk-macros" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-env?rev=8c63bff68a15d79aca3a705ee6916a68db57b7e6#8c63bff68a15d79aca3a705ee6916a68db57b7e6" +source = "git+https://github.com/stellar/rs-soroban-env?rev=91f44778389490ad863d61a8a90ac9875ba6d8fd#91f44778389490ad863d61a8a90ac9875ba6d8fd" dependencies = [ "itertools 0.10.5", "proc-macro2", @@ -2608,7 +2608,7 @@ dependencies = [ [[package]] name = "soroban-sdk" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=0992413f9b05e5bfb1f872bce99e89d9129b2e61#0992413f9b05e5bfb1f872bce99e89d9129b2e61" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=729ed3ac5fe8600a3245d5816eadd3c95ab2eb54#729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" dependencies = [ "arbitrary", "bytes-lit", @@ -2625,7 +2625,7 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=0992413f9b05e5bfb1f872bce99e89d9129b2e61#0992413f9b05e5bfb1f872bce99e89d9129b2e61" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=729ed3ac5fe8600a3245d5816eadd3c95ab2eb54#729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" dependencies = [ "crate-git-revision 0.0.6", "darling", @@ -2644,7 +2644,7 @@ dependencies = [ [[package]] name = "soroban-spec" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=0992413f9b05e5bfb1f872bce99e89d9129b2e61#0992413f9b05e5bfb1f872bce99e89d9129b2e61" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=729ed3ac5fe8600a3245d5816eadd3c95ab2eb54#729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" dependencies = [ "base64 0.13.1", "stellar-xdr", @@ -2669,7 +2669,7 @@ dependencies = [ [[package]] name = "soroban-spec-rust" version = "20.0.0-rc2" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=0992413f9b05e5bfb1f872bce99e89d9129b2e61#0992413f9b05e5bfb1f872bce99e89d9129b2e61" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=729ed3ac5fe8600a3245d5816eadd3c95ab2eb54#729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" dependencies = [ "prettyplease", "proc-macro2", @@ -2805,7 +2805,7 @@ dependencies = [ [[package]] name = "stellar-xdr" version = "20.0.0-rc1" -source = "git+https://github.com/stellar/rs-stellar-xdr?rev=d5ce0c9e7aa83461773a6e81662067f35d39e4c1#d5ce0c9e7aa83461773a6e81662067f35d39e4c1" +source = "git+https://github.com/stellar/rs-stellar-xdr?rev=9c97e4fa909a0b6455547a4f4a95800696b2a69a#9c97e4fa909a0b6455547a4f4a95800696b2a69a" dependencies = [ "arbitrary", "base64 0.13.1", diff --git a/Cargo.toml b/Cargo.toml index 6747e6aeb..99889cb26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,18 +16,18 @@ version = "20.0.0-rc4" [workspace.dependencies.soroban-env-host] version = "20.0.0-rc2" git = "https://github.com/stellar/rs-soroban-env" -rev = "8c63bff68a15d79aca3a705ee6916a68db57b7e6" +rev = "91f44778389490ad863d61a8a90ac9875ba6d8fd" [workspace.dependencies.soroban-spec] version = "20.0.0-rc2" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "0992413f9b05e5bfb1f872bce99e89d9129b2e61" +rev = "729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" # path = "../rs-soroban-sdk/soroban-spec" [workspace.dependencies.soroban-spec-rust] version = "20.0.0-rc2" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "0992413f9b05e5bfb1f872bce99e89d9129b2e61" +rev = "729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" # path = "../rs-soroban-sdk/soroban-spec-rust" [workspace.dependencies.soroban-spec-json] @@ -45,12 +45,12 @@ path = "./cmd/crates/soroban-spec-tools" [workspace.dependencies.soroban-sdk] version = "20.0.0-rc2" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "0992413f9b05e5bfb1f872bce99e89d9129b2e61" +rev = "729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" [workspace.dependencies.soroban-ledger-snapshot] version = "20.0.0-rc2" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "0992413f9b05e5bfb1f872bce99e89d9129b2e61" +rev = "729ed3ac5fe8600a3245d5816eadd3c95ab2eb54" [workspace.dependencies.soroban-cli] version = "20.0.0-rc4" @@ -59,7 +59,7 @@ path = "cmd/soroban-cli" [workspace.dependencies.stellar-xdr] version = "20.0.0-rc1" git = "https://github.com/stellar/rs-stellar-xdr" -rev = "d5ce0c9e7aa83461773a6e81662067f35d39e4c1" +rev = "9c97e4fa909a0b6455547a4f4a95800696b2a69a" default-features = false [workspace.dependencies] diff --git a/cmd/soroban-rpc/internal/test/docker-compose.yml b/cmd/soroban-rpc/internal/test/docker-compose.yml index 7d8fd89ea..4f7949002 100644 --- a/cmd/soroban-rpc/internal/test/docker-compose.yml +++ b/cmd/soroban-rpc/internal/test/docker-compose.yml @@ -15,7 +15,7 @@ services: # Note: Please keep the image pinned to an immutable tag matching the Captive Core version. # This avoids implicit updates which break compatibility between # the Core container and captive core. - image: ${CORE_IMAGE:-stellar/stellar-core:19.13.1-1481.3acf6dd26.focal} + image: ${CORE_IMAGE:-stellar/stellar-core:19.14.1-1529.fcbbad4ce.focal} depends_on: - core-postgres restart: on-failure diff --git a/go.mod b/go.mod index fe3964128..fa812f3d1 100644 --- a/go.mod +++ b/go.mod @@ -16,14 +16,12 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stellar/go v0.0.0-20230913112642-b19a4ceec268 + github.com/stellar/go v0.0.0-20231016131404-dc8a5c304cce github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.12.0 gotest.tools/v3 v3.5.0 ) -require github.com/xdrpp/goxdr v0.1.1 // indirect - require ( github.com/BurntSushi/toml v0.3.1 // indirect github.com/Microsoft/go-winio v0.4.16 // indirect @@ -70,9 +68,10 @@ require ( github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.0.0 // indirect github.com/spf13/viper v1.3.2 // indirect - github.com/stellar/go-xdr v0.0.0-20211103144802-8017fc4bdfee // indirect + github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect + github.com/xdrpp/goxdr v0.1.1 // indirect golang.org/x/crypto v0.12.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/net v0.14.0 // indirect diff --git a/go.sum b/go.sum index cd64f6830..141c4df46 100644 --- a/go.sum +++ b/go.sum @@ -189,10 +189,10 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/stellar/go v0.0.0-20230913112642-b19a4ceec268 h1:mmweoXJEkZKyoUkvL+nS1ecwlHclHxGGZmhUsCnZpuE= -github.com/stellar/go v0.0.0-20230913112642-b19a4ceec268/go.mod h1:5/qoLl0pexA5OPi0BZvDsOc3532CJlHuRg1dnBxbsGg= -github.com/stellar/go-xdr v0.0.0-20211103144802-8017fc4bdfee h1:fbVs0xmXpBvVS4GBeiRmAE3Le70ofAqFMch1GTiq/e8= -github.com/stellar/go-xdr v0.0.0-20211103144802-8017fc4bdfee/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= +github.com/stellar/go v0.0.0-20231016131404-dc8a5c304cce h1:p+JZNTwrdHMjuaGMzq3jlue4W0w+G3KC5AGp46O3ymQ= +github.com/stellar/go v0.0.0-20231016131404-dc8a5c304cce/go.mod h1:g78pyZyDFnKMJUaBIXxH7xyQ7PdDrvrJTFCxdGMMb3c= +github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206 h1:UFuvvpbWL8+jqO1QmKYWSVhiMp4MRiIFd8/zQlUINH0= +github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= From f4b827b78a3c2c4bc19d8379a933181e6e51cacf Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 16 Oct 2023 16:30:11 +0200 Subject: [PATCH 02/14] Update soroban-rpc --- cmd/soroban-rpc/internal/db/ledger_test.go | 4 +- cmd/soroban-rpc/internal/db/ledgerentry.go | 44 +++--- .../internal/db/ledgerentry_test.go | 45 +++--- cmd/soroban-rpc/internal/ingest/service.go | 2 +- .../internal/ingest/service_test.go | 4 +- .../internal/methods/get_events_test.go | 4 +- .../methods/get_latest_ledger_test.go | 4 +- .../internal/methods/get_ledger_entries.go | 19 ++- .../internal/methods/get_ledger_entry.go | 12 +- .../internal/methods/get_transaction_test.go | 13 +- .../internal/methods/simulate_transaction.go | 8 +- .../internal/preflight/preflight.go | 29 ++-- .../internal/preflight/preflight_test.go | 34 ++-- .../test/captive-core-integration-tests.cfg | 4 +- cmd/soroban-rpc/internal/test/cli_test.go | 94 ++++++----- .../test/simulate_transaction_test.go | 93 ++++------- .../test/stellar-core-integration-tests.cfg | 4 +- .../transactions/transactions_test.go | 7 +- cmd/soroban-rpc/lib/preflight.h | 16 +- cmd/soroban-rpc/lib/preflight/src/fees.rs | 148 ++++++++---------- .../lib/preflight/src/ledger_storage.rs | 119 +++++++------- cmd/soroban-rpc/lib/preflight/src/lib.rs | 22 +-- .../lib/preflight/src/preflight.rs | 16 +- .../lib/preflight/src/state_expiration.rs | 70 --------- .../lib/preflight/src/state_ttl.rs | 67 ++++++++ go.mod | 2 +- go.sum | 4 +- 27 files changed, 425 insertions(+), 463 deletions(-) delete mode 100644 cmd/soroban-rpc/lib/preflight/src/state_expiration.rs create mode 100644 cmd/soroban-rpc/lib/preflight/src/state_ttl.rs diff --git a/cmd/soroban-rpc/internal/db/ledger_test.go b/cmd/soroban-rpc/internal/db/ledger_test.go index 362f33653..bbbfdbee8 100644 --- a/cmd/soroban-rpc/internal/db/ledger_test.go +++ b/cmd/soroban-rpc/internal/db/ledger_test.go @@ -11,8 +11,8 @@ import ( func createLedger(ledgerSequence uint32) xdr.LedgerCloseMeta { return xdr.LedgerCloseMeta{ - V: 2, - V2: &xdr.LedgerCloseMetaV2{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{ Hash: xdr.Hash{}, Header: xdr.LedgerHeader{ diff --git a/cmd/soroban-rpc/internal/db/ledgerentry.go b/cmd/soroban-rpc/internal/db/ledgerentry.go index 87fbd75dd..2e22cbc7a 100644 --- a/cmd/soroban-rpc/internal/db/ledgerentry.go +++ b/cmd/soroban-rpc/internal/db/ledgerentry.go @@ -24,9 +24,9 @@ type LedgerEntryReader interface { } type LedgerKeyAndEntry struct { - Key xdr.LedgerKey - Entry xdr.LedgerEntry - ExpirationLedgerSeq *uint32 // optional expiration ledger seq, when applicable. + Key xdr.LedgerKey + Entry xdr.LedgerEntry + LiveUntilLedgerSeq *uint32 // optional live-until ledger seq, when applicable. } type LedgerEntryReadTx interface { @@ -228,14 +228,14 @@ func GetLedgerEntry(tx LedgerEntryReadTx, key xdr.LedgerKey) (bool, xdr.LedgerEn return false, xdr.LedgerEntry{}, nil, nil case 1: // expected length - return true, keyEntries[0].Entry, keyEntries[0].ExpirationLedgerSeq, nil + return true, keyEntries[0].Entry, keyEntries[0].LiveUntilLedgerSeq, nil default: return false, xdr.LedgerEntry{}, nil, fmt.Errorf("multiple entries (%d) for key %v", len(keyEntries), key) } } -// isExpirableKey check to see if the key type is expected to be accompanied by a LedgerExpirationEntry -func isExpirableKey(key xdr.LedgerKey) bool { +// hasTTLKey check to see if the key type is expected to be accompanied by a LedgerTTLEntry +func hasTTLKey(key xdr.LedgerKey) bool { switch key.Type { case xdr.LedgerEntryTypeContractData: return true @@ -246,23 +246,23 @@ func isExpirableKey(key xdr.LedgerKey) bool { return false } -func entryKeyToExpirationEntryKey(key xdr.LedgerKey) (xdr.LedgerKey, error) { +func entryKeyToTTLEntryKey(key xdr.LedgerKey) (xdr.LedgerKey, error) { buf, err := key.MarshalBinary() if err != nil { return xdr.LedgerKey{}, err } - var expirationEntry xdr.LedgerKey - err = expirationEntry.SetExpiration(xdr.Hash(sha256.Sum256(buf))) + var ttlEntry xdr.LedgerKey + err = ttlEntry.SetTtl(sha256.Sum256(buf)) if err != nil { return xdr.LedgerKey{}, err } - return expirationEntry, nil + return ttlEntry, nil } func (l *ledgerEntryReadTx) GetLedgerEntries(keys ...xdr.LedgerKey) ([]LedgerKeyAndEntry, error) { encodedKeys := make([]string, len(keys), 2*len(keys)) encodedKeyToKey := make(map[string]xdr.LedgerKey, len(keys)) - encodedKeyToEncodedExpirationLedgerKey := make(map[string]string, len(keys)) + encodedKeyToEncodedTTLLedgerKey := make(map[string]string, len(keys)) for _, k := range keys { encodedKey, err := encodeLedgerKey(l.buffer, k) if err != nil { @@ -270,19 +270,19 @@ func (l *ledgerEntryReadTx) GetLedgerEntries(keys ...xdr.LedgerKey) ([]LedgerKey } encodedKeys = append(encodedKeys, encodedKey) encodedKeyToKey[encodedKey] = k - if !isExpirableKey(k) { + if !hasTTLKey(k) { continue } - expirationEntryKey, err := entryKeyToExpirationEntryKey(k) + ttlEntryKey, err := entryKeyToTTLEntryKey(k) if err != nil { return nil, err } - encodedExpirationKey, err := encodeLedgerKey(l.buffer, expirationEntryKey) + encodedTTLKey, err := encodeLedgerKey(l.buffer, ttlEntryKey) if err != nil { return nil, err } - encodedKeyToEncodedExpirationLedgerKey[encodedKey] = encodedExpirationKey - encodedKeys = append(encodedKeys, encodedExpirationKey) + encodedKeyToEncodedTTLLedgerKey[encodedKey] = encodedTTLKey + encodedKeys = append(encodedKeys, encodedTTLKey) } rawResult, err := l.getRawLedgerEntries(encodedKeys...) @@ -300,22 +300,22 @@ func (l *ledgerEntryReadTx) GetLedgerEntries(keys ...xdr.LedgerKey) ([]LedgerKey if err := xdr.SafeUnmarshal([]byte(encodedEntry), &entry); err != nil { return nil, errors.Wrap(err, "cannot decode ledger entry from DB") } - encodedExpKey, has := encodedKeyToEncodedExpirationLedgerKey[encodedKey] + encodedExpKey, has := encodedKeyToEncodedTTLLedgerKey[encodedKey] if !has { result = append(result, LedgerKeyAndEntry{key, entry, nil}) continue } encodedExpEntry, ok := rawResult[encodedExpKey] if !ok { - // missing expiration key. this should no happen. - return nil, errors.New("missing expiration key entry") + // missing ttl key. This should not happen. + return nil, errors.New("missing ttl key entry") } var expEntry xdr.LedgerEntry if err := xdr.SafeUnmarshal([]byte(encodedExpEntry), &expEntry); err != nil { - return nil, errors.Wrap(err, "cannot decode expiration ledger entry from DB") + return nil, errors.Wrap(err, "cannot decode TTL ledger entry from DB") } - expSeq := uint32(expEntry.Data.Expiration.ExpirationLedgerSeq) - result = append(result, LedgerKeyAndEntry{key, entry, &expSeq}) + liveUntilSeq := uint32(expEntry.Data.Ttl.LiveUntilLedgerSeq) + result = append(result, LedgerKeyAndEntry{key, entry, &liveUntilSeq}) } return result, nil diff --git a/cmd/soroban-rpc/internal/db/ledgerentry_test.go b/cmd/soroban-rpc/internal/db/ledgerentry_test.go index 5da7791ef..2e6b0012c 100644 --- a/cmd/soroban-rpc/internal/db/ledgerentry_test.go +++ b/cmd/soroban-rpc/internal/db/ledgerentry_test.go @@ -75,19 +75,19 @@ func TestGoldenPath(t *testing.T) { key, entry := getContractDataLedgerEntry(t, data) assert.NoError(t, writer.UpsertLedgerEntry(entry)) - expLedgerKey, err := entryKeyToExpirationEntryKey(key) + expLedgerKey, err := entryKeyToTTLEntryKey(key) assert.NoError(t, err) - expLegerEntry := getExpirationLedgerEntry(expLedgerKey) + expLegerEntry := getTTLLedgerEntry(expLedgerKey) assert.NoError(t, writer.UpsertLedgerEntry(expLegerEntry)) ledgerSequence := uint32(23) assert.NoError(t, tx.Commit(ledgerSequence)) - present, obtainedEntry, obtainedLedgerSequence, expSeq := getLedgerEntryAndLatestLedgerSequence(t, db, key) + present, obtainedEntry, obtainedLedgerSequence, liveUntilSeq := getLedgerEntryAndLatestLedgerSequence(t, db, key) assert.True(t, present) assert.Equal(t, ledgerSequence, obtainedLedgerSequence) - require.NotNil(t, expSeq) - assert.Equal(t, uint32(expLegerEntry.Data.Expiration.ExpirationLedgerSeq), *expSeq) + require.NotNil(t, liveUntilSeq) + assert.Equal(t, uint32(expLegerEntry.Data.Ttl.LiveUntilLedgerSeq), *liveUntilSeq) assert.Equal(t, obtainedEntry.Data.Type, xdr.LedgerEntryTypeContractData) assert.Equal(t, xdr.Hash{0xca, 0xfe}, *obtainedEntry.Data.ContractData.Contract.ContractId) assert.Equal(t, six, *obtainedEntry.Data.ContractData.Val.U32) @@ -108,9 +108,9 @@ func TestGoldenPath(t *testing.T) { ledgerSequence = uint32(24) assert.NoError(t, tx.Commit(ledgerSequence)) - present, obtainedEntry, obtainedLedgerSequence, expSeq = getLedgerEntryAndLatestLedgerSequence(t, db, key) + present, obtainedEntry, obtainedLedgerSequence, liveUntilSeq = getLedgerEntryAndLatestLedgerSequence(t, db, key) assert.True(t, present) - require.NotNil(t, expSeq) + require.NotNil(t, liveUntilSeq) assert.Equal(t, ledgerSequence, obtainedLedgerSequence) assert.Equal(t, eight, *obtainedEntry.Data.ContractData.Val.U32) @@ -124,9 +124,9 @@ func TestGoldenPath(t *testing.T) { ledgerSequence = uint32(25) assert.NoError(t, tx.Commit(ledgerSequence)) - present, _, obtainedLedgerSequence, expSeq = getLedgerEntryAndLatestLedgerSequence(t, db, key) + present, _, obtainedLedgerSequence, liveUntilSeq = getLedgerEntryAndLatestLedgerSequence(t, db, key) assert.False(t, present) - assert.Nil(t, expSeq) + assert.Nil(t, liveUntilSeq) assert.Equal(t, ledgerSequence, obtainedLedgerSequence) obtainedLedgerSequence, err = NewLedgerEntryReader(db).GetLatestLedgerSequence(context.Background()) @@ -192,11 +192,11 @@ func getContractDataLedgerEntry(t require.TestingT, data xdr.ContractDataEntry) return key, entry } -func getExpirationLedgerEntry(key xdr.LedgerKey) xdr.LedgerEntry { +func getTTLLedgerEntry(key xdr.LedgerKey) xdr.LedgerEntry { var expLegerEntry xdr.LedgerEntry - expLegerEntry.Data.Expiration = &xdr.ExpirationEntry{ - KeyHash: key.Expiration.KeyHash, - ExpirationLedgerSeq: 100, + expLegerEntry.Data.Ttl = &xdr.TtlEntry{ + KeyHash: key.Ttl.KeyHash, + LiveUntilLedgerSeq: 100, } expLegerEntry.Data.Type = key.Type return expLegerEntry @@ -235,9 +235,9 @@ func TestReadTxsDuringWriteTx(t *testing.T) { key, entry := getContractDataLedgerEntry(t, data) assert.NoError(t, writer.UpsertLedgerEntry(entry)) - expLedgerKey, err := entryKeyToExpirationEntryKey(key) + expLedgerKey, err := entryKeyToTTLEntryKey(key) assert.NoError(t, err) - expLegerEntry := getExpirationLedgerEntry(expLedgerKey) + expLegerEntry := getTTLLedgerEntry(expLedgerKey) assert.NoError(t, writer.UpsertLedgerEntry(expLegerEntry)) // Before committing the changes, make sure multiple concurrent transactions can query the DB @@ -321,9 +321,9 @@ func TestWriteTxsDuringReadTxs(t *testing.T) { key, entry := getContractDataLedgerEntry(t, data) assert.NoError(t, writer.UpsertLedgerEntry(entry)) - expLedgerKey, err := entryKeyToExpirationEntryKey(key) + expLedgerKey, err := entryKeyToTTLEntryKey(key) assert.NoError(t, err) - expLegerEntry := getExpirationLedgerEntry(expLedgerKey) + expLegerEntry := getTTLLedgerEntry(expLedgerKey) assert.NoError(t, writer.UpsertLedgerEntry(expLegerEntry)) // Third read transaction, after the first insert has happened in the write transaction @@ -404,9 +404,9 @@ func TestConcurrentReadersAndWriter(t *testing.T) { for i := 0; i < 200; i++ { key, entry := getContractDataLedgerEntry(t, data(i)) assert.NoError(t, writer.UpsertLedgerEntry(entry)) - expLedgerKey, err := entryKeyToExpirationEntryKey(key) + expLedgerKey, err := entryKeyToTTLEntryKey(key) assert.NoError(t, err) - expLegerEntry := getExpirationLedgerEntry(expLedgerKey) + expLegerEntry := getTTLLedgerEntry(expLedgerKey) assert.NoError(t, writer.UpsertLedgerEntry(expLegerEntry)) } assert.NoError(t, tx.Commit(ledgerSequence)) @@ -480,7 +480,7 @@ forloop: } -func benchmarkLedgerEntry(b *testing.B, cached bool, includeExpired bool) { +func benchmarkLedgerEntry(b *testing.B, cached bool) { db := NewTestDB(b) keyUint32 := xdr.Uint32(0) data := xdr.ContractDataEntry{ @@ -528,9 +528,8 @@ func benchmarkLedgerEntry(b *testing.B, cached bool, includeExpired bool) { } func BenchmarkGetLedgerEntry(b *testing.B) { - b.Run("With cache, include expired", func(b *testing.B) { benchmarkLedgerEntry(b, true, true) }) - b.Run("With cache, exclude expired", func(b *testing.B) { benchmarkLedgerEntry(b, true, false) }) - b.Run("Without cache, exclude expired", func(b *testing.B) { benchmarkLedgerEntry(b, false, false) }) + b.Run("With cache", func(b *testing.B) { benchmarkLedgerEntry(b, true) }) + b.Run("Without cache", func(b *testing.B) { benchmarkLedgerEntry(b, false) }) } func BenchmarkLedgerUpdate(b *testing.B) { diff --git a/cmd/soroban-rpc/internal/ingest/service.go b/cmd/soroban-rpc/internal/ingest/service.go index fab1cd2d7..744e515f9 100644 --- a/cmd/soroban-rpc/internal/ingest/service.go +++ b/cmd/soroban-rpc/internal/ingest/service.go @@ -258,7 +258,7 @@ func (s *Service) ingest(ctx context.Context, sequence uint32) error { } // EvictedTemporaryLedgerKeys will include both temporary ledger keys which - // have been evicted and their corresponding expiration ledger entries + // have been evicted and their corresponding ttl ledger entries evictedTempLedgerKeys, err := ledgerCloseMeta.EvictedTemporaryLedgerKeys() if err != nil { return err diff --git a/cmd/soroban-rpc/internal/ingest/service_test.go b/cmd/soroban-rpc/internal/ingest/service_test.go index 9c76a81fd..4993d326f 100644 --- a/cmd/soroban-rpc/internal/ingest/service_test.go +++ b/cmd/soroban-rpc/internal/ingest/service_test.go @@ -176,8 +176,8 @@ func TestIngestion(t *testing.T) { }, } ledger := xdr.LedgerCloseMeta{ - V: 2, - V2: &xdr.LedgerCloseMetaV2{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{Header: xdr.LedgerHeader{LedgerVersion: 10}}, TxSet: xdr.GeneralizedTransactionSet{ V: 1, diff --git a/cmd/soroban-rpc/internal/methods/get_events_test.go b/cmd/soroban-rpc/internal/methods/get_events_test.go index 86c2086d4..5a1ba6388 100644 --- a/cmd/soroban-rpc/internal/methods/get_events_test.go +++ b/cmd/soroban-rpc/internal/methods/get_events_test.go @@ -1121,8 +1121,8 @@ func ledgerCloseMetaWithEvents(sequence uint32, closeTimestamp int64, txMeta ... } return xdr.LedgerCloseMeta{ - V: 2, - V2: &xdr.LedgerCloseMetaV2{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{ Hash: xdr.Hash{}, Header: xdr.LedgerHeader{ diff --git a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go index 124ec6a33..474b3b8da 100644 --- a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go +++ b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go @@ -60,8 +60,8 @@ func (ledgerReader *ConstantLedgerReader) StreamAllLedgers(ctx context.Context, func createLedger(ledgerSequence uint32, protocolVersion uint32, hash byte) xdr.LedgerCloseMeta { return xdr.LedgerCloseMeta{ - V: 2, - V2: &xdr.LedgerCloseMetaV2{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{ Hash: xdr.Hash{hash}, Header: xdr.LedgerHeader{ diff --git a/cmd/soroban-rpc/internal/methods/get_ledger_entries.go b/cmd/soroban-rpc/internal/methods/get_ledger_entries.go index 00c3ad22a..d37347ef5 100644 --- a/cmd/soroban-rpc/internal/methods/get_ledger_entries.go +++ b/cmd/soroban-rpc/internal/methods/get_ledger_entries.go @@ -7,14 +7,13 @@ import ( "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/handler" "github.com/stellar/go/gxdr" - "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" "github.com/stellar/soroban-tools/cmd/soroban-rpc/internal/db" ) -var ErrLedgerExpirationEntriesCannotBeQueriedDirectly = "ledger expiration entries cannot be queried directly" +var ErrLedgerTtlEntriesCannotBeQueriedDirectly = "ledger ttl entries cannot be queried directly" type GetLedgerEntriesRequest struct { Keys []string `json:"keys"` @@ -27,8 +26,8 @@ type LedgerEntryResult struct { XDR string `json:"xdr"` // Last modified ledger for this entry. LastModifiedLedger int64 `json:"lastModifiedLedgerSeq,string"` - // The expiration ledger, available for entries that have expiration ledgers. - ExpirationLedger *uint32 `json:"expirationLedgerSeq,string,omitempty"` + // The ledger sequence until the entry is live, available for entries that have associated ttl ledger entries. + LiveUntilLedgerSeq *uint32 `json:"liveUntilLedgerSeqLedgerSeq,string,omitempty"` } type GetLedgerEntriesResponse struct { @@ -68,12 +67,12 @@ func NewGetLedgerEntriesHandler(logger *log.Entry, ledgerEntryReader db.LedgerEn Message: fmt.Sprintf("cannot unmarshal key value %s at index %d", requestKey, i), } } - if ledgerKey.Type == xdr.LedgerEntryTypeExpiration { + if ledgerKey.Type == xdr.LedgerEntryTypeTtl { logger.WithField("request", request). - Infof("could not provide ledger expiration entry %s at index %d from getLedgerEntries request", requestKey, i) + Infof("could not provide ledger ttl entry %s at index %d from getLedgerEntries request", requestKey, i) return GetLedgerEntriesResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, - Message: ErrLedgerExpirationEntriesCannotBeQueriedDirectly, + Message: ErrLedgerTtlEntriesCannotBeQueriedDirectly, } } ledgerKeys = append(ledgerKeys, ledgerKey) @@ -102,10 +101,10 @@ func NewGetLedgerEntriesHandler(logger *log.Entry, ledgerEntryReader db.LedgerEn ledgerKeysAndEntries, err := tx.GetLedgerEntries(ledgerKeys...) if err != nil { logger.WithError(err).WithField("request", request). - Info("could not obtain ledger entryies from storage") + Info("could not obtain ledger entries from storage") return GetLedgerEntriesResponse{}, &jrpc2.Error{ Code: jrpc2.InternalError, - Message: "could not obtain ledger entryies from storage", + Message: "could not obtain ledger entries from storage", } } @@ -124,7 +123,7 @@ func NewGetLedgerEntriesHandler(logger *log.Entry, ledgerEntryReader db.LedgerEn Key: request.Keys[i], XDR: ledgerXDR, LastModifiedLedger: int64(ledgerKeyAndEntry.Entry.LastModifiedLedgerSeq), - ExpirationLedger: ledgerKeyAndEntry.ExpirationLedgerSeq, + LiveUntilLedgerSeq: ledgerKeyAndEntry.LiveUntilLedgerSeq, }) } diff --git a/cmd/soroban-rpc/internal/methods/get_ledger_entry.go b/cmd/soroban-rpc/internal/methods/get_ledger_entry.go index 1da93f9dd..614c6e634 100644 --- a/cmd/soroban-rpc/internal/methods/get_ledger_entry.go +++ b/cmd/soroban-rpc/internal/methods/get_ledger_entry.go @@ -26,8 +26,8 @@ type GetLedgerEntryResponse struct { XDR string `json:"xdr"` LastModifiedLedger int64 `json:"lastModifiedLedgerSeq,string"` LatestLedger int64 `json:"latestLedger,string"` - // The expiration ledger, available for entries that have expiration ledgers. - ExpirationLedger *uint32 `json:"expirationLedgerSeq,string,omitempty"` + // The ledger sequence until the entry is live, available for entries that have associated ttl ledger entries. + LiveUntilLedgerSeq *uint32 `json:"LiveUntilLedgerSeq,string,omitempty"` } var invalidLedgerKeyXdrError = &jrpc2.Error{ @@ -52,10 +52,10 @@ func NewGetLedgerEntryHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntr return GetLedgerEntryResponse{}, invalidLedgerKeyXdrError } - if key.Type == xdr.LedgerEntryTypeExpiration { + if key.Type == xdr.LedgerEntryTypeTtl { return GetLedgerEntryResponse{}, &jrpc2.Error{ Code: jrpc2.InvalidParams, - Message: ErrLedgerExpirationEntriesCannotBeQueriedDirectly, + Message: ErrLedgerTtlEntriesCannotBeQueriedDirectly, } } @@ -78,7 +78,7 @@ func NewGetLedgerEntryHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntr } } - present, ledgerEntry, ledgerExpirationSeq, err := db.GetLedgerEntry(tx, key) + present, ledgerEntry, liveUntilLedgerSeq, err := db.GetLedgerEntry(tx, key) if err != nil { logger.WithError(err).WithField("request", request). Info("could not obtain ledger entry from storage") @@ -98,7 +98,7 @@ func NewGetLedgerEntryHandler(logger *log.Entry, ledgerEntryReader db.LedgerEntr response := GetLedgerEntryResponse{ LastModifiedLedger: int64(ledgerEntry.LastModifiedLedgerSeq), LatestLedger: int64(latestLedger), - ExpirationLedger: ledgerExpirationSeq, + LiveUntilLedgerSeq: liveUntilLedgerSeq, } if response.XDR, err = xdr.MarshalBase64(ledgerEntry.Data); err != nil { logger.WithError(err).WithField("request", request). diff --git a/cmd/soroban-rpc/internal/methods/get_transaction_test.go b/cmd/soroban-rpc/internal/methods/get_transaction_test.go index e0c3e5721..1b30cb762 100644 --- a/cmd/soroban-rpc/internal/methods/get_transaction_test.go +++ b/cmd/soroban-rpc/internal/methods/get_transaction_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stellar/go/network" + "github.com/stellar/soroban-tools/cmd/soroban-rpc/internal/daemon/interfaces" "github.com/stellar/soroban-tools/cmd/soroban-rpc/internal/transactions" ) @@ -70,8 +71,8 @@ func txMeta(acctSeq uint32, successful bool) xdr.LedgerCloseMeta { }, } return xdr.LedgerCloseMeta{ - V: 2, - V2: &xdr.LedgerCloseMetaV2{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ ScpValue: xdr.StellarValue{ @@ -134,11 +135,11 @@ func TestGetTransaction(t *testing.T) { tx, err = GetTransaction(store, GetTransactionRequest{hash}) assert.NoError(t, err) - expectedTxResult, err := xdr.MarshalBase64(meta.V2.TxProcessing[0].Result.Result) + expectedTxResult, err := xdr.MarshalBase64(meta.V1.TxProcessing[0].Result.Result) assert.NoError(t, err) expectedEnvelope, err := xdr.MarshalBase64(txEnvelope(1)) assert.NoError(t, err) - expectedTxMeta, err := xdr.MarshalBase64(meta.V2.TxProcessing[0].TxApplyProcessing) + expectedTxMeta, err := xdr.MarshalBase64(meta.V1.TxProcessing[0].TxApplyProcessing) assert.NoError(t, err) assert.Equal(t, GetTransactionResponse{ Status: TransactionStatusSuccess, @@ -182,11 +183,11 @@ func TestGetTransaction(t *testing.T) { xdrHash = txHash(2) hash = hex.EncodeToString(xdrHash[:]) - expectedTxResult, err = xdr.MarshalBase64(meta.V2.TxProcessing[0].Result.Result) + expectedTxResult, err = xdr.MarshalBase64(meta.V1.TxProcessing[0].Result.Result) assert.NoError(t, err) expectedEnvelope, err = xdr.MarshalBase64(txEnvelope(2)) assert.NoError(t, err) - expectedTxMeta, err = xdr.MarshalBase64(meta.V2.TxProcessing[0].TxApplyProcessing) + expectedTxMeta, err = xdr.MarshalBase64(meta.V1.TxProcessing[0].TxApplyProcessing) assert.NoError(t, err) tx, err = GetTransaction(store, GetTransactionRequest{hash}) diff --git a/cmd/soroban-rpc/internal/methods/simulate_transaction.go b/cmd/soroban-rpc/internal/methods/simulate_transaction.go index 638a6a7b5..cd6a8bae1 100644 --- a/cmd/soroban-rpc/internal/methods/simulate_transaction.go +++ b/cmd/soroban-rpc/internal/methods/simulate_transaction.go @@ -86,10 +86,10 @@ func NewSimulateTransactionHandler(logger *log.Entry, ledgerEntryReader db.Ledge footprint := xdr.LedgerFootprint{} switch op.Body.Type { case xdr.OperationTypeInvokeHostFunction: - case xdr.OperationTypeBumpFootprintExpiration, xdr.OperationTypeRestoreFootprint: + case xdr.OperationTypeExtendFootprintTtl, xdr.OperationTypeRestoreFootprint: if txEnvelope.Type != xdr.EnvelopeTypeEnvelopeTypeTx && txEnvelope.V1.Tx.Ext.V != 1 { return SimulateTransactionResponse{ - Error: "To perform a SimulateTransaction for BumpFootprintExpiration or RestoreFootprint operations, SorobanTransactionData must be provided", + Error: "To perform a SimulateTransaction for ExtendFootprintTtl or RestoreFootprint operations, SorobanTransactionData must be provided", } } footprint = txEnvelope.V1.Tx.Ext.SorobanData.Resources.Footprint @@ -177,8 +177,8 @@ func getBucketListSize(ctx context.Context, ledgerReader db.LedgerReader, latest if !ok { return 0, fmt.Errorf("missing meta for latest ledger (%d)", latestLedger) } - if closeMeta.V != 2 { + if closeMeta.V != 1 { return 0, fmt.Errorf("latest ledger (%d) meta has unexpected verion (%d)", latestLedger, closeMeta.V) } - return uint64(closeMeta.V2.TotalByteSizeOfBucketList), nil + return uint64(closeMeta.V1.TotalByteSizeOfBucketList), nil } diff --git a/cmd/soroban-rpc/internal/preflight/preflight.go b/cmd/soroban-rpc/internal/preflight/preflight.go index dc36810c8..442ea5da1 100644 --- a/cmd/soroban-rpc/internal/preflight/preflight.go +++ b/cmd/soroban-rpc/internal/preflight/preflight.go @@ -46,7 +46,7 @@ func SnapshotSourceGet(handle C.uintptr_t, cLedgerKey C.xdr_t) C.xdr_t { if err := xdr.SafeUnmarshal(ledgerKeyXDR, &ledgerKey); err != nil { panic(err) } - // TODO : the expiration sequence here is being ignored for now; it should be passed downstream. + // TODO : the live-until sequence here is being ignored for now; it should be passed downstream. present, entry, _, err := db.GetLedgerEntry(h.readTx, ledgerKey) if err != nil { h.logger.WithError(err).Error("SnapshotSourceGet(): GetLedgerEntry() failed") @@ -118,14 +118,14 @@ func GetPreflight(ctx context.Context, params PreflightParameters) (Preflight, e switch params.OpBody.Type { case xdr.OperationTypeInvokeHostFunction: return getInvokeHostFunctionPreflight(params) - case xdr.OperationTypeBumpFootprintExpiration, xdr.OperationTypeRestoreFootprint: - return getFootprintExpirationPreflight(params) + case xdr.OperationTypeExtendFootprintTtl, xdr.OperationTypeRestoreFootprint: + return getFootprintTtlPreflight(params) default: return Preflight{}, fmt.Errorf("unsupported operation type: %s", params.OpBody.Type.String()) } } -func getFootprintExpirationPreflight(params PreflightParameters) (Preflight, error) { +func getFootprintTtlPreflight(params PreflightParameters) (Preflight, error) { opBodyXDR, err := params.OpBody.MarshalBinary() if err != nil { return Preflight{}, err @@ -144,7 +144,7 @@ func getFootprintExpirationPreflight(params PreflightParameters) (Preflight, err return Preflight{}, err } - res := C.preflight_footprint_expiration_op( + res := C.preflight_footprint_ttl_op( C.uintptr_t(handle), C.uint64_t(params.BucketListSize), opBodyCXDR, @@ -182,20 +182,17 @@ func getInvokeHostFunctionPreflight(params PreflightParameters) (Preflight, erro } sourceAccountCXDR := CXDR(sourceAccountXDR) - hasConfig, stateExpirationConfig, expSeq, err := db.GetLedgerEntry(params.LedgerEntryReadTx, xdr.LedgerKey{ + hasConfig, stateArchivalConfig, _, err := db.GetLedgerEntry(params.LedgerEntryReadTx, xdr.LedgerKey{ Type: xdr.LedgerEntryTypeConfigSetting, ConfigSetting: &xdr.LedgerKeyConfigSetting{ - ConfigSettingId: xdr.ConfigSettingIdConfigSettingStateExpiration, + ConfigSettingId: xdr.ConfigSettingIdConfigSettingStateArchival, }, }) if err != nil { return Preflight{}, err } - if expSeq != nil { - return Preflight{}, errors.New("configuration setting are not expected to be expiring, yet, an expiration ledger sequence was found for ledger entry") - } if !hasConfig { - return Preflight{}, errors.New("state expiration config setting missing in ledger storage") + return Preflight{}, errors.New("state archival config setting missing in ledger storage") } simulationLedgerSeq, err := getSimulationLedgerSeq(params.LedgerEntryReadTx) @@ -203,17 +200,17 @@ func getInvokeHostFunctionPreflight(params PreflightParameters) (Preflight, erro return Preflight{}, err } - stateExpiration := stateExpirationConfig.Data.MustConfigSetting().MustStateExpirationSettings() + 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_expiration: C.uint(stateExpiration.MinTempEntryExpiration), - min_persistent_entry_expiration: C.uint(stateExpiration.MinPersistentEntryExpiration), - max_entry_expiration: C.uint(stateExpiration.MaxEntryExpiration), + 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}) diff --git a/cmd/soroban-rpc/internal/preflight/preflight_test.go b/cmd/soroban-rpc/internal/preflight/preflight_test.go index b3215f49d..47f4baaff 100644 --- a/cmd/soroban-rpc/internal/preflight/preflight_test.go +++ b/cmd/soroban-rpc/internal/preflight/preflight_test.go @@ -32,7 +32,7 @@ var contractCostParams = func() *xdr.ContractCostParams { return &result }() -var mockLedgerEntriesWithoutExpirations = []xdr.LedgerEntry{ +var mockLedgerEntriesWithoutTTLs = []xdr.LedgerEntry{ { LastModifiedLedgerSeq: 1, Data: xdr.LedgerEntryData{ @@ -154,14 +154,14 @@ var mockLedgerEntriesWithoutExpirations = []xdr.LedgerEntry{ Data: xdr.LedgerEntryData{ Type: xdr.LedgerEntryTypeConfigSetting, ConfigSetting: &xdr.ConfigSettingEntry{ - ConfigSettingId: xdr.ConfigSettingIdConfigSettingStateExpiration, - StateExpirationSettings: &xdr.StateExpirationSettings{ - MaxEntryExpiration: 100, - MinTempEntryExpiration: 100, - MinPersistentEntryExpiration: 100, + ConfigSettingId: xdr.ConfigSettingIdConfigSettingStateArchival, + StateArchivalSettings: &xdr.StateArchivalSettings{ + MaxEntryTtl: 100, + MinTemporaryTtl: 100, + MinPersistentTtl: 100, PersistentRentRateDenominator: 100, TempRentRateDenominator: 100, - MaxEntriesToExpire: 100, + MaxEntriesToArchive: 100, BucketListSizeWindowSampleSize: 100, EvictionScanSize: 100, }, @@ -192,10 +192,10 @@ var mockLedgerEntriesWithoutExpirations = []xdr.LedgerEntry{ }, } -// Adds expiration entries to mockLedgerEntriesWithoutExpirations +// Adds ttl entries to mockLedgerEntriesWithoutTTLs var mockLedgerEntries = func() []xdr.LedgerEntry { - result := make([]xdr.LedgerEntry, 0, len(mockLedgerEntriesWithoutExpirations)) - for _, entry := range mockLedgerEntriesWithoutExpirations { + result := make([]xdr.LedgerEntry, 0, len(mockLedgerEntriesWithoutTTLs)) + for _, entry := range mockLedgerEntriesWithoutTTLs { result = append(result, entry) if entry.Data.Type == xdr.LedgerEntryTypeContractData || entry.Data.Type == xdr.LedgerEntryTypeContractCode { @@ -207,18 +207,18 @@ var mockLedgerEntries = func() []xdr.LedgerEntry { if err != nil { panic(err) } - expirationEntry := xdr.LedgerEntry{ + ttlEntry := xdr.LedgerEntry{ LastModifiedLedgerSeq: entry.LastModifiedLedgerSeq, Data: xdr.LedgerEntryData{ - Type: xdr.LedgerEntryTypeExpiration, - Expiration: &xdr.ExpirationEntry{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.TtlEntry{ KeyHash: sha256.Sum256(bin), - // Make sure it doesn't expire - ExpirationLedgerSeq: 1000, + // Make sure it doesn't ttl + LiveUntilLedgerSeq: 1000, }, }, } - result = append(result, expirationEntry) + result = append(result, ttlEntry) } } return result @@ -248,7 +248,7 @@ func (m inMemoryLedgerEntryReadTx) GetLedgerEntries(keys ...xdr.LedgerKey) ([]db if !ok { continue } - // We don't check the expiration but that's ok for the test + // We don't check the TTL but that's ok for the test result = append(result, db.LedgerKeyAndEntry{ Key: key, Entry: entry, diff --git a/cmd/soroban-rpc/internal/test/captive-core-integration-tests.cfg b/cmd/soroban-rpc/internal/test/captive-core-integration-tests.cfg index 45b9a8e61..275599bac 100644 --- a/cmd/soroban-rpc/internal/test/captive-core-integration-tests.cfg +++ b/cmd/soroban-rpc/internal/test/captive-core-integration-tests.cfg @@ -5,8 +5,8 @@ UNSAFE_QUORUM=true FAILURE_SAFETY=0 ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true -# Lower the expiration of persistent ledger entries -# so that ledger expiration/restoring becomes testeable +# Lower the TTL of persistent ledger entries +# so that ledger entry extension/restoring becomes testeable TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 TESTING_SOROBAN_HIGH_LIMIT_OVERRIDE=true diff --git a/cmd/soroban-rpc/internal/test/cli_test.go b/cmd/soroban-rpc/internal/test/cli_test.go index 1634df6c3..c1571d246 100644 --- a/cmd/soroban-rpc/internal/test/cli_test.go +++ b/cmd/soroban-rpc/internal/test/cli_test.go @@ -17,10 +17,11 @@ import ( "github.com/stellar/go/strkey" "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" - "github.com/stellar/soroban-tools/cmd/soroban-rpc/internal/methods" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gotest.tools/v3/icmd" + + "github.com/stellar/soroban-tools/cmd/soroban-rpc/internal/methods" ) func cargoTest(t *testing.T, name string) { @@ -115,11 +116,11 @@ func TestCLIRestorePreamble(t *testing.T) { count = runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "2", count) - // Wait for the counter ledger entry to expire and successfully invoke the `inc` contract function again + // Wait for the counter ledger entry to ttl and successfully invoke the `inc` contract function again // This ensures that the CLI restores the entry (using the RestorePreamble in the simulateTransaction response) ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) client := jrpc2.NewClient(ch, nil) - waitForLedgerEntryToExpire(t, client, getCounterLedgerKey(parseContractStrKey(t, strkeyContractID))) + waitUntilLedgerEntryTTL(t, client, getCounterLedgerKey(parseContractStrKey(t, strkeyContractID))) count = runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "3", count) @@ -134,8 +135,8 @@ func TestCLIBump(t *testing.T) { ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) client := jrpc2.NewClient(ch, nil) - expirationKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) - initialExpirationSeq := getExpirationForLedgerEntry(t, client, expirationKey) + ttlKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) + initialLiveUntilSeq := getLedgerEntryLiveUntil(t, client, ttlKey) bumpOutput := runSuccessfulCLICmd( t, @@ -145,9 +146,9 @@ func TestCLIBump(t *testing.T) { ), ) - newExpirationSeq := getExpirationForLedgerEntry(t, client, expirationKey) - assert.Greater(t, newExpirationSeq, initialExpirationSeq) - assert.Equal(t, fmt.Sprintf("New expiration ledger: %d", newExpirationSeq), bumpOutput) + newLiveUntilSeq := getLedgerEntryLiveUntil(t, client, ttlKey) + assert.Greater(t, newLiveUntilSeq, initialLiveUntilSeq) + assert.Equal(t, fmt.Sprintf("New ttl ledger: %d", newLiveUntilSeq), bumpOutput) } func TestCLIBumpTooLow(t *testing.T) { test := NewCLITest(t) @@ -158,17 +159,17 @@ func TestCLIBumpTooLow(t *testing.T) { ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) client := jrpc2.NewClient(ch, nil) - expirationKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) - initialExpirationSeq := parseInt(t, getExpirationForLedgerEntry(t, client, expirationKey).GoString()) + ttlKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) + initialLiveUntilSeq := parseInt(t, getLedgerEntryLiveUntil(t, client, ttlKey).GoString()) bumpOutput := bump(t, strkeyContractID, "400", "--key COUNTER ") - newExpirationSeq := parseInt(t, getExpirationForLedgerEntry(t, client, expirationKey).GoString()) - assert.Greater(t, newExpirationSeq, initialExpirationSeq) - assert.Equal(t, newExpirationSeq, bumpOutput) + newLiveUntilSeq := parseInt(t, getLedgerEntryLiveUntil(t, client, ttlKey).GoString()) + assert.Greater(t, newLiveUntilSeq, initialLiveUntilSeq) + assert.Equal(t, newLiveUntilSeq, bumpOutput) - updatedExpirationSeq := bump(t, strkeyContractID, "15", "--key COUNTER") - assert.Equal(t, bumpOutput, updatedExpirationSeq) + updatedLiveUntilSeq := bump(t, strkeyContractID, "15", "--key COUNTER") + assert.Equal(t, bumpOutput, updatedLiveUntilSeq) } func TestCLIBumpTooHigh(t *testing.T) { @@ -180,14 +181,14 @@ func TestCLIBumpTooHigh(t *testing.T) { ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) client := jrpc2.NewClient(ch, nil) - expirationKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) - initialExpirationSeq := parseInt(t, getExpirationForLedgerEntry(t, client, expirationKey).GoString()) + ttlKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) + initialLiveUntilSeq := parseInt(t, getLedgerEntryLiveUntil(t, client, ttlKey).GoString()) bumpOutput := bump(t, strkeyContractID, "100000000", "--key COUNTER ") - newExpirationSeq := parseInt(t, getExpirationForLedgerEntry(t, client, expirationKey).GoString()) - assert.Greater(t, newExpirationSeq, initialExpirationSeq) - assert.Equal(t, newExpirationSeq, bumpOutput) + newLiveUntilSeq := parseInt(t, getLedgerEntryLiveUntil(t, client, ttlKey).GoString()) + assert.Greater(t, newLiveUntilSeq, initialLiveUntilSeq) + assert.Equal(t, newLiveUntilSeq, bumpOutput) } func TestCLIRestore(t *testing.T) { @@ -199,11 +200,11 @@ func TestCLIRestore(t *testing.T) { ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) client := jrpc2.NewClient(ch, nil) - expirationKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) - initialExpirationSeq := getExpirationForLedgerEntry(t, client, expirationKey) - // Wait for the counter ledger entry to expire and successfully invoke the `inc` contract function again + ttlKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) + initialLiveUntilSeq := getLedgerEntryLiveUntil(t, client, ttlKey) + // Wait for the counter ledger entry to ttl and successfully invoke the `inc` contract function again // This ensures that the CLI restores the entry (using the RestorePreamble in the simulateTransaction response) - waitForLedgerEntryToExpire(t, client, expirationKey) + waitUntilLedgerEntryTTL(t, client, ttlKey) restoreOutput := runSuccessfulCLICmd( t, @@ -213,37 +214,39 @@ func TestCLIRestore(t *testing.T) { ), ) - newExpirationSeq := getExpirationForLedgerEntry(t, client, getCounterLedgerKey(parseContractStrKey(t, strkeyContractID))) - assert.Greater(t, newExpirationSeq, initialExpirationSeq) - assert.Equal(t, fmt.Sprintf("New expiration ledger: %d", newExpirationSeq), restoreOutput) + newLiveUntilSeq := getLedgerEntryLiveUntil(t, client, getCounterLedgerKey(parseContractStrKey(t, strkeyContractID))) + assert.Greater(t, newLiveUntilSeq, initialLiveUntilSeq) + assert.Equal(t, fmt.Sprintf("New ttl ledger: %d", newLiveUntilSeq), restoreOutput) - // test to see that we get an error when requesting the expiration ledger entry explicitly. - ledgerExpirationEntry := getExpirationKey(t, getCounterLedgerKey(parseContractStrKey(t, strkeyContractID))) - ledgerExpirationEntryB64, err := xdr.MarshalBase64(ledgerExpirationEntry) + // FIXME: the following checks shouldn't live here: + + // test to see that we get an error when requesting the ttl ledger entry explicitly. + ledgerTTLEntry := getTtlKey(t, getCounterLedgerKey(parseContractStrKey(t, strkeyContractID))) + ledgerTTLEntryB64, err := xdr.MarshalBase64(ledgerTTLEntry) require.NoError(t, err) var getLedgerEntryResult methods.GetLedgerEntryResponse err = client.CallResult(context.Background(), "getLedgerEntry", methods.GetLedgerEntryRequest{ - Key: ledgerExpirationEntryB64, + Key: ledgerTTLEntryB64, }, &getLedgerEntryResult) require.Error(t, err) - require.Contains(t, err.Error(), methods.ErrLedgerExpirationEntriesCannotBeQueriedDirectly) + require.Contains(t, err.Error(), methods.ErrLedgerTtlEntriesCannotBeQueriedDirectly) // repeat with getLedgerEntries var getLedgerEntriesResult methods.GetLedgerEntriesResponse err = client.CallResult(context.Background(), "getLedgerEntries", methods.GetLedgerEntriesRequest{ - Keys: []string{ledgerExpirationEntryB64}, + Keys: []string{ledgerTTLEntryB64}, }, &getLedgerEntriesResult) require.Error(t, err) - require.Contains(t, err.Error(), methods.ErrLedgerExpirationEntriesCannotBeQueriedDirectly) + require.Contains(t, err.Error(), methods.ErrLedgerTtlEntriesCannotBeQueriedDirectly) } -func getExpirationKey(t *testing.T, key xdr.LedgerKey) xdr.LedgerKey { +func getTtlKey(t *testing.T, key xdr.LedgerKey) xdr.LedgerKey { assert.True(t, key.Type == xdr.LedgerEntryTypeContractCode || key.Type == xdr.LedgerEntryTypeContractData) binKey, err := key.MarshalBinary() assert.NoError(t, err) return xdr.LedgerKey{ - Type: xdr.LedgerEntryTypeExpiration, - Expiration: &xdr.LedgerKeyExpiration{ + Type: xdr.LedgerEntryTypeTtl, + Ttl: &xdr.LedgerKeyTtl{ KeyHash: sha256.Sum256(binKey), }, } @@ -335,3 +338,20 @@ func bump(t *testing.T, contractId string, amount string, rest string) uint64 { return parseInt(t, res) } + +func getLedgerEntryLiveUntil(t *testing.T, client *jrpc2.Client, ttlLedgerKey xdr.LedgerKey) xdr.Uint32 { + keyB64, err := xdr.MarshalBase64(ttlLedgerKey) + require.NoError(t, err) + getLedgerEntryrequest := methods.GetLedgerEntryRequest{ + Key: keyB64, + } + var getLedgerEntryResult methods.GetLedgerEntryResponse + err = client.CallResult(context.Background(), "getLedgerEntry", getLedgerEntryrequest, &getLedgerEntryResult) + require.NoError(t, err) + var entry xdr.LedgerEntryData + require.NoError(t, xdr.SafeUnmarshalBase64(getLedgerEntryResult.XDR, &entry)) + + require.Contains(t, []xdr.LedgerEntryType{xdr.LedgerEntryTypeContractCode, xdr.LedgerEntryTypeContractData}, entry.Type) + require.NotNil(t, getLedgerEntryResult.LiveUntilLedgerSeq) + return xdr.Uint32(*getLedgerEntryResult.LiveUntilLedgerSeq) +} diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index e1c02b8e4..e5595f271 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -159,7 +159,7 @@ func preflightTransactionParamsLocally(t *testing.T, params txnbuild.Transaction auth = append(auth, a) } v.Auth = auth - case *txnbuild.BumpFootprintExpiration: + case *txnbuild.ExtendFootprintTtl: require.Len(t, response.Results, 0) v.Ext = xdr.TransactionExt{ V: 1, @@ -236,7 +236,7 @@ func TestSimulateTransactionSucceeds(t *testing.T) { ReadBytes: 48, WriteBytes: 7048, }, - RefundableFee: 20056, + ResourceFee: 20056, } // First, decode and compare the transaction data so we get a decent diff if it fails. @@ -247,7 +247,7 @@ func TestSimulateTransactionSucceeds(t *testing.T) { assert.InDelta(t, uint32(expectedTransactionData.Resources.Instructions), uint32(transactionData.Resources.Instructions), 100000) assert.InDelta(t, uint32(expectedTransactionData.Resources.ReadBytes), uint32(transactionData.Resources.ReadBytes), 10) assert.InDelta(t, uint32(expectedTransactionData.Resources.WriteBytes), uint32(transactionData.Resources.WriteBytes), 100) - assert.InDelta(t, int64(expectedTransactionData.RefundableFee), int64(transactionData.RefundableFee), 1000) + assert.InDelta(t, int64(expectedTransactionData.ResourceFee), int64(transactionData.ResourceFee), 1000) // Then decode and check the result xdr, separately so we get a decent diff if it fails. assert.Len(t, result.Results, 1) @@ -494,7 +494,7 @@ func TestSimulateInvokeContractTransactionSucceeds(t *testing.T) { assert.Equal(t, xdr.Hash(contractHash), ro2.ContractCode.Hash) assert.NoError(t, err) - assert.NotZero(t, obtainedTransactionData.RefundableFee) + assert.NotZero(t, obtainedTransactionData.ResourceFee) assert.NotZero(t, obtainedTransactionData.Resources.Instructions) assert.NotZero(t, obtainedTransactionData.Resources.ReadBytes) assert.NotZero(t, obtainedTransactionData.Resources.WriteBytes) @@ -732,7 +732,7 @@ func TestSimulateTransactionBumpAndRestoreFootprint(t *testing.T) { assert.NoError(t, err) sendSuccessfulTransaction(t, client, sourceAccount, tx) - // get the counter ledger entry expiration + // get the counter ledger entry TTL key := getCounterLedgerKey(contractID) keyB64, err := xdr.MarshalBase64(key) @@ -747,17 +747,17 @@ func TestSimulateTransactionBumpAndRestoreFootprint(t *testing.T) { var entry xdr.LedgerEntryData assert.NoError(t, xdr.SafeUnmarshalBase64(getLedgerEntryResult.XDR, &entry)) assert.Equal(t, xdr.LedgerEntryTypeContractData, entry.Type) - require.NotNil(t, getLedgerEntryResult.ExpirationLedger) + require.NotNil(t, getLedgerEntryResult.LiveUntilLedgerSeq) - initialExpirationSeq := *getLedgerEntryResult.ExpirationLedger + initialLiveUntil := *getLedgerEntryResult.LiveUntilLedgerSeq - // bump the initial expiration + // bump the initial TTL params = preflightTransactionParams(t, client, txnbuild.TransactionParams{ SourceAccount: &account, IncrementSequenceNum: true, Operations: []txnbuild.Operation{ - &txnbuild.BumpFootprintExpiration{ - LedgersToExpire: 20, + &txnbuild.ExtendFootprintTtl{ + ExtendTo: 20, Ext: xdr.TransactionExt{ V: 1, SorobanData: &xdr.SorobanTransactionData{ @@ -783,32 +783,12 @@ func TestSimulateTransactionBumpAndRestoreFootprint(t *testing.T) { assert.NoError(t, err) assert.NoError(t, xdr.SafeUnmarshalBase64(getLedgerEntryResult.XDR, &entry)) assert.Equal(t, xdr.LedgerEntryTypeContractData, entry.Type) - require.NotNil(t, getLedgerEntryResult.ExpirationLedger) - newExpirationSeq := *getLedgerEntryResult.ExpirationLedger - assert.Greater(t, newExpirationSeq, initialExpirationSeq) - - // Wait until it expires - waitForExpiration := func() { - expired := false - for i := 0; i < 50; i++ { - err = client.CallResult(context.Background(), "getLedgerEntry", getLedgerEntryrequest, &getLedgerEntryResult) - assert.NoError(t, err) - assert.NoError(t, xdr.SafeUnmarshalBase64(getLedgerEntryResult.XDR, &entry)) - assert.Equal(t, xdr.LedgerEntryTypeContractData, entry.Type) - // See https://soroban.stellar.org/docs/fundamentals-and-concepts/state-expiration#expiration-ledger - currentLedger := getLedgerEntryResult.LatestLedger + 1 - require.NotNil(t, getLedgerEntryResult.ExpirationLedger) - if uint32(currentLedger) > *getLedgerEntryResult.ExpirationLedger { - expired = true - t.Logf("ledger entry expired") - break - } - t.Log("waiting for ledger entry to expire at ledger", *getLedgerEntryResult.ExpirationLedger) - time.Sleep(time.Second) - } - require.True(t, expired) - } - waitForExpiration() + require.NotNil(t, getLedgerEntryResult.LiveUntilLedgerSeq) + newLiveUntilSeq := *getLedgerEntryResult.LiveUntilLedgerSeq + assert.Greater(t, newLiveUntilSeq, initialLiveUntil) + + // Wait until it is not live anymore + waitUntilLedgerEntryTTL(t, client, key) // and restore it params = preflightTransactionParams(t, client, txnbuild.TransactionParams{ @@ -837,8 +817,8 @@ func TestSimulateTransactionBumpAndRestoreFootprint(t *testing.T) { assert.NoError(t, err) sendSuccessfulTransaction(t, client, sourceAccount, tx) - // Wait for expiration again and check the pre-restore field when trying to exec the contract again - waitForLedgerEntryToExpire(t, client, key) + // Wait for TTL again and check the pre-restore field when trying to exec the contract again + waitUntilLedgerEntryTTL(t, client, key) simulationResult := simulateTransactionFromTxParams(t, client, invokeIncPresistentEntryParams) require.NotNil(t, simulationResult.RestorePreamble) @@ -892,30 +872,13 @@ func getCounterLedgerKey(contractID [32]byte) xdr.LedgerKey { return key } -func getExpirationForLedgerEntry(t *testing.T, client *jrpc2.Client, expirationLedgerKey xdr.LedgerKey) xdr.Uint32 { - keyB64, err := xdr.MarshalBase64(expirationLedgerKey) - require.NoError(t, err) - getLedgerEntryrequest := methods.GetLedgerEntryRequest{ - Key: keyB64, - } - var getLedgerEntryResult methods.GetLedgerEntryResponse - err = client.CallResult(context.Background(), "getLedgerEntry", getLedgerEntryrequest, &getLedgerEntryResult) - require.NoError(t, err) - var entry xdr.LedgerEntryData - require.NoError(t, xdr.SafeUnmarshalBase64(getLedgerEntryResult.XDR, &entry)) - - require.Contains(t, []xdr.LedgerEntryType{xdr.LedgerEntryTypeContractCode, xdr.LedgerEntryTypeContractData}, entry.Type) - require.NotNil(t, getLedgerEntryResult.ExpirationLedger) - return xdr.Uint32(*getLedgerEntryResult.ExpirationLedger) -} - -func waitForLedgerEntryToExpire(t *testing.T, client *jrpc2.Client, ledgerKey xdr.LedgerKey) { +func waitUntilLedgerEntryTTL(t *testing.T, client *jrpc2.Client, ledgerKey xdr.LedgerKey) { keyB64, err := xdr.MarshalBase64(ledgerKey) require.NoError(t, err) request := methods.GetLedgerEntriesRequest{ Keys: []string{keyB64}, } - expired := false + ttled := false for i := 0; i < 50; i++ { var result methods.GetLedgerEntriesResponse var entry xdr.LedgerEntryData @@ -923,19 +886,19 @@ func waitForLedgerEntryToExpire(t *testing.T, client *jrpc2.Client, ledgerKey xd require.NoError(t, err) require.NotEmpty(t, result.Entries) require.NoError(t, xdr.SafeUnmarshalBase64(result.Entries[0].XDR, &entry)) - require.NotEqual(t, xdr.LedgerEntryTypeExpiration, entry.Type) - expirationLedgerSeq := xdr.Uint32(*result.Entries[0].ExpirationLedger) + require.NotEqual(t, xdr.LedgerEntryTypeTtl, entry.Type) + liveUntilLedgerSeq := xdr.Uint32(*result.Entries[0].LiveUntilLedgerSeq) // See https://soroban.stellar.org/docs/fundamentals-and-concepts/state-expiration#expiration-ledger currentLedger := result.LatestLedger + 1 - if xdr.Uint32(currentLedger) > expirationLedgerSeq { - expired = true - t.Logf("ledger entry expired") + if xdr.Uint32(currentLedger) > liveUntilLedgerSeq { + ttled = true + t.Logf("ledger entry ttl'ed") break } - t.Log("waiting for ledger entry to expire at ledger", expirationLedgerSeq) + t.Log("waiting for ledger entry to ttl at ledger", liveUntilLedgerSeq) time.Sleep(time.Second) } - require.True(t, expired) + require.True(t, ttled) } func TestSimulateInvokePrng_u64_in_range(t *testing.T) { @@ -1159,7 +1122,7 @@ func TestSimulateSystemEvent(t *testing.T) { require.NoError(t, err) assert.InDelta(t, 7260, uint32(transactionData.Resources.ReadBytes), 200) - assert.InDelta(t, 45, int64(transactionData.RefundableFee), 10) + assert.InDelta(t, 45, int64(transactionData.ResourceFee), 10) assert.InDelta(t, 104, uint32(transactionData.Resources.WriteBytes), 15) require.GreaterOrEqual(t, len(response.Events), 3) } diff --git a/cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg b/cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg index d41ccb021..4c72db24a 100644 --- a/cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg +++ b/cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg @@ -15,8 +15,8 @@ FAILURE_SAFETY=0 DATABASE="postgresql://user=postgres password=mysecretpassword host=core-postgres port=5641 dbname=stellar" ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true -# Lower the expiration of persistent ledger entries -# so that ledger expiration/restoring becomes testeable +# Lower the TTL of persistent ledger entries +# so that ledger entry extension/restoring becomes testeable TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 TESTING_SOROBAN_HIGH_LIMIT_OVERRIDE=true diff --git a/cmd/soroban-rpc/internal/transactions/transactions_test.go b/cmd/soroban-rpc/internal/transactions/transactions_test.go index cf78976c9..64fabff1f 100644 --- a/cmd/soroban-rpc/internal/transactions/transactions_test.go +++ b/cmd/soroban-rpc/internal/transactions/transactions_test.go @@ -5,8 +5,9 @@ import ( "github.com/stellar/go/network" "github.com/stellar/go/xdr" - "github.com/stellar/soroban-tools/cmd/soroban-rpc/internal/daemon/interfaces" "github.com/stretchr/testify/require" + + "github.com/stellar/soroban-tools/cmd/soroban-rpc/internal/daemon/interfaces" ) func expectedTransaction(ledger uint32, feeBump bool) Transaction { @@ -107,8 +108,8 @@ func txMeta(ledgerSequence uint32, feeBump bool) xdr.LedgerCloseMeta { }, } return xdr.LedgerCloseMeta{ - V: 2, - V2: &xdr.LedgerCloseMetaV2{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ LedgerHeader: xdr.LedgerHeaderHistoryEntry{ Header: xdr.LedgerHeader{ ScpValue: xdr.StellarValue{ diff --git a/cmd/soroban-rpc/lib/preflight.h b/cmd/soroban-rpc/lib/preflight.h index fc01d9f45..627cc54c8 100644 --- a/cmd/soroban-rpc/lib/preflight.h +++ b/cmd/soroban-rpc/lib/preflight.h @@ -9,9 +9,9 @@ typedef struct ledger_info_t { uint64_t timestamp; const char *network_passphrase; uint32_t base_reserve; - uint32_t min_temp_entry_expiration; - uint32_t min_persistent_entry_expiration; - uint32_t max_entry_expiration; + uint32_t min_temp_entry_ttl; + uint32_t min_persistent_entry_ttl; + uint32_t max_entry_ttl; } ledger_info_t; typedef struct xdr_t { @@ -43,11 +43,11 @@ preflight_result_t *preflight_invoke_hf_op(uintptr_t handle, // Go Handle to for const xdr_t source_account, // AccountId XDR const ledger_info_t ledger_info); -preflight_result_t *preflight_footprint_expiration_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet - uint64_t bucket_list_size, // Bucket list size of current ledger - const xdr_t op_body, // OperationBody XDR - const xdr_t footprint, // LedgerFootprint XDR - uint32_t current_ledger_seq); // Current ledger sequence +preflight_result_t *preflight_footprint_ttl_op(uintptr_t handle, // Go Handle to forward to SnapshotSourceGet + uint64_t bucket_list_size, // Bucket list size of current ledger + const xdr_t op_body, // OperationBody XDR + const xdr_t footprint, // LedgerFootprint XDR + uint32_t current_ledger_seq); // Current ledger sequence // LedgerKey XDR to LedgerEntry XDR diff --git a/cmd/soroban-rpc/lib/preflight/src/fees.rs b/cmd/soroban-rpc/lib/preflight/src/fees.rs index d30497700..3e034422b 100644 --- a/cmd/soroban-rpc/lib/preflight/src/fees.rs +++ b/cmd/soroban-rpc/lib/preflight/src/fees.rs @@ -2,33 +2,27 @@ use anyhow::{bail, ensure, Context, Error, Result}; use ledger_storage::LedgerStorage; use soroban_env_host::budget::Budget; use soroban_env_host::e2e_invoke::{ - extract_rent_changes, get_ledger_changes, ExpirationEntryMap, LedgerEntryChange, + extract_rent_changes, get_ledger_changes, LedgerEntryChange, TtlEntryMap, }; use soroban_env_host::fees::{ compute_rent_fee, compute_transaction_resource_fee, compute_write_fee_per_1kb, FeeConfiguration, LedgerEntryRentChange, RentFeeConfiguration, TransactionResources, - WriteFeeConfiguration, + WriteFeeConfiguration, TTL_ENTRY_SIZE, }; use soroban_env_host::storage::{AccessType, Footprint, Storage}; use soroban_env_host::xdr; use soroban_env_host::xdr::ContractDataDurability::Persistent; use soroban_env_host::xdr::{ - BumpFootprintExpirationOp, ConfigSettingEntry, ConfigSettingId, ContractEventType, - DecoratedSignature, DiagnosticEvent, ExtensionPoint, InvokeHostFunctionOp, LedgerFootprint, - LedgerKey, Memo, MuxedAccount, MuxedAccountMed25519, Operation, OperationBody, Preconditions, + ConfigSettingEntry, ConfigSettingId, ContractEventType, DecoratedSignature, DiagnosticEvent, + ExtendFootprintTtlOp, ExtensionPoint, InvokeHostFunctionOp, LedgerFootprint, LedgerKey, Memo, + MuxedAccount, MuxedAccountMed25519, Operation, OperationBody, Preconditions, RestoreFootprintOp, ScVal, SequenceNumber, Signature, SignatureHint, SorobanResources, SorobanTransactionData, Transaction, TransactionExt, TransactionV1Envelope, Uint256, WriteXdr, }; -use state_expiration::{get_restored_ledger_sequence, ExpirableLedgerEntry}; +use state_ttl::{get_restored_ledger_sequence, TTLLedgerEntry}; use std::cmp::max; use std::convert::{TryFrom, TryInto}; -// TODO: this should be imported from soroban_env_host::fees instead -/// Serialize XDR size for any `ExpirationEntry` ledger entry. -const EXPIRATION_ENTRY_SIZE: u32 = 48; - -// TODO: this should perhaps be an new type -#[allow(clippy::too_many_arguments)] pub(crate) fn compute_host_function_transaction_data_and_min_fee( op: &InvokeHostFunctionOp, pre_storage: &LedgerStorage, @@ -39,8 +33,7 @@ pub(crate) fn compute_host_function_transaction_data_and_min_fee( bucket_list_size: u64, current_ledger_seq: u32, ) -> Result<(SorobanTransactionData, i64)> { - let ledger_changes = - get_ledger_changes(budget, post_storage, pre_storage, ExpirationEntryMap::new())?; + let ledger_changes = get_ledger_changes(budget, post_storage, pre_storage, TtlEntryMap::new())?; let soroban_resources = calculate_host_function_soroban_resources(&ledger_changes, &post_storage.footprint, budget) .context("cannot compute host function resources")?; @@ -114,7 +107,7 @@ fn estimate_max_transaction_size_for_operation( read_bytes: 0, write_bytes: 0, }, - refundable_fee: 0, + resource_fee: 0, ext: ExtensionPoint::V0, }), }, @@ -139,12 +132,7 @@ fn calculate_host_function_soroban_resources( .context("cannot convert storage footprint to ledger footprint")?; let read_bytes: u32 = ledger_changes .iter() - .map(|c| { - c.old_entry_size_bytes - + c.expiration_change - .as_ref() - .map_or(0, |_| EXPIRATION_ENTRY_SIZE) - }) + .map(|c| c.old_entry_size_bytes + c.ttl_change.as_ref().map_or(0, |_| TTL_ENTRY_SIZE)) .sum(); let write_bytes: u32 = ledger_changes @@ -200,10 +188,10 @@ fn get_fee_configurations( bail!("unexpected config setting entry for BandwidthV0 key"); }; - let ConfigSettingEntry::StateExpiration(state_expiration) = - ledger_storage.get_configuration_setting(ConfigSettingId::StateExpiration)? + let ConfigSettingEntry::StateArchival(state_archival) = + ledger_storage.get_configuration_setting(ConfigSettingId::StateArchival)? else { - bail!("unexpected config setting entry for StateExpiration key"); + bail!("unexpected config setting entry for StateArchival key"); }; let write_fee_configuration = WriteFeeConfiguration { @@ -229,18 +217,18 @@ fn get_fee_configurations( let rent_fee_configuration = RentFeeConfiguration { fee_per_write_1kb: write_fee_per_1kb, fee_per_write_entry: ledger_cost.fee_write_ledger_entry, - persistent_rent_rate_denominator: state_expiration.persistent_rent_rate_denominator, - temporary_rent_rate_denominator: state_expiration.temp_rent_rate_denominator, + persistent_rent_rate_denominator: state_archival.persistent_rent_rate_denominator, + temporary_rent_rate_denominator: state_archival.temp_rent_rate_denominator, }; Ok((fee_configuration, rent_fee_configuration)) } -// Calculate the implicit ExpirationEntry bytes that will be read for expirable LedgerEntries -fn calculate_expiration_entry_bytes(ledger_entries: &[LedgerKey]) -> u32 { +// Calculate the implicit TTLEntry bytes that will be read for TTLLedgerEntries +fn calculate_ttl_entry_bytes(ledger_entries: &Vec) -> u32 { ledger_entries .iter() .map(|lk| match lk { - LedgerKey::ContractData(_) | LedgerKey::ContractCode(_) => EXPIRATION_ENTRY_SIZE, + LedgerKey::ContractData(_) | LedgerKey::ContractCode(_) => TTL_ENTRY_SIZE, _ => 0, }) .sum() @@ -250,12 +238,12 @@ fn calculate_expiration_entry_bytes(ledger_entries: &[LedgerKey]) -> u32 { fn calculate_unmodified_ledger_entry_bytes( ledger_entries: &[LedgerKey], pre_storage: &LedgerStorage, - include_expired: bool, + include_not_live: bool, ) -> Result { let mut res: usize = 0; for lk in ledger_entries { let entry_xdr = pre_storage - .get_xdr(lk, include_expired) + .get_xdr(lk, include_not_live) .with_context(|| format!("cannot get xdr of ledger entry with key {lk:?}"))?; let entry_size = entry_xdr.len(); res += entry_size; @@ -308,34 +296,32 @@ fn finalize_transaction_data_and_min_fee( let (non_refundable_fee, refundable_fee) = compute_transaction_resource_fee(transaction_resources, &fee_configuration); let rent_fee = compute_rent_fee(rent_changes, &rent_fee_configuration, current_ledger_seq); + let resource_fee = refundable_fee + non_refundable_fee + rent_fee; let transaction_data = SorobanTransactionData { resources: soroban_resources, - refundable_fee: refundable_fee + rent_fee, + resource_fee, ext: ExtensionPoint::V0, }; - let res = ( - transaction_data, - refundable_fee + non_refundable_fee + rent_fee, - ); + let res = (transaction_data, resource_fee); Ok(res) } -pub(crate) fn compute_bump_footprint_exp_transaction_data_and_min_fee( +pub(crate) fn compute_extend_footprint_ttl_transaction_data_and_min_fee( footprint: LedgerFootprint, - ledgers_to_expire: u32, + extend_to: u32, ledger_storage: &LedgerStorage, bucket_list_size: u64, current_ledger_seq: u32, ) -> Result<(SorobanTransactionData, i64)> { - let rent_changes = compute_bump_footprint_rent_changes( + let rent_changes = compute_extend_footprint_rent_changes( &footprint, ledger_storage, - ledgers_to_expire, + extend_to, current_ledger_seq, ) .context("cannot compute bump rent changes")?; - let expiration_bytes = calculate_expiration_entry_bytes(footprint.read_only.as_slice()); + let ttl_bytes: u32 = calculate_ttl_entry_bytes(footprint.read_only.as_vec()); let unmodified_entry_bytes = calculate_unmodified_ledger_entry_bytes( footprint.read_only.as_slice(), @@ -347,13 +333,13 @@ pub(crate) fn compute_bump_footprint_exp_transaction_data_and_min_fee( let soroban_resources = SorobanResources { footprint, instructions: 0, - read_bytes: unmodified_entry_bytes + expiration_bytes, + read_bytes: unmodified_entry_bytes + ttl_bytes, write_bytes: 0, }; let transaction_size_bytes = estimate_max_transaction_size_for_operation( - &OperationBody::BumpFootprintExpiration(BumpFootprintExpirationOp { + &OperationBody::ExtendFootprintTtl(ExtendFootprintTtlOp { ext: ExtensionPoint::V0, - ledgers_to_expire, + extend_to, }), &soroban_resources.footprint, ) @@ -378,35 +364,36 @@ pub(crate) fn compute_bump_footprint_exp_transaction_data_and_min_fee( } #[allow(clippy::cast_possible_truncation)] -fn compute_bump_footprint_rent_changes( +fn compute_extend_footprint_rent_changes( footprint: &LedgerFootprint, ledger_storage: &LedgerStorage, - ledgers_to_expire: u32, + extend_to: u32, current_ledger_seq: u32, ) -> Result> { let mut rent_changes: Vec = Vec::with_capacity(footprint.read_only.len()); - for key in footprint.read_only.as_slice() { - let unmodified_entry_and_expiration = ledger_storage + for key in (&footprint).read_only.as_slice() { + let unmodified_entry_and_ttl = ledger_storage .get(key, false) .with_context(|| format!("cannot find bump footprint ledger entry with key {key:?}"))?; - let size = (key.to_xdr()?.len() + unmodified_entry_and_expiration.0.to_xdr()?.len()) as u32; - let expirable_entry: Box = (&unmodified_entry_and_expiration) - .try_into() - .map_err(|e: String| { - Error::msg(e.clone()).context("incorrect ledger entry type in footprint") - })?; - let new_expiration_ledger = current_ledger_seq + ledgers_to_expire; - if new_expiration_ledger <= expirable_entry.expiration_ledger_seq() { + let size = (key.to_xdr()?.len() + unmodified_entry_and_ttl.0.to_xdr()?.len()) as u32; + let ttl_entry: Box = + (&unmodified_entry_and_ttl) + .try_into() + .map_err(|e: String| { + Error::msg(e.clone()).context("incorrect ledger entry type in footprint") + })?; + let new_live_until_ledger = current_ledger_seq + extend_to; + if new_live_until_ledger <= ttl_entry.live_until_ledger_seq() { // The bump would be ineffective continue; } let rent_change = LedgerEntryRentChange { - is_persistent: expirable_entry.durability() == Persistent, + is_persistent: ttl_entry.durability() == Persistent, old_size_bytes: size, new_size_bytes: size, - old_expiration_ledger: expirable_entry.expiration_ledger_seq(), - new_expiration_ledger, + old_live_until_ledger: ttl_entry.live_until_ledger_seq(), + new_live_until_ledger, }; rent_changes.push(rent_change); } @@ -419,20 +406,20 @@ pub(crate) fn compute_restore_footprint_transaction_data_and_min_fee( bucket_list_size: u64, current_ledger_seq: u32, ) -> Result<(SorobanTransactionData, i64)> { - let ConfigSettingEntry::StateExpiration(state_expiration) = - ledger_storage.get_configuration_setting(ConfigSettingId::StateExpiration)? + let ConfigSettingEntry::StateArchival(state_archival) = + ledger_storage.get_configuration_setting(ConfigSettingId::StateArchival)? else { - bail!("unexpected config setting entry for StateExpiration key"); + bail!("unexpected config setting entry for StateArchival key"); }; let rent_changes = compute_restore_footprint_rent_changes( &footprint, ledger_storage, - state_expiration.min_persistent_entry_expiration, + state_archival.min_persistent_ttl, current_ledger_seq, ) .context("cannot compute restore rent changes")?; - let expiration_bytes = calculate_expiration_entry_bytes(footprint.read_write.as_vec()); + let ttl_bytes: u32 = calculate_ttl_entry_bytes(footprint.read_write.as_vec()); let write_bytes = calculate_unmodified_ledger_entry_bytes( footprint.read_write.as_vec(), ledger_storage, @@ -442,7 +429,7 @@ pub(crate) fn compute_restore_footprint_transaction_data_and_min_fee( let soroban_resources = SorobanResources { footprint, instructions: 0, - read_bytes: write_bytes + expiration_bytes, + read_bytes: write_bytes + ttl_bytes, write_bytes, }; let transaction_size_bytes = estimate_max_transaction_size_for_operation( @@ -475,37 +462,38 @@ pub(crate) fn compute_restore_footprint_transaction_data_and_min_fee( fn compute_restore_footprint_rent_changes( footprint: &LedgerFootprint, ledger_storage: &LedgerStorage, - min_persistent_entry_expiration: u32, + min_persistent_ttl: u32, current_ledger_seq: u32, ) -> Result> { let mut rent_changes: Vec = Vec::with_capacity(footprint.read_write.len()); for key in footprint.read_write.as_vec() { - let unmodified_entry_and_expiration = ledger_storage.get(key, true).with_context(|| { + let unmodified_entry_and_ttl = ledger_storage.get(key, true).with_context(|| { format!("cannot find restore footprint ledger entry with key {key:?}") })?; - let size = (key.to_xdr()?.len() + unmodified_entry_and_expiration.0.to_xdr()?.len()) as u32; - let expirable_entry: Box = (&unmodified_entry_and_expiration) - .try_into() - .map_err(|e: String| { - Error::msg(e.clone()).context("incorrect ledger entry type in footprint") - })?; + let size = (key.to_xdr()?.len() + unmodified_entry_and_ttl.0.to_xdr()?.len()) as u32; + let ttl_entry: Box = + (&unmodified_entry_and_ttl) + .try_into() + .map_err(|e: String| { + Error::msg(e.clone()).context("incorrect ledger entry type in footprint") + })?; ensure!( - expirable_entry.durability() == Persistent, + ttl_entry.durability() == Persistent, "non-persistent entry in footprint: key = {key:?}" ); - if !expirable_entry.has_expired(current_ledger_seq) { - // noop (the entry hadn't expired) + if ttl_entry.is_live(current_ledger_seq) { + // noop (the entry is alive) continue; } - let new_expiration_ledger = - get_restored_ledger_sequence(current_ledger_seq, min_persistent_entry_expiration); + let new_live_until_ledger = + get_restored_ledger_sequence(current_ledger_seq, min_persistent_ttl); let rent_change = LedgerEntryRentChange { is_persistent: true, old_size_bytes: 0, new_size_bytes: size, - old_expiration_ledger: 0, - new_expiration_ledger, + old_live_until_ledger: 0, + new_live_until_ledger, }; rent_changes.push(rent_change); } diff --git a/cmd/soroban-rpc/lib/preflight/src/ledger_storage.rs b/cmd/soroban-rpc/lib/preflight/src/ledger_storage.rs index 4eac57269..276252d76 100644 --- a/cmd/soroban-rpc/lib/preflight/src/ledger_storage.rs +++ b/cmd/soroban-rpc/lib/preflight/src/ledger_storage.rs @@ -2,12 +2,12 @@ use sha2::Digest; use soroban_env_host::storage::SnapshotSource; use soroban_env_host::xdr::ContractDataDurability::{Persistent, Temporary}; use soroban_env_host::xdr::{ - ConfigSettingEntry, ConfigSettingId, Error as XdrError, ExpirationEntry, Hash, LedgerEntry, - LedgerEntryData, LedgerKey, LedgerKeyConfigSetting, LedgerKeyExpiration, ReadXdr, ScError, - ScErrorCode, WriteXdr, + ConfigSettingEntry, ConfigSettingId, Error as XdrError, Hash, LedgerEntry, LedgerEntryData, + LedgerKey, LedgerKeyConfigSetting, LedgerKeyTtl, ReadXdr, ScError, ScErrorCode, TtlEntry, + WriteXdr, }; use soroban_env_host::HostError; -use state_expiration::{get_restored_ledger_sequence, has_expired, ExpirableLedgerEntry}; +use state_ttl::{get_restored_ledger_sequence, is_live, TTLLedgerEntry}; use std::cell::RefCell; use std::collections::HashSet; use std::convert::TryInto; @@ -28,8 +28,8 @@ extern "C" { pub(crate) enum Error { #[error("not found")] NotFound, - #[error("entry expired")] - EntryExpired, + #[error("entry is not live")] + NotLive, #[error("xdr processing error: {0}")] Xdr(#[from] XdrError), #[error("nul error: {0}")] @@ -38,16 +38,14 @@ pub(crate) enum Error { Utf8Error(#[from] Utf8Error), #[error("unexpected config ledger entry for setting_id {setting_id}")] UnexpectedConfigLedgerEntry { setting_id: String }, - #[error("unexpected ledger entry type ({ledger_entry_type}) for expiration ledger key")] - UnexpectedLedgerEntryTypeForExpirationKey { ledger_entry_type: String }, + #[error("unexpected ledger entry type ({ledger_entry_type}) for ttl ledger key")] + UnexpectedLedgerEntryTypeForTtlKey { ledger_entry_type: String }, } impl From for HostError { fn from(value: Error) -> Self { match value { - Error::NotFound | Error::EntryExpired => { - ScError::Storage(ScErrorCode::MissingValue).into() - } + Error::NotFound | Error::NotLive => ScError::Storage(ScErrorCode::MissingValue).into(), Error::Xdr(_) => ScError::Value(ScErrorCode::InvalidInput).into(), _ => ScError::Context(ScErrorCode::InternalError).into(), } @@ -55,39 +53,37 @@ impl From for HostError { } struct EntryRestoreTracker { - min_persistent_entry_expiration: u32, + min_persistent_ttl: u32, // RefCell is needed to mutate the hashset inside SnapshotSource::get(), which is an immutable method ledger_keys_requiring_restore: RefCell>, } impl EntryRestoreTracker { - // Tracks ledger entries which need to be restored and returns its expiration as it was restored + // Tracks ledger entries which need to be restored and returns its ttl as it was restored pub(crate) fn track_and_restore( &self, current_ledger_sequence: u32, key: &LedgerKey, - entry_and_expiration: &(LedgerEntry, Option), + entry_and_ttl: &(LedgerEntry, Option), ) -> Option { - let expirable_entry: Box = match entry_and_expiration.try_into() { + let ttl_entry: Box = match entry_and_ttl.try_into() { Ok(e) => e, Err(_) => { - // Nothing to track, the entry isn't expirable + // Nothing to track, the entry does not have a ttl return None; } }; - if expirable_entry.durability() != Persistent - || !expirable_entry.has_expired(current_ledger_sequence) - { + if ttl_entry.durability() != Persistent || ttl_entry.is_live(current_ledger_sequence) { // Nothing to track, the entry isn't persistent (and thus not restorable) or - // it hasn't expired - return Some(expirable_entry.expiration_ledger_seq()); + // it is alive + return Some(ttl_entry.live_until_ledger_seq()); } self.ledger_keys_requiring_restore .borrow_mut() .insert(key.clone()); Some(get_restored_ledger_sequence( current_ledger_sequence, - self.min_persistent_entry_expiration, + self.min_persistent_ttl, )) } } @@ -117,23 +113,23 @@ impl LedgerStorage { current_ledger_sequence, restore_tracker: None, }; - let setting_id = ConfigSettingId::StateExpiration; - let ConfigSettingEntry::StateExpiration(state_expiration) = + let setting_id = ConfigSettingId::StateArchival; + let ConfigSettingEntry::StateArchival(state_archival) = ledger_storage.get_configuration_setting(setting_id)? else { return Err(Error::UnexpectedConfigLedgerEntry { setting_id: setting_id.name().to_string(), }); }; - // Now that we have the state expiration config, we can build the tracker + // Now that we have the state archival config, we can build the tracker ledger_storage.restore_tracker = Some(EntryRestoreTracker { ledger_keys_requiring_restore: RefCell::new(HashSet::new()), - min_persistent_entry_expiration: state_expiration.min_persistent_entry_expiration, + min_persistent_ttl: state_archival.min_persistent_ttl, }); Ok(ledger_storage) } - // Get the XDR, regardless of expiration + // Get the XDR, regardless of ttl fn get_xdr_internal(&self, key_xdr: &mut Vec) -> Result, Error> { let key_c_xdr = CXDR { xdr: key_xdr.as_mut_ptr(), @@ -151,52 +147,56 @@ impl LedgerStorage { pub(crate) fn get( &self, key: &LedgerKey, - include_expired: bool, + include_not_live: bool, ) -> Result<(LedgerEntry, Option), Error> { let mut key_xdr = key.to_xdr()?; let xdr = self.get_xdr_internal(&mut key_xdr)?; - let expiration_seq = match key { + let live_until_ledger_seq = match key { // TODO: it would probably be more efficient to do all of this in the Go side // (e.g. it would allow us to query multiple entries at once) LedgerKey::ContractData(_) | LedgerKey::ContractCode(_) => { let key_hash: [u8; 32] = sha2::Sha256::digest(key_xdr).into(); - let expiration_key = LedgerKey::Expiration(LedgerKeyExpiration { + let ttl_key = LedgerKey::Ttl(LedgerKeyTtl { key_hash: Hash(key_hash), }); - let mut expiration_key_xdr = expiration_key.to_xdr()?; - let expiration_entry_xdr = self.get_xdr_internal(&mut expiration_key_xdr)?; - let expiration_entry = LedgerEntry::from_xdr(expiration_entry_xdr)?; - if let LedgerEntryData::Expiration(ExpirationEntry { - expiration_ledger_seq, + let mut ttl_key_xdr = ttl_key.to_xdr()?; + let ttl_entry_xdr = self.get_xdr_internal(&mut ttl_key_xdr)?; + let ttl_entry = LedgerEntry::from_xdr(ttl_entry_xdr)?; + if let LedgerEntryData::Ttl(TtlEntry { + live_until_ledger_seq, .. - }) = expiration_entry.data + }) = ttl_entry.data { - Some(expiration_ledger_seq) + Some(live_until_ledger_seq) } else { - return Err(Error::UnexpectedLedgerEntryTypeForExpirationKey { - ledger_entry_type: expiration_entry.data.name().to_string(), + return Err(Error::UnexpectedLedgerEntryTypeForTtlKey { + ledger_entry_type: ttl_entry.data.name().to_string(), }); } } _ => None, }; - if !include_expired - && expiration_seq.is_some() - && has_expired(expiration_seq.unwrap(), self.current_ledger_sequence) + if !include_not_live + && live_until_ledger_seq.is_some() + && !is_live(live_until_ledger_seq.unwrap(), self.current_ledger_sequence) { - return Err(Error::EntryExpired); + return Err(Error::NotLive); } let entry = LedgerEntry::from_xdr(xdr)?; - Ok((entry, expiration_seq)) + Ok((entry, live_until_ledger_seq)) } - pub(crate) fn get_xdr(&self, key: &LedgerKey, include_expired: bool) -> Result, Error> { + pub(crate) fn get_xdr( + &self, + key: &LedgerKey, + include_not_live: bool, + ) -> Result, Error> { // TODO: this can be optimized since for entry types other than ContractCode/ContractData, // they don't need to be deserialized and serialized again - let (entry, _) = self.get(key, include_expired)?; + let (entry, _) = self.get(key, include_not_live)?; Ok(entry.to_xdr()?) } @@ -232,25 +232,22 @@ impl LedgerStorage { impl SnapshotSource for LedgerStorage { fn get(&self, key: &Rc) -> Result<(Rc, Option), HostError> { if let Some(ref tracker) = self.restore_tracker { - let mut entry_and_expiration = self.get(key, true)?; - // Explicitly discard temporary expired entries - if let Ok(expirable_entry) = - TryInto::>::try_into(&entry_and_expiration) - { - if expirable_entry.durability() == Temporary - && expirable_entry.has_expired(self.current_ledger_sequence) + let mut entry_and_ttl = self.get(key, true)?; + // Explicitly discard temporary ttl'ed entries + if let Ok(ttl_entry) = TryInto::>::try_into(&entry_and_ttl) { + if ttl_entry.durability() == Temporary + && !ttl_entry.is_live(self.current_ledger_sequence) { - return Err(HostError::from(Error::EntryExpired)); + return Err(HostError::from(Error::NotLive)); } } - // If the entry expired, we modify the expiration to make it seem like it was restored - entry_and_expiration.1 = - tracker.track_and_restore(self.current_ledger_sequence, key, &entry_and_expiration); - return Ok((entry_and_expiration.0.into(), entry_and_expiration.1)); + // If the entry is not live, we modify the ttl to make it seem like it was restored + entry_and_ttl.1 = + tracker.track_and_restore(self.current_ledger_sequence, key, &entry_and_ttl); + return Ok((entry_and_ttl.0.into(), entry_and_ttl.1)); } - let entry_and_expiration = - ::get(self, key, false).map_err(HostError::from)?; - Ok((entry_and_expiration.0.into(), entry_and_expiration.1)) + let entry_and_ttl = ::get(self, key, false).map_err(HostError::from)?; + return Ok((entry_and_ttl.0.into(), entry_and_ttl.1)); } fn has(&self, key: &Rc) -> Result { diff --git a/cmd/soroban-rpc/lib/preflight/src/lib.rs b/cmd/soroban-rpc/lib/preflight/src/lib.rs index 18a1976a8..98a4ebb33 100644 --- a/cmd/soroban-rpc/lib/preflight/src/lib.rs +++ b/cmd/soroban-rpc/lib/preflight/src/lib.rs @@ -1,7 +1,7 @@ mod fees; mod ledger_storage; mod preflight; -mod state_expiration; +mod state_ttl; extern crate anyhow; extern crate base64; @@ -30,9 +30,9 @@ pub struct CLedgerInfo { pub timestamp: u64, pub network_passphrase: *const libc::c_char, pub base_reserve: u32, - pub min_temp_entry_expiration: u32, - pub min_persistent_entry_expiration: u32, - pub max_entry_expiration: u32, + pub min_temp_entry_ttl: u32, + pub min_persistent_entry_ttl: u32, + pub max_entry_ttl: u32, } impl From for LedgerInfo { @@ -44,9 +44,9 @@ impl From for LedgerInfo { timestamp: c.timestamp, network_id: Sha256::digest(network_passphrase).into(), base_reserve: c.base_reserve, - min_temp_entry_expiration: c.min_temp_entry_expiration, - min_persistent_entry_expiration: c.min_persistent_entry_expiration, - max_entry_expiration: c.max_entry_expiration, + min_temp_entry_ttl: c.min_temp_entry_ttl, + min_persistent_entry_ttl: c.min_persistent_entry_ttl, + max_entry_ttl: c.max_entry_ttl, } } } @@ -167,7 +167,7 @@ fn preflight_invoke_hf_op_or_maybe_panic( } #[no_mangle] -pub extern "C" fn preflight_footprint_expiration_op( +pub extern "C" fn preflight_footprint_ttl_op( handle: libc::uintptr_t, // Go Handle to forward to SnapshotSourceGet and SnapshotSourceHas bucket_list_size: u64, // Bucket list size for current ledger op_body: CXDR, // OperationBody XDR @@ -175,7 +175,7 @@ pub extern "C" fn preflight_footprint_expiration_op( current_ledger_seq: u32, ) -> *mut CPreflightResult { catch_preflight_panic(Box::new(move || { - preflight_footprint_expiration_op_or_maybe_panic( + preflight_footprint_ttl_op_or_maybe_panic( handle, bucket_list_size, op_body, @@ -185,7 +185,7 @@ pub extern "C" fn preflight_footprint_expiration_op( })) } -fn preflight_footprint_expiration_op_or_maybe_panic( +fn preflight_footprint_ttl_op_or_maybe_panic( handle: libc::uintptr_t, bucket_list_size: u64, op_body: CXDR, @@ -195,7 +195,7 @@ fn preflight_footprint_expiration_op_or_maybe_panic( let op_body = OperationBody::from_xdr(from_c_xdr(op_body)).unwrap(); let footprint = LedgerFootprint::from_xdr(from_c_xdr(footprint)).unwrap(); let ledger_storage = &LedgerStorage::new(handle, current_ledger_seq); - let result = preflight::preflight_footprint_expiration_op( + let result = preflight::preflight_footprint_ttl_op( ledger_storage, bucket_list_size, op_body, diff --git a/cmd/soroban-rpc/lib/preflight/src/preflight.rs b/cmd/soroban-rpc/lib/preflight/src/preflight.rs index c6c5ac0e4..012316601 100644 --- a/cmd/soroban-rpc/lib/preflight/src/preflight.rs +++ b/cmd/soroban-rpc/lib/preflight/src/preflight.rs @@ -238,7 +238,7 @@ fn get_budget_from_network_config_params(ledger_storage: &LedgerStorage) -> Resu Ok(budget) } -pub(crate) fn preflight_footprint_expiration_op( +pub(crate) fn preflight_footprint_ttl_op( ledger_storage: &LedgerStorage, bucket_list_size: u64, op_body: OperationBody, @@ -246,9 +246,9 @@ pub(crate) fn preflight_footprint_expiration_op( current_ledger_seq: u32, ) -> Result { match op_body { - OperationBody::BumpFootprintExpiration(op) => preflight_bump_footprint_expiration( + OperationBody::ExtendFootprintTtl(op) => preflight_extend_footprint_ttl( footprint, - op.ledgers_to_expire, + op.extend_to, ledger_storage, bucket_list_size, current_ledger_seq, @@ -260,23 +260,23 @@ pub(crate) fn preflight_footprint_expiration_op( current_ledger_seq, ), op => Err(anyhow!( - "preflight_footprint_expiration_op(): unsupported operation type {}", + "preflight_footprint_ttl_op(): unsupported operation type {}", op.name() )), } } -fn preflight_bump_footprint_expiration( +fn preflight_extend_footprint_ttl( footprint: LedgerFootprint, - ledgers_to_expire: u32, + extend_to: u32, ledger_storage: &LedgerStorage, bucket_list_size: u64, current_ledger_seq: u32, ) -> Result { let (transaction_data, min_fee) = - fees::compute_bump_footprint_exp_transaction_data_and_min_fee( + fees::compute_extend_footprint_ttl_transaction_data_and_min_fee( footprint, - ledgers_to_expire, + extend_to, ledger_storage, bucket_list_size, current_ledger_seq, diff --git a/cmd/soroban-rpc/lib/preflight/src/state_expiration.rs b/cmd/soroban-rpc/lib/preflight/src/state_expiration.rs deleted file mode 100644 index c5a485f1f..000000000 --- a/cmd/soroban-rpc/lib/preflight/src/state_expiration.rs +++ /dev/null @@ -1,70 +0,0 @@ -use soroban_env_host::xdr::ContractDataDurability::Persistent; -use soroban_env_host::xdr::{ - ContractCodeEntry, ContractDataDurability, ContractDataEntry, LedgerEntry, LedgerEntryData, -}; -use std::convert::TryInto; - -pub(crate) trait ExpirableLedgerEntry { - fn durability(&self) -> ContractDataDurability; - fn expiration_ledger_seq(&self) -> u32; - fn has_expired(&self, current_ledger_seq: u32) -> bool { - has_expired(self.expiration_ledger_seq(), current_ledger_seq) - } -} - -impl ExpirableLedgerEntry for (&ContractCodeEntry, u32) { - fn durability(&self) -> ContractDataDurability { - Persistent - } - - fn expiration_ledger_seq(&self) -> u32 { - self.1 - } -} - -impl ExpirableLedgerEntry for (&ContractDataEntry, u32) { - fn durability(&self) -> ContractDataDurability { - self.0.durability - } - - fn expiration_ledger_seq(&self) -> u32 { - self.1 - } -} - -// Convert a ledger entry and its expiration into an ExpirableLedgerEntry -impl<'a> TryInto> for &'a (LedgerEntry, Option) { - type Error = String; - - fn try_into(self) -> Result, Self::Error> { - match (&self.0.data, self.1) { - (LedgerEntryData::ContractData(d), Some(expiration_seq)) => { - Ok(Box::new((d, expiration_seq))) - } - (LedgerEntryData::ContractCode(c), Some(expiration_seq)) => { - Ok(Box::new((c, expiration_seq))) - } - (LedgerEntryData::ContractData(_) | LedgerEntryData::ContractCode(_), _) => { - Err(format!( - "missing expiration for expirable ledger entry ({})", - self.0.data.name() - )) - } - _ => Err(format!( - "ledger entry type ({}) is not expirable", - self.0.data.name() - )), - } - } -} - -pub(crate) fn has_expired(expiration_ledger_seq: u32, current_ledger_seq: u32) -> bool { - current_ledger_seq > expiration_ledger_seq -} - -pub(crate) fn get_restored_ledger_sequence( - current_ledger_seq: u32, - min_persistent_entry_expiration: u32, -) -> u32 { - current_ledger_seq + min_persistent_entry_expiration - 1 -} diff --git a/cmd/soroban-rpc/lib/preflight/src/state_ttl.rs b/cmd/soroban-rpc/lib/preflight/src/state_ttl.rs new file mode 100644 index 000000000..bd436b066 --- /dev/null +++ b/cmd/soroban-rpc/lib/preflight/src/state_ttl.rs @@ -0,0 +1,67 @@ +use soroban_env_host::xdr::ContractDataDurability::Persistent; +use soroban_env_host::xdr::{ + ContractCodeEntry, ContractDataDurability, ContractDataEntry, LedgerEntry, LedgerEntryData, +}; +use std::convert::TryInto; + +pub(crate) trait TTLLedgerEntry { + fn durability(&self) -> ContractDataDurability; + fn live_until_ledger_seq(&self) -> u32; + fn is_live(&self, current_ledger_seq: u32) -> bool { + is_live(self.live_until_ledger_seq(), current_ledger_seq) + } +} + +impl TTLLedgerEntry for (&ContractCodeEntry, u32) { + fn durability(&self) -> ContractDataDurability { + Persistent + } + + fn live_until_ledger_seq(&self) -> u32 { + self.1 + } +} + +impl TTLLedgerEntry for (&ContractDataEntry, u32) { + fn durability(&self) -> ContractDataDurability { + self.0.durability + } + + fn live_until_ledger_seq(&self) -> u32 { + self.1 + } +} + +// Convert a ledger entry and its Time to live (i.e. live_until_seq) into a TTLLedgerEntry +impl<'a> TryInto> for &'a (LedgerEntry, Option) { + type Error = String; + + fn try_into(self) -> Result, Self::Error> { + match (&self.0.data, self.1) { + (LedgerEntryData::ContractData(d), Some(live_until_seq)) => { + Ok(Box::new((d, live_until_seq))) + } + (LedgerEntryData::ContractCode(c), Some(live_until_seq)) => { + Ok(Box::new((c, live_until_seq))) + } + (LedgerEntryData::ContractData(_) | LedgerEntryData::ContractCode(_), _) => Err( + format!("missing ttl for ledger entry ({})", self.0.data.name()), + ), + _ => Err(format!( + "ledger entry type ({}) cannot have a TTL", + self.0.data.name() + )), + } + } +} + +pub(crate) fn is_live(live_until_ledger_seq: u32, current_ledger_seq: u32) -> bool { + live_until_ledger_seq >= current_ledger_seq +} + +pub(crate) fn get_restored_ledger_sequence( + current_ledger_seq: u32, + min_persistent_ttl: u32, +) -> u32 { + current_ledger_seq + min_persistent_ttl - 1; +} diff --git a/go.mod b/go.mod index fa812f3d1..deafdcfd3 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stellar/go v0.0.0-20231016131404-dc8a5c304cce + github.com/stellar/go v0.0.0-20231016155130-3fcefd39bb2a github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.12.0 gotest.tools/v3 v3.5.0 diff --git a/go.sum b/go.sum index 141c4df46..71bfcc49e 100644 --- a/go.sum +++ b/go.sum @@ -189,8 +189,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/stellar/go v0.0.0-20231016131404-dc8a5c304cce h1:p+JZNTwrdHMjuaGMzq3jlue4W0w+G3KC5AGp46O3ymQ= -github.com/stellar/go v0.0.0-20231016131404-dc8a5c304cce/go.mod h1:g78pyZyDFnKMJUaBIXxH7xyQ7PdDrvrJTFCxdGMMb3c= +github.com/stellar/go v0.0.0-20231016155130-3fcefd39bb2a h1:/uOQTCtZbN0UQovF8d4XaNLKPYk9L7hY+hrHiXf3gS8= +github.com/stellar/go v0.0.0-20231016155130-3fcefd39bb2a/go.mod h1:g78pyZyDFnKMJUaBIXxH7xyQ7PdDrvrJTFCxdGMMb3c= github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206 h1:UFuvvpbWL8+jqO1QmKYWSVhiMp4MRiIFd8/zQlUINH0= github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 47cc52e993703c1bf57beb2d6899f47ced975c80 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 16 Oct 2023 18:40:26 +0200 Subject: [PATCH 03/14] Update stellar core image to my personal repo (since it failed to build) --- cmd/soroban-rpc/internal/test/docker-compose.yml | 2 +- cmd/soroban-rpc/lib/preflight/src/state_ttl.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/test/docker-compose.yml b/cmd/soroban-rpc/internal/test/docker-compose.yml index 4f7949002..bac17e52e 100644 --- a/cmd/soroban-rpc/internal/test/docker-compose.yml +++ b/cmd/soroban-rpc/internal/test/docker-compose.yml @@ -15,7 +15,7 @@ services: # Note: Please keep the image pinned to an immutable tag matching the Captive Core version. # This avoids implicit updates which break compatibility between # the Core container and captive core. - image: ${CORE_IMAGE:-stellar/stellar-core:19.14.1-1529.fcbbad4ce.focal} + image: ${CORE_IMAGE:-2opremio/stellar-core:19.14.1-1529.fcbbad4ce.focal} depends_on: - core-postgres restart: on-failure diff --git a/cmd/soroban-rpc/lib/preflight/src/state_ttl.rs b/cmd/soroban-rpc/lib/preflight/src/state_ttl.rs index bd436b066..5373177c9 100644 --- a/cmd/soroban-rpc/lib/preflight/src/state_ttl.rs +++ b/cmd/soroban-rpc/lib/preflight/src/state_ttl.rs @@ -63,5 +63,5 @@ pub(crate) fn get_restored_ledger_sequence( current_ledger_seq: u32, min_persistent_ttl: u32, ) -> u32 { - current_ledger_seq + min_persistent_ttl - 1; + current_ledger_seq + min_persistent_ttl - 1 } From 6edac55eae09449278014e9695762f6ef697441a Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 16 Oct 2023 19:35:00 +0200 Subject: [PATCH 04/14] Disable soroban diagnostic events on the validator node --- cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg b/cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg index 4c72db24a..594a35b24 100644 --- a/cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg +++ b/cmd/soroban-rpc/internal/test/stellar-core-integration-tests.cfg @@ -14,7 +14,6 @@ FAILURE_SAFETY=0 DATABASE="postgresql://user=postgres password=mysecretpassword host=core-postgres port=5641 dbname=stellar" -ENABLE_SOROBAN_DIAGNOSTIC_EVENTS=true # Lower the TTL of persistent ledger entries # so that ledger entry extension/restoring becomes testeable TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 From f13f3b0d6f8f85770f697574da0a8728e485c83d Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 16 Oct 2023 19:39:29 +0200 Subject: [PATCH 05/14] Fix test --- cmd/soroban-rpc/internal/test/simulate_transaction_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index e5595f271..60efcb36e 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -236,7 +236,7 @@ func TestSimulateTransactionSucceeds(t *testing.T) { ReadBytes: 48, WriteBytes: 7048, }, - ResourceFee: 20056, + ResourceFee: 130498, } // First, decode and compare the transaction data so we get a decent diff if it fails. From a0a803ac26922f0dc1a912f80e0c557048dea9c6 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 16 Oct 2023 19:41:40 +0200 Subject: [PATCH 06/14] Minor renamings --- cmd/soroban-rpc/internal/test/simulate_transaction_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index 60efcb36e..2958ca0c2 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -669,7 +669,7 @@ func TestSimulateTransactionUnmarshalError(t *testing.T) { ) } -func TestSimulateTransactionBumpAndRestoreFootprint(t *testing.T) { +func TestSimulateTransactionExtendAndRestoreFootprint(t *testing.T) { test := NewTest(t) ch := jhttp.NewChannel(test.sorobanRPCURL(), nil) @@ -751,7 +751,7 @@ func TestSimulateTransactionBumpAndRestoreFootprint(t *testing.T) { initialLiveUntil := *getLedgerEntryResult.LiveUntilLedgerSeq - // bump the initial TTL + // Extend the initial TTL params = preflightTransactionParams(t, client, txnbuild.TransactionParams{ SourceAccount: &account, IncrementSequenceNum: true, From 83ed10a1cf2aa9f41b515383681b7905af5492c4 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 16 Oct 2023 19:50:22 +0200 Subject: [PATCH 07/14] Bump stellar/go dependency again --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index deafdcfd3..536639743 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stellar/go v0.0.0-20231016155130-3fcefd39bb2a + github.com/stellar/go v0.0.0-20231016174715-c7d3a47ee7a2 github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.12.0 gotest.tools/v3 v3.5.0 diff --git a/go.sum b/go.sum index 71bfcc49e..1a7a5119d 100644 --- a/go.sum +++ b/go.sum @@ -189,8 +189,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/stellar/go v0.0.0-20231016155130-3fcefd39bb2a h1:/uOQTCtZbN0UQovF8d4XaNLKPYk9L7hY+hrHiXf3gS8= -github.com/stellar/go v0.0.0-20231016155130-3fcefd39bb2a/go.mod h1:g78pyZyDFnKMJUaBIXxH7xyQ7PdDrvrJTFCxdGMMb3c= +github.com/stellar/go v0.0.0-20231016174715-c7d3a47ee7a2 h1:IOOHd1yrwmK0wiAuNDmoHUPTucO0oGkkKa3CE1pgn2E= +github.com/stellar/go v0.0.0-20231016174715-c7d3a47ee7a2/go.mod h1:g78pyZyDFnKMJUaBIXxH7xyQ7PdDrvrJTFCxdGMMb3c= github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206 h1:UFuvvpbWL8+jqO1QmKYWSVhiMp4MRiIFd8/zQlUINH0= github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 054b61656759a76e66a031c83a8e1541c07528b1 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 17 Oct 2023 14:48:32 +0200 Subject: [PATCH 08/14] Fix test --- cmd/soroban-rpc/internal/test/simulate_transaction_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index 2958ca0c2..92ca41d89 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -538,7 +538,6 @@ func TestSimulateInvokeContractTransactionSucceeds(t *testing.T) { assert.Len(t, event.Event.Body.V0.Topics, 1) assert.Equal(t, xdr.ScValTypeScvString, event.Event.Body.V0.Topics[0].Type) assert.Equal(t, xdr.ScString("auth"), *event.Event.Body.V0.Topics[0].Str) - metrics := getMetrics(test) 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") @@ -1122,7 +1121,7 @@ func TestSimulateSystemEvent(t *testing.T) { require.NoError(t, err) assert.InDelta(t, 7260, uint32(transactionData.Resources.ReadBytes), 200) - assert.InDelta(t, 45, int64(transactionData.ResourceFee), 10) + assert.InDelta(t, 98339, int64(transactionData.ResourceFee), 10) assert.InDelta(t, 104, uint32(transactionData.Resources.WriteBytes), 15) require.GreaterOrEqual(t, len(response.Events), 3) } From 5032bb37422574e62d6e6615140f8ef6f2a824de Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 17 Oct 2023 15:16:27 +0200 Subject: [PATCH 09/14] Upgrade chi to fix test --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 536639743..62feb34a4 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/squirrel v1.5.4 github.com/cenkalti/backoff/v4 v4.2.1 github.com/creachadair/jrpc2 v1.1.0 - github.com/go-chi/chi v4.0.3+incompatible + github.com/go-chi/chi v4.1.2+incompatible github.com/go-git/go-git/v5 v5.4.2 github.com/mattn/go-sqlite3 v1.14.17 github.com/pelletier/go-toml v1.9.5 diff --git a/go.sum b/go.sum index 1a7a5119d..19be596c9 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS github.com/gavv/monotime v0.0.0-20161010190848-47d58efa6955 h1:gmtGRvSexPU4B1T/yYo0sLOKzER1YT+b4kPxPpm0Ty4= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-chi/chi v4.0.3+incompatible h1:gakN3pDJnzZN5jqFV2TEdF66rTfKeITyR8qu6ekICEY= -github.com/go-chi/chi v4.0.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= +github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-errors/errors v0.0.0-20150906023321-a41850380601 h1:jxTbmDuqQUTI6MscgbqB39vtxGfr2fi61nYIcFQUnlE= github.com/go-errors/errors v0.0.0-20150906023321-a41850380601/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= From 21c21a529f4aaa2cae484546db4623ccfc94f449 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 17 Oct 2023 15:42:14 +0200 Subject: [PATCH 10/14] Fix test (the test was broken before) --- cmd/soroban-rpc/internal/test/simulate_transaction_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index 92ca41d89..b11f24769 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -830,6 +830,7 @@ func TestSimulateTransactionExtendAndRestoreFootprint(t *testing.T) { Operations: []txnbuild.Operation{ &txnbuild.RestoreFootprint{}, }, + BaseFee: txnbuild.MinBaseFee, Preconditions: txnbuild.Preconditions{ TimeBounds: txnbuild.NewInfiniteTimeout(), }, From b923796263db026e7983cf6b7d8f08038c4f423f Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 17 Oct 2023 15:58:49 +0200 Subject: [PATCH 11/14] Check output of cargo test --list --- cmd/soroban-rpc/internal/test/cli_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-rpc/internal/test/cli_test.go b/cmd/soroban-rpc/internal/test/cli_test.go index c1571d246..4229fc289 100644 --- a/cmd/soroban-rpc/internal/test/cli_test.go +++ b/cmd/soroban-rpc/internal/test/cli_test.go @@ -36,8 +36,9 @@ func cargoTest(t *testing.T, name string) { } func TestCLICargoTest(t *testing.T) { - names := icmd.RunCmd(icmd.Command("cargo", "-q", "test", "integration_and_sandbox::", "--package", "soroban-test", "--", "--list")) - input := names.Stdout() + result := icmd.RunCmd(icmd.Command("cargo", "-q", "test", "integration_and_sandbox::", "--package", "soroban-test", "--", "--list")) + require.NoError(t, result.Error) + input := result.Stdout() lines := strings.Split(input, "\n") for _, line := range lines { testName := strings.TrimSuffix(line, ": test") From ad282389f9033ae3418d944c092be36212c28c66 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Mon, 23 Oct 2023 10:41:34 -0400 Subject: [PATCH 12/14] fix(CLI): update xdr and bump -> extend (#1031) --- Cargo.toml | 2 +- cmd/crates/soroban-spec-json/src/lib.rs | 4 +- cmd/crates/soroban-spec-json/src/types.rs | 2 +- cmd/crates/soroban-spec-tools/src/lib.rs | 30 +- cmd/crates/soroban-spec-tools/src/utils.rs | 13 +- .../src/boilerplate.rs | 2 +- cmd/crates/soroban-spec-typescript/src/lib.rs | 4 +- .../soroban-spec-typescript/src/types.rs | 2 +- cmd/crates/soroban-test/Cargo.toml | 3 + cmd/crates/soroban-test/src/lib.rs | 11 +- cmd/crates/soroban-test/tests/it/config.rs | 24 +- .../soroban-test/tests/it/custom_types.rs | 497 ------------ .../soroban-test/tests/it/hello_world.rs | 461 ----------- cmd/crates/soroban-test/tests/it/help.rs | 97 +++ .../soroban-test/tests/it/integration.rs | 4 + .../tests/it/integration/custom_types.rs | 419 ++++++++++ .../tests/it/{ => integration}/dotenv.rs | 37 +- .../tests/it/integration/hello_world.rs | 290 +++++++ .../soroban-test/tests/it/integration/util.rs | 117 +++ .../tests/it/integration_and_sandbox.rs | 222 ------ cmd/crates/soroban-test/tests/it/main.rs | 8 +- cmd/crates/soroban-test/tests/it/util.rs | 117 +-- .../src/commands/config/events_file.rs | 236 ------ .../src/commands/config/ledger_file.rs | 55 -- cmd/soroban-cli/src/commands/config/mod.rs | 25 - .../commands/contract/bindings/typescript.rs | 8 +- .../src/commands/contract/deploy.rs | 41 +- .../commands/contract/{bump.rs => extend.rs} | 103 +-- .../src/commands/contract/fetch.rs | 28 +- .../src/commands/contract/install.rs | 32 +- .../src/commands/contract/invoke.rs | 205 +---- cmd/soroban-cli/src/commands/contract/mod.rs | 12 +- cmd/soroban-cli/src/commands/contract/read.rs | 39 +- .../src/commands/contract/restore.rs | 50 +- cmd/soroban-cli/src/commands/events.rs | 168 +--- .../src/commands/lab/token/wrap.rs | 41 +- cmd/soroban-cli/src/commands/mod.rs | 7 +- cmd/soroban-cli/src/key.rs | 6 +- cmd/soroban-cli/src/lib.rs | 1 - cmd/soroban-cli/src/network.rs | 8 - cmd/soroban-cli/src/rpc/mod.rs | 16 +- cmd/soroban-cli/src/rpc/transaction.rs | 2 +- cmd/soroban-cli/src/utils.rs | 266 +------ cmd/soroban-rpc/internal/events/cursor.go | 2 +- cmd/soroban-rpc/internal/jsonrpc.go | 7 +- cmd/soroban-rpc/internal/test/cli_test.go | 37 +- .../test/simulate_transaction_test.go | 6 +- cmd/soroban-rpc/lib/preflight/src/fees.rs | 15 +- .../lib/preflight/src/ledger_storage.rs | 2 +- docs/soroban-cli-full-docs.md | 62 +- go.mod | 105 +-- go.sum | 718 ++++++++++++++---- 52 files changed, 1821 insertions(+), 2848 deletions(-) delete mode 100644 cmd/crates/soroban-test/tests/it/custom_types.rs create mode 100644 cmd/crates/soroban-test/tests/it/help.rs create mode 100644 cmd/crates/soroban-test/tests/it/integration.rs create mode 100644 cmd/crates/soroban-test/tests/it/integration/custom_types.rs rename cmd/crates/soroban-test/tests/it/{ => integration}/dotenv.rs (63%) create mode 100644 cmd/crates/soroban-test/tests/it/integration/hello_world.rs create mode 100644 cmd/crates/soroban-test/tests/it/integration/util.rs delete mode 100644 cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs delete mode 100644 cmd/soroban-cli/src/commands/config/events_file.rs delete mode 100644 cmd/soroban-cli/src/commands/config/ledger_file.rs rename cmd/soroban-cli/src/commands/contract/{bump.rs => extend.rs} (60%) delete mode 100644 cmd/soroban-cli/src/network.rs diff --git a/Cargo.toml b/Cargo.toml index 99889cb26..7ccadcac0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ path = "cmd/soroban-cli" version = "20.0.0-rc1" git = "https://github.com/stellar/rs-stellar-xdr" rev = "9c97e4fa909a0b6455547a4f4a95800696b2a69a" -default-features = false +default-features = true [workspace.dependencies] base64 = "0.21.2" diff --git a/cmd/crates/soroban-spec-json/src/lib.rs b/cmd/crates/soroban-spec-json/src/lib.rs index e7310ccfd..cdc64665b 100644 --- a/cmd/crates/soroban-spec-json/src/lib.rs +++ b/cmd/crates/soroban-spec-json/src/lib.rs @@ -3,8 +3,8 @@ use std::{fs, io}; pub mod types; use sha2::{Digest, Sha256}; -use stellar_xdr::ScSpecEntry; +use stellar_xdr::curr::ScSpecEntry; use types::Entry; use soroban_spec::read::{from_wasm, FromWasmError}; @@ -16,7 +16,7 @@ pub enum GenerateFromFileError { #[error("sha256 does not match, expected: {expected}")] VerifySha256 { expected: String }, #[error("parsing contract spec: {0}")] - Parse(stellar_xdr::Error), + Parse(stellar_xdr::curr::Error), #[error("getting contract spec: {0}")] GetSpec(FromWasmError), } diff --git a/cmd/crates/soroban-spec-json/src/types.rs b/cmd/crates/soroban-spec-json/src/types.rs index 863132ca8..6fcc483e1 100644 --- a/cmd/crates/soroban-spec-json/src/types.rs +++ b/cmd/crates/soroban-spec-json/src/types.rs @@ -1,5 +1,5 @@ use serde::Serialize; -use stellar_xdr::{ +use stellar_xdr::curr::{ ScSpecEntry, ScSpecFunctionInputV0, ScSpecTypeDef, ScSpecUdtEnumCaseV0, ScSpecUdtErrorEnumCaseV0, ScSpecUdtStructFieldV0, ScSpecUdtUnionCaseV0, }; diff --git a/cmd/crates/soroban-spec-tools/src/lib.rs b/cmd/crates/soroban-spec-tools/src/lib.rs index 4458f30e2..a95bc9454 100644 --- a/cmd/crates/soroban-spec-tools/src/lib.rs +++ b/cmd/crates/soroban-spec-tools/src/lib.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use itertools::Itertools; use serde_json::{json, Value}; -use stellar_xdr::{ +use stellar_xdr::curr::{ AccountId, BytesM, ContractExecutable, Error as XdrError, Hash, Int128Parts, Int256Parts, PublicKey, ScAddress, ScBytes, ScContractInstance, ScMap, ScMapEntry, ScNonceKey, ScSpecEntry, ScSpecFunctionV0, ScSpecTypeDef as ScType, ScSpecTypeMap, ScSpecTypeOption, ScSpecTypeResult, @@ -1025,9 +1025,9 @@ pub fn to_json(v: &ScVal) -> Result { .. }) => json!({ "hash": hash }), ScVal::ContractInstance(ScContractInstance { - executable: ContractExecutable::Token, + executable: ContractExecutable::StellarAsset, .. - }) => json!({"token": true}), + }) => json!({"SAC": true}), ScVal::LedgerKeyNonce(ScNonceKey { nonce }) => { Value::Number(serde_json::Number::from(*nonce)) } @@ -1175,11 +1175,10 @@ impl Spec { .iter() .map(|f| { Some(match f { - stellar_xdr::ScSpecUdtUnionCaseV0::VoidV0(ScSpecUdtUnionCaseVoidV0 { - name, - .. - }) => name.to_string_lossy(), - stellar_xdr::ScSpecUdtUnionCaseV0::TupleV0(ScSpecUdtUnionCaseTupleV0 { + ScSpecUdtUnionCaseV0::VoidV0(ScSpecUdtUnionCaseVoidV0 { name, .. }) => { + name.to_string_lossy() + } + ScSpecUdtUnionCaseV0::TupleV0(ScSpecUdtUnionCaseTupleV0 { name, type_, .. @@ -1331,14 +1330,11 @@ impl Spec { .cases .iter() .map(|case| match case { - stellar_xdr::ScSpecUdtUnionCaseV0::VoidV0(ScSpecUdtUnionCaseVoidV0 { - name, - .. - }) => Some(format!("\"{}\"", name.to_string_lossy())), - stellar_xdr::ScSpecUdtUnionCaseV0::TupleV0(ScSpecUdtUnionCaseTupleV0 { - name, - type_, - .. + ScSpecUdtUnionCaseV0::VoidV0(ScSpecUdtUnionCaseVoidV0 { name, .. }) => { + Some(format!("\"{}\"", name.to_string_lossy())) + } + ScSpecUdtUnionCaseV0::TupleV0(ScSpecUdtUnionCaseTupleV0 { + name, type_, .. }) => { if type_.len() == 1 { let single = self.example(&type_[0])?; @@ -1362,7 +1358,7 @@ impl Spec { mod tests { use super::*; - use stellar_xdr::ScSpecTypeBytesN; + use stellar_xdr::curr::ScSpecTypeBytesN; #[test] fn from_json_primitives_bytesn() { diff --git a/cmd/crates/soroban-spec-tools/src/utils.rs b/cmd/crates/soroban-spec-tools/src/utils.rs index f53c24bc9..50cd5ee7a 100644 --- a/cmd/crates/soroban-spec-tools/src/utils.rs +++ b/cmd/crates/soroban-spec-tools/src/utils.rs @@ -5,7 +5,7 @@ use std::{ io::{self, Cursor}, }; -use stellar_xdr::{ +use stellar_xdr::curr::{ DepthLimitedRead, ReadXdr, ScEnvMetaEntry, ScMetaEntry, ScMetaV0, ScSpecEntry, ScSpecFunctionV0, ScSpecUdtEnumV0, ScSpecUdtErrorEnumV0, ScSpecUdtStructV0, ScSpecUdtUnionV0, StringM, @@ -33,7 +33,7 @@ pub enum Error { error: wasmparser::BinaryReaderError, }, #[error("xdr processing error: {0}")] - Xdr(#[from] stellar_xdr::Error), + Xdr(#[from] stellar_xdr::curr::Error), #[error(transparent)] Parser(#[from] wasmparser::BinaryReaderError), @@ -62,8 +62,7 @@ impl ContractSpec { env_meta_base64 = Some(base64.encode(env_meta)); let cursor = Cursor::new(env_meta); let mut depth_limit_read = DepthLimitedRead::new(cursor, 100); - ScEnvMetaEntry::read_xdr_iter(&mut depth_limit_read) - .collect::, stellar_xdr::Error>>()? + ScEnvMetaEntry::read_xdr_iter(&mut depth_limit_read).collect::, _>>()? } else { vec![] }; @@ -73,8 +72,7 @@ impl ContractSpec { meta_base64 = Some(base64.encode(meta)); let cursor = Cursor::new(meta); let mut depth_limit_read = DepthLimitedRead::new(cursor, 100); - ScMetaEntry::read_xdr_iter(&mut depth_limit_read) - .collect::, stellar_xdr::Error>>()? + ScMetaEntry::read_xdr_iter(&mut depth_limit_read).collect::, _>>()? } else { vec![] }; @@ -84,8 +82,7 @@ impl ContractSpec { spec_base64 = Some(base64.encode(spec)); let cursor = Cursor::new(spec); let mut depth_limit_read = DepthLimitedRead::new(cursor, 100); - ScSpecEntry::read_xdr_iter(&mut depth_limit_read) - .collect::, stellar_xdr::Error>>()? + ScSpecEntry::read_xdr_iter(&mut depth_limit_read).collect::, _>>()? } else { vec![] }; diff --git a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs index ae14ae476..95b690591 100644 --- a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs +++ b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs @@ -6,7 +6,7 @@ use std::{ io::Write, path::{Path, PathBuf}, }; -use stellar_xdr::ScSpecEntry; +use stellar_xdr::curr::ScSpecEntry; use super::generate; diff --git a/cmd/crates/soroban-spec-typescript/src/lib.rs b/cmd/crates/soroban-spec-typescript/src/lib.rs index 5e8f8f210..7dff04756 100644 --- a/cmd/crates/soroban-spec-typescript/src/lib.rs +++ b/cmd/crates/soroban-spec-typescript/src/lib.rs @@ -10,7 +10,7 @@ use crate::types::Type; use heck::ToLowerCamelCase; use itertools::Itertools; use sha2::{Digest, Sha256}; -use stellar_xdr::{ScSpecEntry, WriteXdr}; +use stellar_xdr::curr::{ScSpecEntry, WriteXdr}; use types::Entry; @@ -27,7 +27,7 @@ pub enum GenerateFromFileError { #[error("sha256 does not match, expected: {expected}")] VerifySha256 { expected: String }, #[error("parsing contract spec: {0}")] - Parse(stellar_xdr::Error), + Parse(stellar_xdr::curr::Error), #[error("getting contract spec: {0}")] GetSpec(FromWasmError), } diff --git a/cmd/crates/soroban-spec-typescript/src/types.rs b/cmd/crates/soroban-spec-typescript/src/types.rs index b70bb6836..350d41296 100644 --- a/cmd/crates/soroban-spec-typescript/src/types.rs +++ b/cmd/crates/soroban-spec-typescript/src/types.rs @@ -1,5 +1,5 @@ use serde::Serialize; -use stellar_xdr::{ +use stellar_xdr::curr::{ ScSpecEntry, ScSpecFunctionInputV0, ScSpecTypeDef, ScSpecUdtEnumCaseV0, ScSpecUdtErrorEnumCaseV0, ScSpecUdtStructFieldV0, ScSpecUdtStructV0, ScSpecUdtUnionCaseV0, }; diff --git a/cmd/crates/soroban-test/Cargo.toml b/cmd/crates/soroban-test/Cargo.toml index 6d157780b..e2a4d4d87 100644 --- a/cmd/crates/soroban-test/Cargo.toml +++ b/cmd/crates/soroban-test/Cargo.toml @@ -37,3 +37,6 @@ fs_extra = "1.3.0" serde_json = "1.0.93" which = { workspace = true } tokio = "1.28.1" + +[features] +integration = [] \ No newline at end of file diff --git a/cmd/crates/soroban-test/src/lib.rs b/cmd/crates/soroban-test/src/lib.rs index 7cf95c5b6..8ec628bf7 100644 --- a/cmd/crates/soroban-test/src/lib.rs +++ b/cmd/crates/soroban-test/src/lib.rs @@ -71,7 +71,7 @@ impl TestEnv { /// ```rust,no_run /// use soroban_test::TestEnv; /// TestEnv::with_default(|env| { - /// env.invoke(&["--id", "1", "--", "hello", "--world=world"]).unwrap(); + /// env.new_assert_cmd("contract").args(&["invoke", "--id", "1", "--", "hello", "--world=world"]).assert().success(); /// }); /// ``` /// @@ -122,7 +122,7 @@ impl TestEnv { } /// A convenience method for using the invoke command. - pub fn invoke>(&self, command_str: &[I]) -> Result { + pub async fn invoke>(&self, command_str: &[I]) -> Result { let cmd = contract::invoke::Cmd::parse_arg_vec( &command_str .iter() @@ -131,13 +131,13 @@ impl TestEnv { .collect::>(), ) .unwrap(); - self.invoke_cmd(cmd) + self.invoke_cmd(cmd).await } /// Invoke an already parsed invoke command - pub fn invoke_cmd(&self, mut cmd: invoke::Cmd) -> Result { + pub async fn invoke_cmd(&self, mut cmd: invoke::Cmd) -> Result { cmd.set_pwd(self.dir()); - cmd.run_in_sandbox(&global::Args { + cmd.run_against_rpc_server(&global::Args { locator: config::locator::Args { global: false, config_dir: None, @@ -148,6 +148,7 @@ impl TestEnv { very_verbose: false, list: false, }) + .await } /// Reference to current directory of the `TestEnv`. diff --git a/cmd/crates/soroban-test/tests/it/config.rs b/cmd/crates/soroban-test/tests/it/config.rs index 80bb0a574..a0a240af1 100644 --- a/cmd/crates/soroban-test/tests/it/config.rs +++ b/cmd/crates/soroban-test/tests/it/config.rs @@ -1,8 +1,8 @@ use assert_fs::TempDir; -use soroban_test::{temp_ledger_file, TestEnv}; +use soroban_test::TestEnv; use std::{fs, path::Path}; -use crate::util::{add_identity, add_test_id, SecretKind, DEFAULT_SEED_PHRASE, HELLO_WORLD}; +use crate::util::{add_identity, add_test_id, SecretKind, DEFAULT_SEED_PHRASE}; use soroban_cli::commands::config::network; const NETWORK_PASSPHRASE: &str = "Local Sandbox Stellar Network ; September 2022"; @@ -205,26 +205,6 @@ fn seed_phrase() { .stdout("test_seed\n"); } -#[test] -fn use_different_ledger_file() { - let sandbox = TestEnv::default(); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id=1") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--ledger-file") - .arg(temp_ledger_file()) - .arg("--") - .arg("hello") - .arg("--world=world") - .assert() - .stdout("[\"Hello\",\"world\"]\n") - .success(); - assert!(fs::read(sandbox.dir().join(".soroban/ledger.json")).is_err()); -} - #[test] fn read_address() { let sandbox = TestEnv::default(); diff --git a/cmd/crates/soroban-test/tests/it/custom_types.rs b/cmd/crates/soroban-test/tests/it/custom_types.rs deleted file mode 100644 index 839b326f5..000000000 --- a/cmd/crates/soroban-test/tests/it/custom_types.rs +++ /dev/null @@ -1,497 +0,0 @@ -use serde_json::json; - -use soroban_cli::commands; -use soroban_test::TestEnv; - -use crate::util::{invoke, invoke_with_roundtrip, CUSTOM_TYPES}; - -#[test] -fn symbol() { - invoke(&TestEnv::default(), "hello") - .arg("--hello") - .arg("world") - .assert() - .success() - .stdout( - r#""world" -"#, - ); -} - -#[test] -fn string_with_quotes() { - invoke_with_roundtrip("string", json!("hello world")); -} - -#[test] -fn symbol_with_quotes() { - invoke_with_roundtrip("hello", json!("world")); -} - -#[test] -fn generate_help() { - invoke(&TestEnv::default(), "strukt_hel") - .arg("--help") - .assert() - .success() - .stdout(predicates::str::contains( - "Example contract method which takes a struct", - )); -} - -#[test] -fn multi_arg_failure() { - invoke(&TestEnv::default(), "multi_args") - .arg("--b") - .assert() - .failure() - .stderr("error: Missing argument a\n"); -} - -#[test] -fn multi_arg_success() { - invoke(&TestEnv::default(), "multi_args") - .arg("--a") - .arg("42") - .arg("--b") - .assert() - .success() - .stdout("42\n"); -} - -#[test] -fn bytes_as_file() { - let env = &TestEnv::default(); - let path = env.temp_dir.join("bytes.txt"); - std::fs::write(&path, 0x0073_7465_6c6c_6172u128.to_be_bytes()).unwrap(); - invoke(env, "bytes") - .arg("--bytes-file-path") - .arg(path) - .assert() - .success() - .stdout("\"0000000000000000007374656c6c6172\"\n"); -} - -#[test] -fn map() { - invoke_with_roundtrip("map", json!({"0": true, "1": false})); -} - -#[test] -fn map_help() { - invoke(&TestEnv::default(), "map") - .arg("--help") - .assert() - .success() - .stdout(predicates::str::contains("Map")); -} - -#[test] -fn vec_() { - invoke_with_roundtrip("vec", json!([0, 1])); -} - -#[test] -fn vec_help() { - invoke(&TestEnv::default(), "vec") - .arg("--help") - .assert() - .success() - .stdout(predicates::str::contains("Array")); -} - -#[test] -fn tuple() { - invoke_with_roundtrip("tuple", json!(["hello", 0])); -} - -#[test] -fn tuple_help() { - invoke(&TestEnv::default(), "tuple") - .arg("--help") - .assert() - .success() - .stdout(predicates::str::contains("Tuple")); -} - -#[test] -fn strukt() { - invoke_with_roundtrip("strukt", json!({"a": 42, "b": true, "c": "world"})); -} - -#[test] -fn tuple_strukt() { - invoke_with_roundtrip( - "tuple_strukt", - json!([{"a": 42, "b": true, "c": "world"}, "First"]), - ); -} - -#[test] -fn strukt_help() { - invoke(&TestEnv::default(), "strukt") - .arg("--help") - .assert() - .stdout(predicates::str::contains( - "--strukt '{ \"a\": 1, \"b\": true, \"c\": \"hello\" }'", - )) - .stdout(predicates::str::contains( - "This is from the rust doc above the struct Test", - )); -} - -#[test] -fn complex_enum_help() { - invoke(&TestEnv::default(), "complex") - .arg("--help") - .assert() - .stdout(predicates::str::contains( - r#"--complex '{"Struct":{ "a": 1, "b": true, "c": "hello" }}"#, - )) - .stdout(predicates::str::contains( - r#"{"Tuple":[{ "a": 1, "b": true, "c": "hello" }"#, - )) - .stdout(predicates::str::contains( - r#"{"Enum":"First"|"Second"|"Third"}"#, - )) - .stdout(predicates::str::contains( - r#"{"Asset":["GDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCR4W4", "-100"]}"#, - )) - .stdout(predicates::str::contains(r#""Void"'"#)); -} - -#[test] -fn enum_2_str() { - invoke_with_roundtrip("simple", json!("First")); -} - -#[test] -fn e_2_s_enum() { - invoke_with_roundtrip("complex", json!({"Enum": "First"})); -} - -#[test] -fn asset() { - invoke_with_roundtrip( - "complex", - json!({"Asset": ["CB64D3G7SM2RTH6JSGG34DDTFTQ5CFDKVDZJZSODMCX4NJ2HV2KN7OHT", "100" ]}), - ); -} - -fn complex_tuple() -> serde_json::Value { - json!({"Tuple": [{"a": 42, "b": true, "c": "world"}, "First"]}) -} - -#[test] -fn e_2_s_tuple() { - invoke_with_roundtrip("complex", complex_tuple()); -} - -#[test] -fn e_2_s_strukt() { - invoke_with_roundtrip( - "complex", - json!({"Struct": {"a": 42, "b": true, "c": "world"}}), - ); -} - -#[test] -fn number_arg() { - invoke_with_roundtrip("u32_", 42); -} - -#[test] -fn number_arg_return_ok() { - invoke(&TestEnv::default(), "u32_fail_on_even") - .arg("--u32_") - .arg("1") - .assert() - .success() - .stdout("1\n"); -} - -#[test] -fn number_arg_return_err() { - TestEnv::with_default(|sandbox| { - // matches!(res, commands::invoke::Error) - let p = CUSTOM_TYPES.path(); - let wasm = p.to_str().unwrap(); - let res = sandbox - .invoke(&[ - "--id=1", - "--wasm", - wasm, - "--", - "u32_fail_on_even", - "--u32_=2", - ]) - .unwrap_err(); - if let commands::contract::invoke::Error::ContractInvoke(name, doc) = &res { - assert_eq!(name, "NumberMustBeOdd"); - assert_eq!(doc, "Please provide an odd number"); - }; - println!("{res:#?}"); - }); -} - -#[test] -fn void() { - invoke(&TestEnv::default(), "woid") - .assert() - .success() - .stdout("\n") - .stderr(""); -} - -#[test] -fn val() { - invoke(&TestEnv::default(), "val") - .assert() - .success() - .stdout("null\n") - .stderr(""); -} - -#[test] -fn i32() { - invoke_with_roundtrip("i32_", 42); -} - -#[test] -fn handle_arg_larger_than_i32_failure() { - invoke(&TestEnv::default(), "i32_") - .arg("--i32_") - .arg(u32::MAX.to_string()) - .assert() - .failure() - .stderr(predicates::str::contains("value is not parseable")); -} - -#[test] -fn handle_arg_larger_than_i64_failure() { - invoke(&TestEnv::default(), "i64_") - .arg("--i64_") - .arg(u64::MAX.to_string()) - .assert() - .failure() - .stderr(predicates::str::contains("value is not parseable")); -} - -#[test] -fn i64() { - invoke_with_roundtrip("i64_", i64::MAX); -} - -#[test] -fn negative_i32() { - invoke_with_roundtrip("i32_", -42); -} - -#[test] -fn negative_i64() { - invoke_with_roundtrip("i64_", i64::MIN); -} - -#[test] -fn account_address() { - invoke_with_roundtrip( - "addresse", - json!("GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS"), - ); -} - -#[test] -fn contract_address() { - invoke_with_roundtrip( - "addresse", - json!("CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE"), - ); -} - -#[test] -fn bytes() { - invoke_with_roundtrip("bytes", json!("7374656c6c6172")); -} - -#[test] -fn const_enum() { - invoke_with_roundtrip("card", "11"); -} - -#[test] -fn parse_u128() { - let num = "340000000000000000000000000000000000000"; - invoke(&TestEnv::default(), "u128") - .arg("--u128") - .arg(num) - .assert() - .success() - .stdout(format!( - r#""{num}" -"#, - )); -} - -#[test] -fn parse_i128() { - let num = "170000000000000000000000000000000000000"; - invoke(&TestEnv::default(), "i128") - .arg("--i128") - .arg(num) - .assert() - .success() - .stdout(format!( - r#""{num}" -"#, - )); -} - -#[test] -fn parse_negative_i128() { - let num = "-170000000000000000000000000000000000000"; - invoke(&TestEnv::default(), "i128") - .arg("--i128") - .arg(num) - .assert() - .success() - .stdout(format!( - r#""{num}" -"#, - )); -} - -#[test] -fn parse_u256() { - let num = "340000000000000000000000000000000000000"; - invoke(&TestEnv::default(), "u256") - .arg("--u256") - .arg(num) - .assert() - .success() - .stdout(format!( - r#""{num}" -"#, - )); -} - -#[test] -fn parse_i256() { - let num = "170000000000000000000000000000000000000"; - invoke(&TestEnv::default(), "i256") - .arg("--i256") - .arg(num) - .assert() - .success() - .stdout(format!( - r#""{num}" -"#, - )); -} - -#[test] -fn parse_negative_i256() { - let num = "-170000000000000000000000000000000000000"; - invoke(&TestEnv::default(), "i256") - .arg("--i256") - .arg(num) - .assert() - .success() - .stdout(format!( - r#""{num}" -"#, - )); -} - -#[test] -fn boolean() { - invoke(&TestEnv::default(), "boolean") - .arg("--boolean") - .assert() - .success() - .stdout( - r#"true -"#, - ); -} -#[test] -fn boolean_two() { - invoke(&TestEnv::default(), "boolean") - .arg("--boolean") - .arg("true") - .assert() - .success() - .stdout( - r#"true -"#, - ); -} - -#[test] -fn boolean_no_flag() { - invoke(&TestEnv::default(), "boolean") - .assert() - .success() - .stdout( - r#"false -"#, - ); -} - -#[test] -fn boolean_false() { - invoke(&TestEnv::default(), "boolean") - .arg("--boolean") - .arg("false") - .assert() - .success() - .stdout( - r#"false -"#, - ); -} - -#[test] -fn boolean_not() { - invoke(&TestEnv::default(), "not") - .arg("--boolean") - .assert() - .success() - .stdout( - r#"false -"#, - ); -} - -#[test] -fn boolean_not_no_flag() { - invoke(&TestEnv::default(), "not") - .assert() - .success() - .stdout( - r#"true -"#, - ); -} - -#[test] -fn option_none() { - invoke(&TestEnv::default(), "option") - .assert() - .success() - .stdout( - r#"null -"#, - ); -} - -#[test] -fn option_some() { - invoke(&TestEnv::default(), "option") - .arg("--option=1") - .assert() - .success() - .stdout( - r#"1 -"#, - ); -} diff --git a/cmd/crates/soroban-test/tests/it/hello_world.rs b/cmd/crates/soroban-test/tests/it/hello_world.rs index a87aff892..38b78ee38 100644 --- a/cmd/crates/soroban-test/tests/it/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/hello_world.rs @@ -11,427 +11,12 @@ use crate::util::{ TEST_SALT, }; -#[test] -fn install_wasm_then_deploy_contract() { - let sandbox = TestEnv::default(); - assert_eq!(deploy_hello(&sandbox), TEST_CONTRACT_ID); -} - -const TEST_CONTRACT_ID: &str = "CBVTIVBYWAO2HNPNGKDCZW4OZYYESTKNGD7IPRTDGQSFJS4QBDQQJX3T"; - -fn deploy_hello(sandbox: &TestEnv) -> String { - let hash = HELLO_WORLD.hash().unwrap(); - sandbox - .new_assert_cmd("contract") - .arg("install") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .assert() - .success() - .stdout(format!("{hash}\n")); - - let mut cmd: &mut assert_cmd::Command = &mut sandbox.new_assert_cmd("contract"); - - cmd = cmd.arg("deploy").arg("--wasm-hash").arg(&format!("{hash}")); - if is_rpc() { - cmd = cmd.arg("--salt").arg(TEST_SALT); - } else { - cmd = cmd.arg("--id").arg(TEST_CONTRACT_ID); - } - cmd.assert() - .success() - .stdout(format!("{TEST_CONTRACT_ID}\n")); - TEST_CONTRACT_ID.to_string() -} - -#[test] -fn deploy_contract_with_wasm_file() { - if is_rpc() { - return; - } - TestEnv::default() - .new_assert_cmd("contract") - .arg("deploy") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--id=1") - .assert() - .success() - .stdout("CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM\n"); -} - -#[test] -fn invoke_hello_world_with_deploy_first() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - println!("{id}"); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("hello") - .arg("--world=world") - .assert() - .stdout("[\"Hello\",\"world\"]\n") - .success(); -} - -#[test] -fn invoke_hello_world() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("hello") - .arg("--world=world") - .assert() - .stdout("[\"Hello\",\"world\"]\n") - .success(); -} - -#[test] -fn invoke_hello_world_from_file() { - let sandbox = TestEnv::default(); - let tmp_file = sandbox.temp_dir.join("world.txt"); - std::fs::write(&tmp_file, "world").unwrap(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("hello") - .arg("--world-file-path") - .arg(&tmp_file) - .assert() - .stdout("[\"Hello\",\"world\"]\n") - .success(); -} - -#[test] -fn invoke_hello_world_from_file_fail() { - let sandbox = TestEnv::default(); - let tmp_file = sandbox.temp_dir.join("world.txt"); - std::fs::write(&tmp_file, "world").unwrap(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("hello") - .arg("--world-file-path") - .arg(&tmp_file) - .arg("--world=hello") - .assert() - .stderr(predicates::str::contains("error: the argument '--world-file-path ' cannot be used with '--world '")) - .failure(); -} - -#[test] -fn invoke_hello_world_with_lib() { - TestEnv::with_default(|e| { - let id = deploy_hello(e); - let mut cmd = contract::invoke::Cmd { - contract_id: id, - slop: vec!["hello".into(), "--world=world".into()], - ..Default::default() - }; - - cmd.config.network.rpc_url = rpc_url(); - cmd.config.network.network_passphrase = network_passphrase(); - - let res = e.invoke_cmd(cmd).unwrap(); - assert_eq!(res, r#"["Hello","world"]"#); - }); -} - -#[test] -fn invoke_hello_world_with_lib_two() { - TestEnv::with_default(|e| { - let id = deploy_hello(e); - let hello_world = HELLO_WORLD.to_string(); - let mut invoke_args = vec!["--id", &id, "--wasm", hello_world.as_str()]; - let args = vec!["--", "hello", "--world=world"]; - let res = if let (Some(rpc), Some(network_passphrase)) = - (rpc_url_arg(), network_passphrase_arg()) - { - invoke_args.push(&rpc); - invoke_args.push(&network_passphrase); - e.invoke(&[invoke_args, args].concat()).unwrap() - } else { - e.invoke(&[invoke_args, args].concat()).unwrap() - }; - assert_eq!(res, r#"["Hello","world"]"#); - }); -} -// #[test] -// fn invoke_hello_world_with_lib_three() { -// let sandbox = TestEnv::default(); -// let builder = invoke::CmdBuilder::new().contract_id("1").wasm(HELLO_WORLD.path()).function("hello").slop(["--hello=world"]).build(); -// std::env::set_current_dir(sandbox.dir()).unwrap(); -// assert_eq!(res.run_in_sandbox().unwrap(), r#"["Hello","world"]"#); -// } - -#[test] -fn invoke_auth() { - let sandbox = TestEnv::default(); - let id = &deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("auth") - .arg(&format!("--addr={DEFAULT_PUB_KEY}")) - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); - - // Invoke it again without providing the contract, to exercise the deployment - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("auth") - .arg(&format!("--addr={DEFAULT_PUB_KEY}")) - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); -} - -#[tokio::test] -async fn invoke_auth_with_identity() { - let sandbox = TestEnv::default(); - sandbox - .cmd::("test -d ") - .run() - .await - .unwrap(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("auth") - .arg("--addr=test") - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); -} - -#[test] -fn invoke_auth_with_different_test_account() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--hd-path=1") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("auth") - .arg(&format!("--addr={DEFAULT_PUB_KEY_1}")) - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY_1}\"\n")) - .success(); -} -#[test] -fn contract_data_read_failure() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .arg("--durability=persistent") - .assert() - .failure() - .stderr( - "error: no matching contract data entries were found for the specified contract id\n", - ); -} - -#[test] -fn contract_data_read() { - let sandbox = TestEnv::default(); - let id = &deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("inc") - .assert() - .success(); - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .arg("--durability=persistent") - .assert() - .success() - .stdout("COUNTER,1,4,4096\n"); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("inc") - .assert() - .success(); - - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .arg("--durability=persistent") - .assert() - .success() - .stdout("COUNTER,2,4,4096\n"); -} -#[test] -fn invoke_auth_with_different_test_account_fail() { - let sandbox = TestEnv::default(); - let id = &deploy_hello(&sandbox); - let res = sandbox.invoke(&[ - "--hd-path=1", - "--id", - id, - "--wasm", - HELLO_WORLD.path().to_str().unwrap(), - &rpc_url_arg().unwrap_or_default(), - &network_passphrase_arg().unwrap_or_default(), - "--", - "auth", - &format!("--addr={DEFAULT_PUB_KEY}"), - "--world=world", - ]); - assert!(res.is_err()); - if let Err(e) = res { - assert!( - matches!(e, contract::invoke::Error::Host(_)), - "Expected host error got {e:?}" - ); - }; -} - -#[test] -fn invoke_hello_world_with_seed() { - let sandbox = TestEnv::default(); - let identity = add_test_seed(sandbox.dir()); - invoke_with_source(&sandbox, &identity); -} - -#[test] -fn invoke_with_seed() { - let sandbox = TestEnv::default(); - invoke_with_source(&sandbox, DEFAULT_SEED_PHRASE); -} - -#[test] -fn invoke_with_id() { - let sandbox = TestEnv::default(); - let identity = add_test_seed(sandbox.dir()); - invoke_with_source(&sandbox, &identity); -} - -#[test] -fn invoke_with_sk() { - let sandbox = TestEnv::default(); - invoke_with_source(&sandbox, DEFAULT_SECRET_KEY); -} - -fn invoke_with_source(sandbox: &TestEnv, source: &str) { - let id = &deploy_hello(sandbox); - let cmd = sandbox.invoke(&[ - "--source-account", - source, - "--id", - id, - "--wasm", - HELLO_WORLD.path().to_str().unwrap(), - &rpc_url_arg().unwrap_or_default(), - &network_passphrase_arg().unwrap_or_default(), - "--", - "hello", - "--world=world", - ]); - assert_eq!(cmd.unwrap(), "[\"Hello\",\"world\"]"); - - // Invoke it again without providing the contract, to exercise the deployment - let cmd = sandbox.invoke(&[ - "--source-account", - source, - "--id", - id, - "--", - "hello", - "--world=world", - ]); - assert_eq!(cmd.unwrap(), "[\"Hello\",\"world\"]"); -} - -#[test] -fn handles_kebab_case() { - let e = TestEnv::default(); - let id = deploy_hello(&e); - assert!(e - .invoke(&[ - "--id", - &id, - "--wasm", - HELLO_WORLD.path().to_str().unwrap(), - "--", - "multi-word-cmd", - "--contract-owner=world", - ]) - .is_ok()); -} #[tokio::test] async fn fetch() { @@ -445,49 +30,3 @@ async fn fetch() { cmd.run().await.unwrap(); assert!(f.exists()); } - -#[test] -fn build() { - let sandbox = TestEnv::default(); - - let cargo_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let hello_world_contract_path = - cargo_dir.join("tests/fixtures/test-wasms/hello_world/Cargo.toml"); - sandbox - .new_assert_cmd("contract") - .arg("build") - .arg("--manifest-path") - .arg(hello_world_contract_path) - .arg("--profile") - .arg("test-wasms") - .arg("--package") - .arg("test_hello_world") - .assert() - .success(); -} - -#[test] -fn invoke_prng_u64_in_range_test() { - let sandbox = TestEnv::default(); - let res = sandbox - .new_assert_cmd("contract") - .arg("deploy") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .assert() - .success(); - let stdout = String::from_utf8(res.get_output().stdout.clone()).unwrap(); - let id = stdout.trim_end(); - println!("{id}"); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("prng_u64_in_range") - .arg("--low=0") - .arg("--high=100") - .assert() - .success(); -} diff --git a/cmd/crates/soroban-test/tests/it/help.rs b/cmd/crates/soroban-test/tests/it/help.rs new file mode 100644 index 000000000..6d4680e77 --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/help.rs @@ -0,0 +1,97 @@ +use soroban_cli::commands::contract; +use soroban_test::TestEnv; + +use crate::util::{invoke_custom as invoke, CUSTOM_TYPES}; + +async fn invoke_custom(func: &str, args: &str) -> Result { + let e = &TestEnv::default(); + invoke(e, "1", func, args, &CUSTOM_TYPES.path()).await +} + +#[tokio::test] +async fn generate_help() { + assert!(invoke_custom("strukt_hel", "--help") + .await + .unwrap() + .contains("Example contract method which takes a struct")); +} + +#[tokio::test] +async fn vec_help() { + assert!(invoke_custom("vec", "--help") + .await + .unwrap() + .contains("Array")); +} + +#[tokio::test] +async fn tuple_help() { + assert!(invoke_custom("tuple", "--help") + .await + .unwrap() + .contains("Tuple")); +} + +#[tokio::test] +async fn strukt_help() { + let output = invoke_custom("strukt", "--help").await.unwrap(); + assert!(output.contains("--strukt '{ \"a\": 1, \"b\": true, \"c\": \"hello\" }'",)); + assert!(output.contains("This is from the rust doc above the struct Test",)); +} + +#[tokio::test] +async fn complex_enum_help() { + let output = invoke_custom("complex", "--help").await.unwrap(); + assert!(output.contains(r#"--complex '{"Struct":{ "a": 1, "b": true, "c": "hello" }}"#,)); + assert!(output.contains(r#"{"Tuple":[{ "a": 1, "b": true, "c": "hello" }"#,)); + assert!(output.contains(r#"{"Enum":"First"|"Second"|"Third"}"#,)); + assert!(output.contains( + r#"{"Asset":["GDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCR4W4", "-100"]}"#, + )); + assert!(output.contains(r#""Void"'"#)); +} + +#[tokio::test] +async fn multi_arg_failure() { + assert!(matches!( + invoke_custom("multi_args", "--b").await.unwrap_err(), + contract::invoke::Error::MissingArgument(_) + )); +} + +#[tokio::test] +async fn handle_arg_larger_than_i32_failure() { + let res = invoke_custom("i32_", &format!("--i32_={}", u32::MAX)).await; + assert!(matches!( + res, + Err(contract::invoke::Error::CannotParseArg { .. }) + )); +} + +#[tokio::test] +async fn handle_arg_larger_than_i64_failure() { + let res = invoke_custom("i64_", &format!("--i64_={}", u64::MAX)).await; + assert!(matches!( + res, + Err(contract::invoke::Error::CannotParseArg { .. }) + )); +} + +#[test] +fn build() { + let sandbox = TestEnv::default(); + let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let hello_world_contract_path = + cargo_dir.join("tests/fixtures/test-wasms/hello_world/Cargo.toml"); + sandbox + .new_assert_cmd("contract") + .arg("build") + .arg("--manifest-path") + .arg(hello_world_contract_path) + .arg("--profile") + .arg("test-wasms") + .arg("--package") + .arg("test_hello_world") + .assert() + .success(); +} diff --git a/cmd/crates/soroban-test/tests/it/integration.rs b/cmd/crates/soroban-test/tests/it/integration.rs new file mode 100644 index 000000000..d196ce07b --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/integration.rs @@ -0,0 +1,4 @@ +mod custom_types; +mod dotenv; +mod hello_world; +mod util; diff --git a/cmd/crates/soroban-test/tests/it/integration/custom_types.rs b/cmd/crates/soroban-test/tests/it/integration/custom_types.rs new file mode 100644 index 000000000..4e36b452c --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/integration/custom_types.rs @@ -0,0 +1,419 @@ +use serde_json::json; + +use soroban_cli::commands; +use soroban_test::TestEnv; + +use crate::integration::util::{deploy_custom, extend_contract, CUSTOM_TYPES}; + +use super::util::invoke_with_roundtrip; + +fn invoke_custom(e: &TestEnv, id: &str, func: &str) -> assert_cmd::Command { + let mut s = e.new_assert_cmd("contract"); + s.arg("invoke").arg("--id").arg(id).arg("--").arg(func); + s +} + +#[tokio::test] +async fn parse() { + let sandbox = &TestEnv::default(); + let id = &deploy_custom(sandbox); + extend_contract(sandbox, id, CUSTOM_TYPES).await; + symbol(sandbox, id); + string_with_quotes(sandbox, id).await; + symbol_with_quotes(sandbox, id).await; + multi_arg_success(sandbox, id); + bytes_as_file(sandbox, id); + map(sandbox, id).await; + vec_(sandbox, id).await; + tuple(sandbox, id).await; + strukt(sandbox, id).await; + tuple_strukt(sandbox, id).await; + enum_2_str(sandbox, id).await; + e_2_s_enum(sandbox, id).await; + asset(sandbox, id).await; + e_2_s_tuple(sandbox, id).await; + e_2_s_strukt(sandbox, id).await; + number_arg(sandbox, id).await; + number_arg_return_err(sandbox, id).await; + i32(sandbox, id).await; + i64(sandbox, id).await; + negative_i32(sandbox, id).await; + negative_i64(sandbox, id).await; + account_address(sandbox, id).await; + contract_address(sandbox, id).await; + bytes(sandbox, id).await; + const_enum(sandbox, id).await; + number_arg_return_ok(sandbox, id); + void(sandbox, id); + val(sandbox, id); + parse_u128(sandbox, id); + parse_i128(sandbox, id); + parse_negative_i128(sandbox, id); + parse_u256(sandbox, id); + parse_i256(sandbox, id); + parse_negative_i256(sandbox, id); + boolean(sandbox, id); + boolean_two(sandbox, id); + boolean_no_flag(sandbox, id); + boolean_false(sandbox, id); + boolean_not(sandbox, id); + boolean_not_no_flag(sandbox, id); + option_none(sandbox, id); + option_some(sandbox, id); +} + +fn symbol(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "hello") + .arg("--hello") + .arg("world") + .assert() + .success() + .stdout( + r#""world" +"#, + ); +} + +async fn string_with_quotes(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "string", json!("hello world")).await; +} + +async fn symbol_with_quotes(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "hello", json!("world")).await; +} + +fn multi_arg_success(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "multi_args") + .arg("--a") + .arg("42") + .arg("--b") + .assert() + .success() + .stdout("42\n"); +} + +fn bytes_as_file(sandbox: &TestEnv, id: &str) { + let env = &TestEnv::default(); + let path = env.temp_dir.join("bytes.txt"); + std::fs::write(&path, 0x0073_7465_6c6c_6172u128.to_be_bytes()).unwrap(); + invoke_custom(sandbox, id, "bytes") + .arg("--bytes-file-path") + .arg(path) + .assert() + .success() + .stdout("\"0000000000000000007374656c6c6172\"\n"); +} + +async fn map(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "map", json!({"0": true, "1": false})).await; +} + +async fn vec_(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "vec", json!([0, 1])).await; +} + +async fn tuple(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "tuple", json!(["hello", 0])).await; +} + +async fn strukt(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip( + sandbox, + id, + "strukt", + json!({"a": 42, "b": true, "c": "world"}), + ) + .await; +} + +async fn tuple_strukt(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip( + sandbox, + id, + "tuple_strukt", + json!([{"a": 42, "b": true, "c": "world"}, "First"]), + ) + .await; +} + +async fn enum_2_str(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "simple", json!("First")).await; +} + +async fn e_2_s_enum(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "complex", json!({"Enum": "First"})).await; +} + +async fn asset(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip( + sandbox, + id, + "complex", + json!({"Asset": ["CB64D3G7SM2RTH6JSGG34DDTFTQ5CFDKVDZJZSODMCX4NJ2HV2KN7OHT", "100" ]}), + ) + .await; +} + +fn complex_tuple() -> serde_json::Value { + json!({"Tuple": [{"a": 42, "b": true, "c": "world"}, "First"]}) +} + +async fn e_2_s_tuple(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "complex", complex_tuple()).await; +} + +async fn e_2_s_strukt(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip( + sandbox, + id, + "complex", + json!({"Struct": {"a": 42, "b": true, "c": "world"}}), + ) + .await; +} + +async fn number_arg(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "u32_", 42).await; +} + +fn number_arg_return_ok(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "u32_fail_on_even") + .arg("--u32_") + .arg("1") + .assert() + .success() + .stdout("1\n"); +} + +async fn number_arg_return_err(sandbox: &TestEnv, id: &str) { + let res = sandbox + .invoke(&["--id", id, "--", "u32_fail_on_even", "--u32_=2"]) + .await + .unwrap_err(); + if let commands::contract::invoke::Error::ContractInvoke(name, doc) = &res { + assert_eq!(name, "NumberMustBeOdd"); + assert_eq!(doc, "Please provide an odd number"); + }; + println!("{res:#?}"); +} + +fn void(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "woid") + .assert() + .success() + .stdout("\n") + .stderr(""); +} + +fn val(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "val") + .assert() + .success() + .stdout("null\n") + .stderr(""); +} + +async fn i32(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "i32_", 42).await; +} + +async fn i64(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "i64_", i64::MAX).await; +} + +async fn negative_i32(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "i32_", -42).await; +} + +async fn negative_i64(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "i64_", i64::MIN).await; +} + +async fn account_address(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip( + sandbox, + id, + "addresse", + json!("GD5KD2KEZJIGTC63IGW6UMUSMVUVG5IHG64HUTFWCHVZH2N2IBOQN7PS"), + ) + .await; +} + +async fn contract_address(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip( + sandbox, + id, + "addresse", + json!("CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE"), + ) + .await; +} + +async fn bytes(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "bytes", json!("7374656c6c6172")).await; +} + +async fn const_enum(sandbox: &TestEnv, id: &str) { + invoke_with_roundtrip(sandbox, id, "card", "11").await; +} + +fn parse_u128(sandbox: &TestEnv, id: &str) { + let num = "340000000000000000000000000000000000000"; + invoke_custom(sandbox, id, "u128") + .arg("--u128") + .arg(num) + .assert() + .success() + .stdout(format!( + r#""{num}" +"#, + )); +} + +fn parse_i128(sandbox: &TestEnv, id: &str) { + let num = "170000000000000000000000000000000000000"; + invoke_custom(sandbox, id, "i128") + .arg("--i128") + .arg(num) + .assert() + .success() + .stdout(format!( + r#""{num}" +"#, + )); +} + +fn parse_negative_i128(sandbox: &TestEnv, id: &str) { + let num = "-170000000000000000000000000000000000000"; + invoke_custom(sandbox, id, "i128") + .arg("--i128") + .arg(num) + .assert() + .success() + .stdout(format!( + r#""{num}" +"#, + )); +} + +fn parse_u256(sandbox: &TestEnv, id: &str) { + let num = "340000000000000000000000000000000000000"; + invoke_custom(sandbox, id, "u256") + .arg("--u256") + .arg(num) + .assert() + .success() + .stdout(format!( + r#""{num}" +"#, + )); +} + +fn parse_i256(sandbox: &TestEnv, id: &str) { + let num = "170000000000000000000000000000000000000"; + invoke_custom(sandbox, id, "i256") + .arg("--i256") + .arg(num) + .assert() + .success() + .stdout(format!( + r#""{num}" +"#, + )); +} + +fn parse_negative_i256(sandbox: &TestEnv, id: &str) { + let num = "-170000000000000000000000000000000000000"; + invoke_custom(sandbox, id, "i256") + .arg("--i256") + .arg(num) + .assert() + .success() + .stdout(format!( + r#""{num}" +"#, + )); +} + +fn boolean(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "boolean") + .arg("--boolean") + .assert() + .success() + .stdout( + r#"true +"#, + ); +} +fn boolean_two(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "boolean") + .arg("--boolean") + .arg("true") + .assert() + .success() + .stdout( + r#"true +"#, + ); +} + +fn boolean_no_flag(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "boolean") + .assert() + .success() + .stdout( + r#"false +"#, + ); +} + +fn boolean_false(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "boolean") + .arg("--boolean") + .arg("false") + .assert() + .success() + .stdout( + r#"false +"#, + ); +} + +fn boolean_not(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "not") + .arg("--boolean") + .assert() + .success() + .stdout( + r#"false +"#, + ); +} + +fn boolean_not_no_flag(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "not").assert().success().stdout( + r#"true +"#, + ); +} + +fn option_none(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "option") + .assert() + .success() + .stdout( + r#"null +"#, + ); +} + +fn option_some(sandbox: &TestEnv, id: &str) { + invoke_custom(sandbox, id, "option") + .arg("--option=1") + .assert() + .success() + .stdout( + r#"1 +"#, + ); +} diff --git a/cmd/crates/soroban-test/tests/it/dotenv.rs b/cmd/crates/soroban-test/tests/it/integration/dotenv.rs similarity index 63% rename from cmd/crates/soroban-test/tests/it/dotenv.rs rename to cmd/crates/soroban-test/tests/it/integration/dotenv.rs index eb7b5a68f..d7d56aaf3 100644 --- a/cmd/crates/soroban-test/tests/it/dotenv.rs +++ b/cmd/crates/soroban-test/tests/it/integration/dotenv.rs @@ -1,19 +1,6 @@ use soroban_test::TestEnv; -use crate::util::HELLO_WORLD; - -const SOROBAN_CONTRACT_ID: &str = "SOROBAN_CONTRACT_ID=1"; - -fn deploy(e: &TestEnv, id: &str) { - e.new_assert_cmd("contract") - .arg("deploy") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--id") - .arg(id) - .assert() - .success(); -} +use super::util::{deploy_hello, TEST_CONTRACT_ID}; fn write_env_file(e: &TestEnv, contents: &str) { let env_file = e.dir().join(".env"); @@ -21,11 +8,15 @@ fn write_env_file(e: &TestEnv, contents: &str) { assert_eq!(contents, std::fs::read_to_string(env_file).unwrap()); } +fn contract_id() -> String { + format!("SOROBAN_CONTRACT_ID={TEST_CONTRACT_ID}") +} + #[test] fn can_read_file() { TestEnv::with_default(|e| { - deploy(e, "1"); - write_env_file(e, SOROBAN_CONTRACT_ID); + deploy_hello(e); + write_env_file(e, &contract_id()); e.new_assert_cmd("contract") .arg("invoke") .arg("--") @@ -40,8 +31,8 @@ fn can_read_file() { #[test] fn current_env_not_overwritten() { TestEnv::with_default(|e| { - deploy(e, "1"); - write_env_file(e, SOROBAN_CONTRACT_ID); + deploy_hello(e); + write_env_file(e, &contract_id()); e.new_assert_cmd("contract") .env("SOROBAN_CONTRACT_ID", "2") @@ -50,20 +41,20 @@ fn current_env_not_overwritten() { .arg("hello") .arg("--world=world") .assert() - .stderr("error: parsing contract spec: contract spec not found\n"); + .stderr("error: Contract not found: CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4\n"); }); } #[test] fn cli_args_have_priority() { TestEnv::with_default(|e| { - deploy(e, "2"); - write_env_file(e, SOROBAN_CONTRACT_ID); + deploy_hello(e); + write_env_file(e, &contract_id()); e.new_assert_cmd("contract") - .env("SOROBAN_CONTRACT_ID", "3") + .env("SOROBAN_CONTRACT_ID", "2") .arg("invoke") .arg("--id") - .arg("2") + .arg(TEST_CONTRACT_ID) .arg("--") .arg("hello") .arg("--world=world") diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs new file mode 100644 index 000000000..fed4f4493 --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -0,0 +1,290 @@ +use soroban_cli::commands::{ + config::identity, + contract::{self, fetch}, +}; +use soroban_test::TestEnv; + +use crate::{integration::util::extend_contract, util::DEFAULT_SEED_PHRASE}; + +use super::util::{ + add_test_seed, deploy_hello, extend, network_passphrase, network_passphrase_arg, rpc_url, + rpc_url_arg, DEFAULT_PUB_KEY, DEFAULT_PUB_KEY_1, DEFAULT_SECRET_KEY, HELLO_WORLD, +}; + +#[tokio::test] +#[ignore] +async fn invoke() { + let sandbox = &TestEnv::default(); + let id = &deploy_hello(sandbox); + extend_contract(sandbox, id, HELLO_WORLD).await; + // Note that all functions tested here have no state + invoke_hello_world(sandbox, id); + invoke_hello_world_with_lib(sandbox, id).await; + invoke_hello_world_with_lib_two(sandbox, id).await; + invoke_auth(sandbox, id); + invoke_auth_with_identity(sandbox, id).await; + invoke_auth_with_different_test_account_fail(sandbox, id).await; + // invoke_auth_with_different_test_account(sandbox, id); + contract_data_read_failure(sandbox, id); + invoke_with_seed(sandbox, id).await; + invoke_with_sk(sandbox, id).await; + // This does add an identity to local config + invoke_with_id(sandbox, id).await; + handles_kebab_case(sandbox, id).await; + fetch(sandbox, id).await; + invoke_prng_u64_in_range_test(sandbox, id).await; +} + +fn invoke_hello_world(sandbox: &TestEnv, id: &str) { + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--") + .arg("hello") + .arg("--world=world") + .assert() + .stdout("[\"Hello\",\"world\"]\n") + .success(); +} + +async fn invoke_hello_world_with_lib(e: &TestEnv, id: &str) { + let mut cmd = contract::invoke::Cmd { + contract_id: id.to_string(), + slop: vec!["hello".into(), "--world=world".into()], + ..Default::default() + }; + + cmd.config.network.rpc_url = rpc_url(); + cmd.config.network.network_passphrase = network_passphrase(); + + let res = e.invoke_cmd(cmd).await.unwrap(); + assert_eq!(res, r#"["Hello","world"]"#); +} + +async fn invoke_hello_world_with_lib_two(e: &TestEnv, id: &str) { + let hello_world = HELLO_WORLD.to_string(); + let mut invoke_args = vec!["--id", id, "--wasm", hello_world.as_str()]; + let args = vec!["--", "hello", "--world=world"]; + let res = + if let (Some(rpc), Some(network_passphrase)) = (rpc_url_arg(), network_passphrase_arg()) { + invoke_args.push(&rpc); + invoke_args.push(&network_passphrase); + e.invoke(&[invoke_args, args].concat()).await.unwrap() + } else { + e.invoke(&[invoke_args, args].concat()).await.unwrap() + }; + assert_eq!(res, r#"["Hello","world"]"#); +} + +fn invoke_auth(sandbox: &TestEnv, id: &str) { + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--") + .arg("auth") + .arg(&format!("--addr={DEFAULT_PUB_KEY}")) + .arg("--world=world") + .assert() + .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) + .success(); + + // Invoke it again without providing the contract, to exercise the deployment + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--") + .arg("auth") + .arg(&format!("--addr={DEFAULT_PUB_KEY}")) + .arg("--world=world") + .assert() + .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) + .success(); +} + +async fn invoke_auth_with_identity(sandbox: &TestEnv, id: &str) { + sandbox + .cmd::("test -d ") + .run() + .await + .unwrap(); + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--") + .arg("auth") + .arg("--addr") + .arg(DEFAULT_PUB_KEY) + .arg("--world=world") + .assert() + .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) + .success(); +} + +// fn invoke_auth_with_different_test_account(sandbox: &TestEnv, id: &str) { +// sandbox +// .new_assert_cmd("contract") +// .arg("invoke") +// .arg("--hd-path=1") +// .arg("--id") +// .arg(id) +// .arg("--wasm") +// .arg(HELLO_WORLD.path()) +// .arg("--") +// .arg("auth") +// .arg(&format!("--addr={DEFAULT_PUB_KEY_1}")) +// .arg("--world=world") +// .assert() +// .stdout(format!("\"{DEFAULT_PUB_KEY_1}\"\n")) +// .success(); +// } + +async fn invoke_auth_with_different_test_account_fail(sandbox: &TestEnv, id: &str) { + let res = sandbox + .invoke(&[ + "--hd-path=0", + "--id", + id, + &rpc_url_arg().unwrap_or_default(), + &network_passphrase_arg().unwrap_or_default(), + "--", + "auth", + &format!("--addr={DEFAULT_PUB_KEY_1}"), + "--world=world", + ]) + .await; + let e = res.unwrap_err(); + assert!( + matches!(e, contract::invoke::Error::Rpc(_)), + "Expected rpc error got {e:?}" + ); +} + +fn contract_data_read_failure(sandbox: &TestEnv, id: &str) { + sandbox + .new_assert_cmd("contract") + .arg("read") + .arg("--id") + .arg(id) + .arg("--key=COUNTER") + .arg("--durability=persistent") + .assert() + .failure() + .stderr( + "error: no matching contract data entries were found for the specified contract id\n", + ); +} + +#[tokio::test] +async fn contract_data_read() { + const KEY: &str = "COUNTER"; + let sandbox = &TestEnv::default(); + let id = &deploy_hello(sandbox); + let res = sandbox.invoke(&["--id", id, "--", "inc"]).await.unwrap(); + assert_eq!(res.trim(), "1"); + extend(sandbox, id, Some(KEY)).await; + + sandbox + .new_assert_cmd("contract") + .arg("read") + .arg("--id") + .arg(id) + .arg("--key") + .arg(KEY) + .arg("--durability=persistent") + .assert() + .success() + .stdout(predicates::str::starts_with("COUNTER,1")); + + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--") + .arg("inc") + .assert() + .success(); + + sandbox + .new_assert_cmd("contract") + .arg("read") + .arg("--id") + .arg(id) + .arg("--key") + .arg(KEY) + .arg("--durability=persistent") + .assert() + .success() + .stdout(predicates::str::starts_with("COUNTER,2")); +} + +async fn invoke_with_seed(sandbox: &TestEnv, id: &str) { + invoke_with_source(sandbox, DEFAULT_SEED_PHRASE, id).await; +} + +async fn invoke_with_sk(sandbox: &TestEnv, id: &str) { + invoke_with_source(sandbox, DEFAULT_SECRET_KEY, id).await; +} + +async fn invoke_with_id(sandbox: &TestEnv, id: &str) { + let identity = add_test_seed(sandbox.dir()); + invoke_with_source(sandbox, &identity, id).await; +} + +async fn invoke_with_source(sandbox: &TestEnv, source: &str, id: &str) { + let cmd = sandbox + .invoke(&[ + "--source-account", + source, + "--id", + id, + "--", + "hello", + "--world=world", + ]) + .await + .unwrap(); + assert_eq!(cmd, "[\"Hello\",\"world\"]"); +} + +async fn handles_kebab_case(e: &TestEnv, id: &str) { + assert!(e + .invoke(&["--id", id, "--", "multi-word-cmd", "--contract-owner=world",]) + .await + .is_ok()); +} + +async fn fetch(sandbox: &TestEnv, id: &str) { + let f = sandbox.dir().join("contract.wasm"); + let cmd = sandbox.cmd_arr::(&["--id", id, "--out-file", f.to_str().unwrap()]); + cmd.run().await.unwrap(); + assert!(f.exists()); +} + +async fn invoke_prng_u64_in_range_test(sandbox: &TestEnv, id: &str) { + assert!(sandbox + .invoke(&[ + "--id", + id, + "--wasm", + HELLO_WORLD.path().to_str().unwrap(), + "--", + "prng_u64_in_range", + "--low=0", + "--high=100", + ]) + .await + .is_ok()); +} diff --git a/cmd/crates/soroban-test/tests/it/integration/util.rs b/cmd/crates/soroban-test/tests/it/integration/util.rs new file mode 100644 index 000000000..878f8a055 --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/integration/util.rs @@ -0,0 +1,117 @@ +use soroban_cli::commands::contract; +use soroban_test::{TestEnv, Wasm}; +use std::{fmt::Display, path::Path}; + +use crate::util::{add_identity, SecretKind}; + +pub const HELLO_WORLD: &Wasm = &Wasm::Custom("test-wasms", "test_hello_world"); +pub const CUSTOM_TYPES: &Wasm = &Wasm::Custom("test-wasms", "test_custom_types"); + +pub fn add_test_seed(dir: &Path) -> String { + let name = "test_seed"; + add_identity( + dir, + name, + SecretKind::Seed, + "coral light army gather adapt blossom school alcohol coral light army giggle", + ); + name.to_owned() +} + +pub async fn invoke_with_roundtrip(e: &TestEnv, id: &str, func: &str, data: D) +where + D: Display, +{ + let data = data.to_string(); + println!("{data}"); + let res = e + .invoke(&["--id", id, "--", func, &format!("--{func}"), &data]) + .await + .unwrap(); + assert_eq!(res, data); +} + +pub const DEFAULT_PUB_KEY: &str = "GDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCR4W4"; +pub const DEFAULT_SECRET_KEY: &str = "SC36BWNUOCZAO7DMEJNNKFV6BOTPJP7IG5PSHLUOLT6DZFRU3D3XGIXW"; + +pub const DEFAULT_PUB_KEY_1: &str = "GCKZUJVUNEFGD4HLFBUNVYM2QY2P5WQQZMGRA3DDL4HYVT5MW5KG3ODV"; +pub const TEST_SALT: &str = "f55ff16f66f43360266b95db6f8fec01d76031054306ae4a4b380598f6cfd114"; +pub const TEST_CONTRACT_ID: &str = "CBVTIVBYWAO2HNPNGKDCZW4OZYYESTKNGD7IPRTDGQSFJS4QBDQQJX3T"; + +pub fn rpc_url() -> Option { + std::env::var("SOROBAN_RPC_URL").ok() +} + +pub fn rpc_url_arg() -> Option { + rpc_url().map(|url| format!("--rpc-url={url}")) +} + +pub fn network_passphrase() -> Option { + std::env::var("SOROBAN_NETWORK_PASSPHRASE").ok() +} + +pub fn network_passphrase_arg() -> Option { + network_passphrase().map(|p| format!("--network-passphrase={p}")) +} + +pub fn deploy_hello(sandbox: &TestEnv) -> String { + deploy_contract(sandbox, HELLO_WORLD) +} + +pub fn deploy_custom(sandbox: &TestEnv) -> String { + deploy_contract(sandbox, CUSTOM_TYPES) +} + +pub fn deploy_contract(sandbox: &TestEnv, wasm: &Wasm) -> String { + let hash = wasm.hash().unwrap(); + sandbox + .new_assert_cmd("contract") + .arg("install") + .arg("--wasm") + .arg(wasm.path()) + .assert() + .success() + .stdout(format!("{hash}\n")); + + sandbox + .new_assert_cmd("contract") + .arg("deploy") + .arg("--wasm-hash") + .arg(&format!("{hash}")) + .arg("--salt") + .arg(TEST_SALT) + .assert() + .success() + .stdout(format!("{TEST_CONTRACT_ID}\n")); + TEST_CONTRACT_ID.to_string() +} + +pub async fn extend_contract(sandbox: &TestEnv, id: &str, wasm: &Wasm<'_>) { + extend(sandbox, id, None).await; + let cmd: contract::extend::Cmd = sandbox.cmd_arr(&[ + "--wasm-hash", + wasm.hash().unwrap().to_string().as_str(), + "--durability", + "persistent", + "--ledgers-to-extend", + "100000", + ]); + cmd.run().await.unwrap(); +} + +pub async fn extend(sandbox: &TestEnv, id: &str, value: Option<&str>) { + let mut args = vec![ + "--id", + id, + "--durability", + "persistent", + "--ledgers-to-extend", + "100000", + ]; + if let Some(value) = value { + args.push("--key"); + args.push(value); + } + let cmd: contract::extend::Cmd = sandbox.cmd_arr(&args); + cmd.run().await.unwrap(); +} diff --git a/cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs b/cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs deleted file mode 100644 index 5536966c5..000000000 --- a/cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs +++ /dev/null @@ -1,222 +0,0 @@ -use soroban_cli::commands::{config::identity, contract::fetch}; -use soroban_test::TestEnv; - -use crate::util::{ - add_test_seed, deploy_hello, is_rpc, network_passphrase_arg, rpc_url_arg, DEFAULT_PUB_KEY, - DEFAULT_SECRET_KEY, DEFAULT_SEED_PHRASE, HELLO_WORLD, -}; - -#[test] -fn invoke_hello_world_with_lib_two() { - TestEnv::with_default(|e| { - let id = deploy_hello(e); - let hello_world = HELLO_WORLD.to_string(); - let mut invoke_args = vec!["--id", &id, "--wasm", hello_world.as_str()]; - let args = vec!["--", "hello", "--world=world"]; - let res = if let (Some(rpc), Some(network_passphrase)) = - (rpc_url_arg(), network_passphrase_arg()) - { - invoke_args.push(&rpc); - invoke_args.push(&network_passphrase); - e.invoke(&[invoke_args, args].concat()).unwrap() - } else { - e.invoke(&[invoke_args, args].concat()).unwrap() - }; - assert_eq!(res, r#"["Hello","world"]"#); - }); -} - -#[test] -fn invoke_auth() { - let sandbox = TestEnv::default(); - let id = &deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("auth") - .arg(&format!("--addr={DEFAULT_PUB_KEY}")) - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); - - // Invoke it again without providing the contract, to exercise the deployment - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("auth") - .arg(&format!("--addr={DEFAULT_PUB_KEY}")) - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); -} - -#[tokio::test] -async fn invoke_auth_with_identity() { - let sandbox = TestEnv::default(); - sandbox - .cmd::("test -d ") - .run() - .await - .unwrap(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("auth") - .arg("--addr=test") - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); -} - -#[test] -fn contract_data_read_failure() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .arg("--durability=persistent") - .assert() - .failure() - .stderr( - "error: no matching contract data entries were found for the specified contract id\n", - ); -} - -#[test] -fn contract_data_read() { - let sandbox = TestEnv::default(); - let id = &deploy_hello(&sandbox); - - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("inc") - .assert() - .success(); - - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .arg("--durability=persistent") - .assert() - .success() - .stdout(predicates::str::starts_with("COUNTER,1")); - - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("inc") - .assert() - .success(); - - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .arg("--durability=persistent") - .assert() - .success() - .stdout(predicates::str::starts_with("COUNTER,2")); -} - -#[test] -fn invoke_hello_world_with_seed() { - let sandbox = TestEnv::default(); - let identity = add_test_seed(sandbox.dir()); - invoke_with_source(&sandbox, &identity); -} - -#[test] -fn invoke_with_seed() { - let sandbox = TestEnv::default(); - invoke_with_source(&sandbox, DEFAULT_SEED_PHRASE); -} - -#[test] -fn invoke_with_id() { - let sandbox = TestEnv::default(); - let identity = add_test_seed(sandbox.dir()); - invoke_with_source(&sandbox, &identity); -} - -#[test] -fn invoke_with_sk() { - let sandbox = TestEnv::default(); - invoke_with_source(&sandbox, DEFAULT_SECRET_KEY); -} - -fn invoke_with_source(sandbox: &TestEnv, source: &str) { - let id = &deploy_hello(sandbox); - let cmd = sandbox.invoke(&[ - "--source-account", - source, - "--id", - id, - "--wasm", - HELLO_WORLD.path().to_str().unwrap(), - &rpc_url_arg().unwrap_or_default(), - &network_passphrase_arg().unwrap_or_default(), - "--", - "hello", - "--world=world", - ]); - assert_eq!(cmd.unwrap(), "[\"Hello\",\"world\"]"); - - // Invoke it again without providing the contract, to exercise the deployment - let cmd = sandbox.invoke(&[ - "--source-account", - source, - "--id", - id, - "--", - "hello", - "--world=world", - ]); - assert_eq!(cmd.unwrap(), "[\"Hello\",\"world\"]"); -} - -#[tokio::test] -async fn fetch() { - if !is_rpc() { - return; - } - let e = TestEnv::default(); - let f = e.dir().join("contract.wasm"); - let id = deploy_hello(&e); - let cmd = e.cmd_arr::(&["--id", &id, "--out-file", f.to_str().unwrap()]); - cmd.run().await.unwrap(); - assert!(f.exists()); -} diff --git a/cmd/crates/soroban-test/tests/it/main.rs b/cmd/crates/soroban-test/tests/it/main.rs index e822b7740..bd2627b96 100644 --- a/cmd/crates/soroban-test/tests/it/main.rs +++ b/cmd/crates/soroban-test/tests/it/main.rs @@ -1,10 +1,8 @@ mod arg_parsing; mod config; - -mod custom_types; -mod dotenv; -mod hello_world; -mod integration_and_sandbox; +mod help; +// #[cfg(feature = "integration")] +mod integration; mod lab; mod plugin; mod util; diff --git a/cmd/crates/soroban-test/tests/it/util.rs b/cmd/crates/soroban-test/tests/it/util.rs index 68c2e31ac..ad5dacc7d 100644 --- a/cmd/crates/soroban-test/tests/it/util.rs +++ b/cmd/crates/soroban-test/tests/it/util.rs @@ -1,10 +1,11 @@ -use std::{fmt::Display, path::Path}; +use std::path::Path; -use assert_cmd::Command; -use soroban_cli::commands::config::{locator::KeyType, secret::Secret}; +use soroban_cli::commands::{ + config::{locator::KeyType, secret::Secret}, + contract, +}; use soroban_test::{TestEnv, Wasm}; -pub const HELLO_WORLD: &Wasm = &Wasm::Custom("test-wasms", "test_hello_world"); pub const CUSTOM_TYPES: &Wasm = &Wasm::Custom("test-wasms", "test_custom_types"); #[derive(Clone)] @@ -40,102 +41,20 @@ pub fn add_test_id(dir: &Path) -> String { name.to_owned() } -pub fn add_test_seed(dir: &Path) -> String { - let name = "test_seed"; - add_identity( - dir, - name, - SecretKind::Seed, - "coral light army gather adapt blossom school alcohol coral light army giggle", - ); - name.to_owned() -} - -pub fn invoke(sandbox: &TestEnv, func: &str) -> Command { - let mut s = sandbox.new_assert_cmd("contract"); - s.arg("invoke") - .arg("--id=1") - .arg("--wasm") - .arg(CUSTOM_TYPES.path()) - .arg("--") - .arg(func); - s -} - -pub fn invoke_with_roundtrip(func: &str, data: D) -where - D: Display, -{ - TestEnv::with_default(|e| { - let data = data.to_string(); - println!("{data}"); - let res = e - .invoke(&[ - "--id=1", - "--wasm", - &CUSTOM_TYPES.to_string(), - "--", - func, - &format!("--{func}"), - &data, - ]) - .unwrap(); - assert_eq!(res, data); - }); -} - -pub fn is_rpc() -> bool { - std::env::var("SOROBAN_RPC_URL").is_ok() -} - pub const DEFAULT_SEED_PHRASE: &str = "coral light army gather adapt blossom school alcohol coral light army giggle"; -pub const DEFAULT_PUB_KEY: &str = "GDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCR4W4"; -pub const DEFAULT_SECRET_KEY: &str = "SC36BWNUOCZAO7DMEJNNKFV6BOTPJP7IG5PSHLUOLT6DZFRU3D3XGIXW"; - -pub const DEFAULT_PUB_KEY_1: &str = "GCKZUJVUNEFGD4HLFBUNVYM2QY2P5WQQZMGRA3DDL4HYVT5MW5KG3ODV"; -pub const TEST_SALT: &str = "f55ff16f66f43360266b95db6f8fec01d76031054306ae4a4b380598f6cfd114"; - -pub fn rpc_url() -> Option { - std::env::var("SOROBAN_RPC_URL").ok() -} - -pub fn rpc_url_arg() -> Option { - rpc_url().map(|url| format!("--rpc-url={url}")) -} - -pub fn network_passphrase() -> Option { - std::env::var("SOROBAN_NETWORK_PASSPHRASE").ok() -} - -pub fn network_passphrase_arg() -> Option { - network_passphrase().map(|p| format!("--network-passphrase={p}")) -} - -pub const TEST_CONTRACT_ID: &str = "CBVTIVBYWAO2HNPNGKDCZW4OZYYESTKNGD7IPRTDGQSFJS4QBDQQJX3T"; - -pub fn deploy_hello(sandbox: &TestEnv) -> String { - let hash = HELLO_WORLD.hash().unwrap(); - sandbox - .new_assert_cmd("contract") - .arg("install") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .assert() - .success() - .stdout(format!("{hash}\n")); - - let mut cmd: &mut assert_cmd::Command = &mut sandbox.new_assert_cmd("contract"); - - cmd = cmd.arg("deploy").arg("--wasm-hash").arg(&format!("{hash}")); - if is_rpc() { - cmd = cmd.arg("--salt").arg(TEST_SALT); - } else { - cmd = cmd.arg("--id").arg(TEST_CONTRACT_ID); - } - cmd.assert() - .success() - .stdout(format!("{TEST_CONTRACT_ID}\n")); - TEST_CONTRACT_ID.to_string() +#[allow(dead_code)] +pub async fn invoke_custom( + sandbox: &TestEnv, + id: &str, + func: &str, + arg: &str, + wasm: &Path, +) -> Result { + let mut i: contract::invoke::Cmd = sandbox.cmd_arr(&["--id", id, "--", func, arg]); + i.wasm = Some(wasm.to_path_buf()); + i.config.network.network = Some("futurenet".to_owned()); + i.invoke(&soroban_cli::commands::global::Args::default()) + .await } diff --git a/cmd/soroban-cli/src/commands/config/events_file.rs b/cmd/soroban-cli/src/commands/config/events_file.rs deleted file mode 100644 index ba1b280b0..000000000 --- a/cmd/soroban-cli/src/commands/config/events_file.rs +++ /dev/null @@ -1,236 +0,0 @@ -use crate::{ - commands::HEADING_SANDBOX, - rpc::{self, does_topic_match, Event}, - toid, -}; -use chrono::{DateTime, NaiveDateTime, Utc}; -use clap::arg; -use soroban_env_host::{ - events, - xdr::{self, WriteXdr}, -}; -use soroban_ledger_snapshot::LedgerSnapshot; -use std::{ - fs, - path::{Path, PathBuf}, -}; -use stellar_strkey::{Contract, Strkey}; - -#[derive(Debug, clap::Args, Clone, Default)] -#[group(skip)] -pub struct Args { - /// File to persist events, default is `.soroban/events.json` - #[arg( - long, - value_name = "PATH", - env = "SOROBAN_EVENTS_FILE", - help_heading = HEADING_SANDBOX, - conflicts_with = "rpc_url", - conflicts_with = "network", - )] - pub events_file: Option, -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error(transparent)] - Xdr(#[from] xdr::Error), - #[error(transparent)] - Rpc(#[from] rpc::Error), - #[error(transparent)] - SerdeJson(#[from] serde_json::Error), - #[error(transparent)] - Io(#[from] std::io::Error), - #[error(transparent)] - Generic(#[from] Box), - #[error("invalid timestamp in event: {ts}")] - InvalidTimestamp { ts: String }, -} - -impl Args { - /// Returns a list of events from the on-disk event store, which stores events - /// exactly as they'd be returned by an RPC server. - pub fn read(&self, pwd: &Path) -> Result { - let path = self.path(pwd); - let reader = std::fs::OpenOptions::new().read(true).open(path)?; - Ok(serde_json::from_reader(reader)?) - } - - /// Reads the existing event file, appends the new events, and writes it all to - /// disk. Note that this almost certainly isn't safe to call in parallel. - pub fn commit( - &self, - new_events: &[events::HostEvent], - ledger_info: &LedgerSnapshot, - pwd: &Path, - ) -> Result<(), Error> { - let output_file = self.path(pwd); - // Create the directory tree if necessary, since these are unlikely to be - // the first events. - if let Some(dir) = output_file.parent() { - if !dir.exists() { - fs::create_dir_all(dir)?; - } - } - - let mut events: Vec = if output_file.exists() { - let mut file = fs::OpenOptions::new().read(true).open(&output_file)?; - let payload: rpc::GetEventsResponse = serde_json::from_reader(&mut file)?; - payload.events - } else { - vec![] - }; - - for (i, event) in new_events.iter().enumerate() { - let contract_event = &event.event; - let topic = match &contract_event.body { - xdr::ContractEventBody::V0(e) => &e.topics, - } - .iter() - .map(xdr::WriteXdr::to_xdr_base64) - .collect::, _>>()?; - - // stolen from - // https://github.com/stellar/soroban-tools/blob/main/cmd/soroban-rpc/internal/methods/get_events.go#L264 - let id = format!( - "{}-{:010}", - toid::Toid::new( - ledger_info.sequence_number, - // we should technically inject the tx order here from the - // ledger info, but the sandbox does one tx/op per ledger - // anyway, so this is a safe assumption - 1, - 1, - ) - .to_paging_token(), - i + 1 - ); - - // Misc. timestamp to RFC 3339-formatted datetime nonsense, with an - // absurd amount of verbosity because every edge case needs its own - // chain of error-handling methods. - // - // Reference: https://stackoverflow.com/a/50072164 - let ts: i64 = - ledger_info - .timestamp - .try_into() - .map_err(|_e| Error::InvalidTimestamp { - ts: ledger_info.timestamp.to_string(), - })?; - let ndt = NaiveDateTime::from_timestamp_opt(ts, 0).ok_or_else(|| { - Error::InvalidTimestamp { - ts: ledger_info.timestamp.to_string(), - } - })?; - - let dt: DateTime = DateTime::from_naive_utc_and_offset(ndt, Utc); - - let cereal_event = rpc::Event { - event_type: match contract_event.type_ { - xdr::ContractEventType::Contract => "contract", - xdr::ContractEventType::System => "system", - xdr::ContractEventType::Diagnostic => "diagnostic", - } - .to_string(), - paging_token: id.clone(), - id, - ledger: ledger_info.sequence_number.to_string(), - ledger_closed_at: dt.format("%Y-%m-%dT%H:%M:%SZ").to_string(), - contract_id: Strkey::Contract(Contract( - contract_event - .contract_id - .as_ref() - .unwrap_or(&xdr::Hash([0; 32])) - .0, - )) - .to_string(), - topic, - value: match &contract_event.body { - xdr::ContractEventBody::V0(e) => &e.data, - } - .to_xdr_base64()?, - }; - - events.push(cereal_event); - } - - let mut file = std::fs::OpenOptions::new() - .create(true) - .write(true) - .truncate(true) - .open(&output_file)?; - - serde_json::to_writer_pretty( - &mut file, - &rpc::GetEventsResponse { - events, - latest_ledger: ledger_info.sequence_number, - }, - )?; - - Ok(()) - } - - pub fn path(&self, pwd: &Path) -> PathBuf { - if let Some(path) = &self.events_file { - path.clone() - } else { - pwd.join("events.json") - } - } - - pub fn filter_events( - events: &[Event], - path: &Path, - start_cursor: (u64, i32), - contract_ids: &[String], - topic_filters: &[String], - count: usize, - ) -> Vec { - events - .iter() - .filter(|evt| match evt.parse_cursor() { - Ok(event_cursor) => event_cursor > start_cursor, - Err(e) => { - eprintln!("error parsing key 'ledger': {e:?}"); - eprintln!( - "your sandbox events file ('{path:?}') may be corrupt, consider deleting it", - ); - eprintln!("ignoring this event: {evt:#?}"); - - false - } - }) - .filter(|evt| { - // Contract ID filter(s) are optional, so we should render all - // events if they're omitted. - contract_ids.is_empty() || contract_ids.iter().any(|id| *id == evt.contract_id) - }) - .filter(|evt| { - // Like before, no topic filters means pass everything through. - topic_filters.is_empty() || - // Reminder: All of the topic filters are part of a single - // filter object, and each one contains segments, so we need to - // apply all of them to the given event. - topic_filters - .iter() - // quadratic, but both are <= 5 long - .any(|f| { - does_topic_match( - &evt.topic, - // misc. Rust nonsense: make a copy over the given - // split filter, because passing a slice of - // references is too much for this language to - // handle - &f.split(',') - .map(std::string::ToString::to_string) - .collect::>() - ) - }) - }) - .take(count) - .cloned() - .collect() - } -} diff --git a/cmd/soroban-cli/src/commands/config/ledger_file.rs b/cmd/soroban-cli/src/commands/config/ledger_file.rs deleted file mode 100644 index f85cbfdac..000000000 --- a/cmd/soroban-cli/src/commands/config/ledger_file.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::{commands::HEADING_SANDBOX, utils}; -use clap::arg; -use soroban_ledger_snapshot::LedgerSnapshot; -use std::path::{Path, PathBuf}; - -#[derive(Debug, clap::Args, Clone, Default)] -#[group(skip)] -pub struct Args { - /// File to persist ledger state, default is `.soroban/ledger.json` - #[arg( - long, - env = "SOROBAN_LEDGER_FILE", - help_heading = HEADING_SANDBOX, - )] - pub ledger_file: Option, -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("reading file {filepath}: {error}")] - CannotReadLedgerFile { - filepath: PathBuf, - error: soroban_ledger_snapshot::Error, - }, - - #[error("committing file {filepath}: {error}")] - CannotCommitLedgerFile { - filepath: PathBuf, - error: soroban_ledger_snapshot::Error, - }, -} - -impl Args { - pub fn read(&self, pwd: &Path) -> Result { - let filepath = self.path(pwd); - utils::ledger_snapshot_read_or_default(&filepath) - .map_err(|e| Error::CannotReadLedgerFile { filepath, error: e }) - } - - pub fn write(&self, state: &LedgerSnapshot, pwd: &Path) -> Result<(), Error> { - let filepath = self.path(pwd); - - state - .write_file(&filepath) - .map_err(|e| Error::CannotCommitLedgerFile { filepath, error: e }) - } - - pub fn path(&self, pwd: &Path) -> PathBuf { - if let Some(path) = &self.ledger_file { - path.clone() - } else { - pwd.join("ledger.json") - } - } -} diff --git a/cmd/soroban-cli/src/commands/config/mod.rs b/cmd/soroban-cli/src/commands/config/mod.rs index 8b47b32bf..f4d8ec554 100644 --- a/cmd/soroban-cli/src/commands/config/mod.rs +++ b/cmd/soroban-cli/src/commands/config/mod.rs @@ -2,15 +2,12 @@ use std::path::PathBuf; use clap::{arg, command, Parser}; use serde::{Deserialize, Serialize}; -use soroban_ledger_snapshot::LedgerSnapshot; use crate::Pwd; use self::{network::Network, secret::Secret}; -pub mod events_file; pub mod identity; -pub mod ledger_file; pub mod locator; pub mod network; pub mod secret; @@ -20,7 +17,6 @@ pub enum Cmd { /// Configure different identities to sign transactions. #[command(subcommand)] Identity(identity::Cmd), - /// Configure different networks #[command(subcommand)] Network(network::Cmd), @@ -30,16 +26,10 @@ pub enum Cmd { pub enum Error { #[error(transparent)] Identity(#[from] identity::Error), - #[error(transparent)] Network(#[from] network::Error), - - #[error(transparent)] - Ledger(#[from] ledger_file::Error), - #[error(transparent)] Secret(#[from] secret::Error), - #[error(transparent)] Config(#[from] locator::Error), } @@ -60,9 +50,6 @@ pub struct Args { #[command(flatten)] pub network: network::Args, - #[command(flatten)] - pub ledger_file: ledger_file::Args, - #[arg(long, visible_alias = "source", env = "SOROBAN_ACCOUNT")] /// Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` pub source_account: Option, @@ -98,18 +85,6 @@ impl Args { Ok(self.network.get(&self.locator)?) } - pub fn is_no_network(&self) -> bool { - self.network.is_no_network() - } - - pub fn get_state(&self) -> Result { - Ok(self.ledger_file.read(&self.locator.config_dir()?)?) - } - - pub fn set_state(&self, state: &LedgerSnapshot) -> Result<(), Error> { - Ok(self.ledger_file.write(state, &self.locator.config_dir()?)?) - } - pub fn config_dir(&self) -> Result { Ok(self.locator.config_dir()?) } diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index ef5856ea0..c0a780153 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -7,7 +7,7 @@ use crate::wasm; use crate::{ commands::{ config::{ - ledger_file, locator, + locator, network::{self, Network}, }, contract::{self, fetch}, @@ -21,22 +21,17 @@ pub struct Cmd { /// Path to optional wasm binary #[arg(long)] pub wasm: Option, - /// Where to place generated project #[arg(long)] output_dir: PathBuf, - /// Whether to overwrite output directory if it already exists #[arg(long)] overwrite: bool, - /// The contract ID/address on the network #[arg(long, visible_alias = "id")] contract_id: String, - #[command(flatten)] locator: locator::Args, - #[command(flatten)] network: network::Args, } @@ -79,7 +74,6 @@ impl Cmd { out_file: None, locator: self.locator.clone(), network: self.network.clone(), - ledger_file: ledger_file::Args::default(), }; let bytes = fetch.get_bytes().await?; ContractSpec::new(&bytes)?.spec diff --git a/cmd/soroban-cli/src/commands/contract/deploy.rs b/cmd/soroban-cli/src/commands/contract/deploy.rs index 7c7152bcc..2b3cffb17 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy.rs @@ -17,7 +17,7 @@ use soroban_env_host::{ }; use crate::{ - commands::{config, contract::install, HEADING_RPC, HEADING_SANDBOX}, + commands::{config, contract::install, HEADING_RPC}, rpc::{self, Client}, utils, wasm, }; @@ -33,22 +33,12 @@ pub struct Cmd { /// WASM file to deploy #[arg(long, group = "wasm_src")] wasm: Option, - /// Hash of the already installed/deployed WASM file #[arg(long = "wasm-hash", conflicts_with = "wasm", group = "wasm_src")] wasm_hash: Option, - - /// Contract ID to deploy to - #[arg( - long = "id", - conflicts_with = "rpc_url", - help_heading = HEADING_SANDBOX, - )] - contract_id: Option, /// Custom salt 32-byte salt for the token id #[arg( long, - conflicts_with_all = &["contract_id", "ledger_file"], help_heading = HEADING_RPC, )] salt: Option, @@ -125,34 +115,7 @@ impl Cmd { } })?); - if self.config.is_no_network() { - self.run_in_sandbox(hash) - } else { - self.run_against_rpc_server(hash).await - } - } - - #[allow(clippy::needless_pass_by_value)] - pub fn run_in_sandbox(&self, wasm_hash: Hash) -> Result { - let contract_id: [u8; 32] = match &self.contract_id { - Some(id) => { - utils::contract_id_from_str(id).map_err(|e| Error::CannotParseContractId { - contract_id: self.contract_id.as_ref().unwrap().clone(), - error: e, - })? - } - None => rand::thread_rng().gen::<[u8; 32]>(), - }; - - let mut state = self.config.get_state()?; - utils::add_contract_to_ledger_entries( - &mut state.ledger_entries, - contract_id, - wasm_hash.0, - state.min_persistent_entry_expiration, - ); - self.config.set_state(&state)?; - Ok(stellar_strkey::Contract(contract_id).to_string()) + self.run_against_rpc_server(hash).await } async fn run_against_rpc_server(&self, wasm_hash: Hash) -> Result { diff --git a/cmd/soroban-cli/src/commands/contract/bump.rs b/cmd/soroban-cli/src/commands/contract/extend.rs similarity index 60% rename from cmd/soroban-cli/src/commands/contract/bump.rs rename to cmd/soroban-cli/src/commands/contract/extend.rs index 06a86cf92..d98fb311f 100644 --- a/cmd/soroban-cli/src/commands/contract/bump.rs +++ b/cmd/soroban-cli/src/commands/contract/extend.rs @@ -2,10 +2,10 @@ use std::{fmt::Debug, path::Path, str::FromStr}; use clap::{command, Parser}; use soroban_env_host::xdr::{ - BumpFootprintExpirationOp, Error as XdrError, ExpirationEntry, ExtensionPoint, LedgerEntry, - LedgerEntryChange, LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation, - OperationBody, Preconditions, SequenceNumber, SorobanResources, SorobanTransactionData, - Transaction, TransactionExt, TransactionMeta, TransactionMetaV3, Uint256, + Error as XdrError, ExtendFootprintTtlOp, ExtensionPoint, LedgerEntry, LedgerEntryChange, + LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation, OperationBody, Preconditions, + SequenceNumber, SorobanResources, SorobanTransactionData, Transaction, TransactionExt, + TransactionMeta, TransactionMetaV3, TtlEntry, Uint256, }; use crate::{ @@ -15,22 +15,19 @@ use crate::{ wasm, Pwd, }; -const MAX_LEDGERS_TO_EXPIRE: u32 = 535_679; +const MAX_LEDGERS_TO_EXTEND: u32 = 535_679; #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { /// Number of ledgers to extend the entries #[arg(long, required = true)] - pub ledgers_to_expire: u32, - - /// Only print the new expiration ledger + pub ledgers_to_extend: u32, + /// Only print the new TTL ledger #[arg(long)] - pub expiration_ledger_only: bool, - + pub extension_ledger_only: bool, #[command(flatten)] pub key: key::Args, - #[command(flatten)] pub config: config::Args, #[command(flatten)] @@ -83,25 +80,21 @@ pub enum Error { impl Cmd { #[allow(clippy::too_many_lines)] pub async fn run(&self) -> Result<(), Error> { - let expiration_ledger_seq = if self.config.is_no_network() { - self.run_in_sandbox()? - } else { - self.run_against_rpc_server().await? - }; - if self.expiration_ledger_only { + let expiration_ledger_seq = self.run_against_rpc_server().await?; + if self.extension_ledger_only { println!("{expiration_ledger_seq}"); } else { - println!("New expiration ledger: {expiration_ledger_seq}"); + println!("New ttl ledger: {expiration_ledger_seq}"); } Ok(()) } - fn ledgers_to_expire(&self) -> u32 { - let res = u32::min(self.ledgers_to_expire, MAX_LEDGERS_TO_EXPIRE); - if res < self.ledgers_to_expire { + fn ledgers_to_extend(&self) -> u32 { + let res = u32::min(self.ledgers_to_extend, MAX_LEDGERS_TO_EXTEND); + if res < self.ledgers_to_extend { tracing::warn!( - "Ledgers to expire is too large, using max value of {MAX_LEDGERS_TO_EXPIRE}" + "Ledgers to extend is too large, using max value of {MAX_LEDGERS_TO_EXTEND}" ); } res @@ -114,7 +107,7 @@ impl Cmd { let network = &self.config.get_network()?; let client = Client::new(&network.rpc_url)?; let key = self.config.key_pair()?; - let ledgers_to_expire = self.ledgers_to_expire(); + let extend_to = self.ledgers_to_extend(); // Get the account sequence number let public_strkey = @@ -130,9 +123,9 @@ impl Cmd { memo: Memo::None, operations: vec![Operation { source_account: None, - body: OperationBody::BumpFootprintExpiration(BumpFootprintExpirationOp { + body: OperationBody::ExtendFootprintTtl(ExtendFootprintTtlOp { ext: ExtensionPoint::V0, - ledgers_to_expire, + extend_to, }), }] .try_into()?, @@ -147,7 +140,7 @@ impl Cmd { read_bytes: 0, write_bytes: 0, }, - refundable_fee: 0, + resource_fee: 0, }), }; @@ -161,13 +154,13 @@ impl Cmd { tracing::info!("Events:\n {events:#?}"); } - // The transaction from core will succeed regardless of whether it actually found & bumped + // The transaction from core will succeed regardless of whether it actually found & extended // the entry, so we have to inspect the result meta to tell if it worked or not. let TransactionMeta::V3(TransactionMetaV3 { operations, .. }) = meta else { return Err(Error::LedgerEntryNotFound); }; - // Simply check if there is exactly one entry here. We only support bumping a single + // Simply check if there is exactly one entry here. We only support extending a single // entry via this command (which we should fix separately, but). if operations.len() == 0 { return Err(Error::LedgerEntryNotFound); @@ -175,9 +168,9 @@ impl Cmd { if operations[0].changes.is_empty() { let entry = client.get_full_ledger_entries(&keys).await?; - let expire = entry.entries[0].expiration_ledger_seq; - if entry.latest_ledger + i64::from(ledgers_to_expire) < i64::from(expire) { - return Ok(expire); + let extension = entry.entries[0].live_until_ledger_seq; + if entry.latest_ledger + i64::from(extend_to) < i64::from(extension) { + return Ok(extension); } } @@ -186,56 +179,14 @@ impl Cmd { LedgerEntryChange::State(_), LedgerEntryChange::Updated(LedgerEntry { data: - LedgerEntryData::Expiration(ExpirationEntry { - expiration_ledger_seq, + LedgerEntryData::Ttl(TtlEntry { + live_until_ledger_seq, .. }), .. }), - ) => Ok(*expiration_ledger_seq), + ) => Ok(*live_until_ledger_seq), _ => Err(Error::LedgerEntryNotFound), } } - - fn run_in_sandbox(&self) -> Result { - let keys = self.key.parse_keys()?; - - // Initialize storage and host - // TODO: allow option to separate input and output file - let mut state = self.config.get_state()?; - - // Update all matching entries - let mut expiration_ledger_seq = None; - state.ledger_entries = state - .ledger_entries - .iter() - .map(|(k, v)| { - let new_k = k.as_ref().clone(); - let new_v = v.0.as_ref().clone(); - let new_e = v.1; - ( - Box::new(new_k.clone()), - ( - Box::new(new_v), - if keys.contains(&new_k) { - // It must have an expiration since it's a contract data entry - let old_expiration = v.1.unwrap(); - expiration_ledger_seq = Some(old_expiration + self.ledgers_to_expire); - expiration_ledger_seq - } else { - new_e - }, - ), - ) - }) - .collect::>(); - - self.config.set_state(&state)?; - - let Some(new_expiration_ledger_seq) = expiration_ledger_seq else { - return Err(Error::LedgerEntryNotFound); - }; - - Ok(new_expiration_ledger_seq) - } } diff --git a/cmd/soroban-cli/src/commands/contract/fetch.rs b/cmd/soroban-cli/src/commands/contract/fetch.rs index a1284123e..9929f3832 100644 --- a/cmd/soroban-cli/src/commands/contract/fetch.rs +++ b/cmd/soroban-cli/src/commands/contract/fetch.rs @@ -3,7 +3,7 @@ use std::convert::Infallible; use std::io::Write; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::{fmt::Debug, fs, io, rc::Rc}; +use std::{fmt::Debug, fs, io}; use clap::{arg, command, Parser}; use soroban_env_host::{ @@ -16,12 +16,10 @@ use soroban_env_host::{ }, }; -use soroban_ledger_snapshot::LedgerSnapshot; use soroban_spec::read::FromWasmError; use stellar_strkey::DecodeError; use super::super::config::{self, locator}; -use crate::commands::config::ledger_file; use crate::commands::config::network::{self, Network}; use crate::{ rpc::{self, Client}, @@ -42,8 +40,6 @@ pub struct Cmd { pub locator: locator::Args, #[command(flatten)] pub network: network::Args, - #[command(flatten)] - pub ledger_file: ledger_file::Args, } impl FromStr for Cmd { @@ -87,8 +83,6 @@ pub enum Error { NetworkNotProvided, #[error(transparent)] Network(#[from] network::Error), - #[error(transparent)] - Ledger(#[from] ledger_file::Error), #[error("cannot create contract directory for {0:?}")] CannotCreateContractDir(PathBuf), } @@ -121,11 +115,7 @@ impl Cmd { } pub async fn get_bytes(&self) -> Result, Error> { - if self.network.is_no_network() { - self.run_in_sandbox() - } else { - self.run_against_rpc_server().await - } + self.run_against_rpc_server().await } pub fn network(&self) -> Result { @@ -144,18 +134,6 @@ impl Cmd { Ok(client.get_remote_wasm(&contract_id).await?) } - pub fn get_state(&self) -> Result { - Ok(self.ledger_file.read(&self.locator.config_dir()?)?) - } - - pub fn run_in_sandbox(&self) -> Result, Error> { - let contract_id = self.contract_id()?; - // Initialize storage and host - let snap = Rc::new(self.get_state()?); - let mut storage = Storage::with_recording_footprint(snap); - Ok(get_contract_wasm_from_storage(&mut storage, contract_id)?) - } - fn contract_id(&self) -> Result<[u8; 32], Error> { utils::contract_id_from_str(&self.contract_id) .map_err(|e| Error::CannotParseContractId(self.contract_id.clone(), e)) @@ -198,7 +176,7 @@ pub fn get_contract_wasm_from_storage( Err(FromWasmError::NotFound) } } - ContractExecutable::Token => todo!(), + ContractExecutable::StellarAsset => todo!(), }, _ => Err(FromWasmError::NotFound), }, diff --git a/cmd/soroban-cli/src/commands/contract/install.rs b/cmd/soroban-cli/src/commands/contract/install.rs index 606383ea0..87c2877a7 100644 --- a/cmd/soroban-cli/src/commands/contract/install.rs +++ b/cmd/soroban-cli/src/commands/contract/install.rs @@ -55,28 +55,10 @@ impl Cmd { } pub async fn run_and_get_hash(&self) -> Result { - let contract = self.wasm.read()?; - if self.config.is_no_network() { - self.run_in_sandbox(contract) - } else { - self.run_against_rpc_server(contract).await - } - } - - pub fn run_in_sandbox(&self, contract: Vec) -> Result { - let mut state = self.config.get_state()?; - let wasm_hash = utils::add_contract_code_to_ledger_entries( - &mut state.ledger_entries, - contract, - state.min_persistent_entry_expiration, - )?; - - self.config.set_state(&state)?; - - Ok(wasm_hash) + self.run_against_rpc_server(&self.wasm.read()?).await } - async fn run_against_rpc_server(&self, contract: Vec) -> Result { + async fn run_against_rpc_server(&self, contract: &[u8]) -> Result { let network = self.config.get_network()?; let client = Client::new(&network.rpc_url)?; client @@ -91,7 +73,7 @@ impl Cmd { let sequence: i64 = account_details.seq_num.into(); let (tx_without_preflight, hash) = - build_install_contract_code_tx(contract.clone(), sequence + 1, self.fee.fee, &key)?; + build_install_contract_code_tx(contract, sequence + 1, self.fee.fee, &key)?; // Currently internal errors are not returned if the contract code is expired if let ( @@ -124,7 +106,7 @@ impl Cmd { }, config: self.config.clone(), fee: self.fee.clone(), - ledgers_to_expire: None, + ledgers_to_extend: None, } .run_against_rpc_server() .await?; @@ -135,12 +117,12 @@ impl Cmd { } pub(crate) fn build_install_contract_code_tx( - source_code: Vec, + source_code: &[u8], sequence: i64, fee: u32, key: &ed25519_dalek::SigningKey, ) -> Result<(Transaction, Hash), XdrError> { - let hash = utils::contract_hash(&source_code)?; + let hash = utils::contract_hash(source_code)?; let op = Operation { source_account: Some(MuxedAccount::Ed25519(Uint256( @@ -172,7 +154,7 @@ mod tests { #[test] fn test_build_install_contract_code() { let result = build_install_contract_code_tx( - b"foo".to_vec(), + b"foo", 300, 1, &utils::parse_secret_key("SBFGFF27Y64ZUGFAIG5AMJGQODZZKV2YQKAVUUN4HNE24XZXD2OEUVUP") diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index 8d83cff7f..59c9bf440 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -4,38 +4,34 @@ use std::ffi::OsString; use std::num::ParseIntError; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::{fmt::Debug, fs, io, rc::Rc}; +use std::{fmt::Debug, fs, io}; use clap::{arg, command, value_parser, Parser}; use ed25519_dalek::SigningKey; use heck::ToKebabCase; -use soroban_env_host::e2e_invoke::{get_ledger_changes, ExpirationEntryMap}; -use soroban_env_host::xdr::ReadXdr; + use soroban_env_host::{ - budget::Budget, - storage::Storage, xdr::{ - self, AccountId, Error as XdrError, Hash, HostFunction, InvokeContractArgs, - InvokeHostFunctionOp, LedgerEntryData, LedgerFootprint, LedgerKey, LedgerKeyAccount, Memo, - MuxedAccount, Operation, OperationBody, Preconditions, PublicKey, ScAddress, ScSpecEntry, - ScSpecFunctionV0, ScSpecTypeDef, ScVal, ScVec, SequenceNumber, SorobanAddressCredentials, - SorobanAuthorizationEntry, SorobanCredentials, SorobanResources, Transaction, - TransactionExt, Uint256, VecM, + self, Error as XdrError, Hash, HostFunction, InvokeContractArgs, InvokeHostFunctionOp, + LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation, OperationBody, + Preconditions, ScAddress, ScSpecEntry, ScSpecFunctionV0, ScSpecTypeDef, ScVal, ScVec, + SequenceNumber, SorobanAuthorizationEntry, SorobanResources, Transaction, TransactionExt, + Uint256, VecM, }, - DiagnosticLevel, Host, HostError, + HostError, }; use soroban_spec::read::FromWasmError; use stellar_strkey::DecodeError; use super::super::{ - config::{self, events_file, locator}, + config::{self, locator}, events, }; use crate::{ - commands::{global, HEADING_SANDBOX}, + commands::global, rpc::{self, Client}, - utils::{self, contract_spec, create_ledger_footprint, default_account_ledger_entry}, + utils::{self, contract_spec}, Pwd, }; use soroban_spec_tools::Spec; @@ -47,29 +43,18 @@ pub struct Cmd { /// Contract ID to invoke #[arg(long = "id", env = "SOROBAN_CONTRACT_ID")] pub contract_id: String, - /// WASM file of the contract to invoke (if using sandbox will deploy this file) - #[arg(long)] + // For testing only + #[arg(skip)] pub wasm: Option, - /// Output the cost execution to stderr - #[arg(long = "cost", conflicts_with = "rpc_url", conflicts_with="network", help_heading = HEADING_SANDBOX)] + #[arg(long = "cost")] pub cost: bool, - /// Run with an unlimited budget - #[arg(long = "unlimited-budget", - conflicts_with = "rpc_url", - conflicts_with = "network", - help_heading = HEADING_SANDBOX)] - pub unlimited_budget: bool, - /// Function name as subcommand, then arguments for that function as `--arg-name value` #[arg(last = true, id = "CONTRACT_FN_AND_ARGS")] pub slop: Vec, - #[command(flatten)] pub config: config::Args, #[command(flatten)] - pub events_file: events_file::Args, - #[command(flatten)] pub fee: crate::fee::Args, } @@ -149,8 +134,6 @@ pub enum Error { #[error(transparent)] Clap(#[from] clap::Error), #[error(transparent)] - Events(#[from] events_file::Error), - #[error(transparent)] Locator(#[from] locator::Error), #[error("Contract Error\n{0}: {1}")] ContractInvoke(String, String), @@ -270,11 +253,7 @@ impl Cmd { } pub async fn invoke(&self, global_args: &global::Args) -> Result { - if self.config.is_no_network() { - self.run_in_sandbox(global_args) - } else { - self.run_against_rpc_server(global_args).await - } + self.run_against_rpc_server(global_args).await } pub async fn run_against_rpc_server( @@ -284,6 +263,11 @@ impl Cmd { let network = self.config.get_network()?; tracing::trace!(?network); let contract_id = self.contract_id()?; + let spec_entries = self.spec_entries()?; + if let Some(spec_entries) = &spec_entries { + // For testing wasm arg parsing + let _ = self.build_host_function_parameters(contract_id, spec_entries)?; + } let client = Client::new(&network.rpc_url)?; client .verify_network_passphrase(Some(&network.network_passphrase)) @@ -297,11 +281,7 @@ impl Cmd { let sequence: i64 = account_details.seq_num.into(); // Get the contract - let spec_entries = if let Some(spec) = self.spec_entries()? { - spec - } else { - client.get_remote_contract_spec(&contract_id).await? - }; + let spec_entries = client.get_remote_contract_spec(&contract_id).await?; // Get the ledger footprint let (function, spec, host_function_params, signers) = @@ -338,145 +318,6 @@ impl Cmd { output_to_string(&spec, &return_value, &function) } - pub fn run_in_sandbox(&self, global_args: &global::Args) -> Result { - let contract_id = self.contract_id()?; - // Initialize storage and host - // TODO: allow option to separate input and output file - let mut state = self.config.get_state()?; - - // If a file is specified, deploy the contract to storage - self.deploy_contract_in_sandbox(&mut state, &contract_id)?; - - // Create source account, adding it to the ledger if not already present. - let source_account = AccountId(PublicKey::PublicKeyTypeEd25519(Uint256( - self.config.key_pair()?.verifying_key().to_bytes(), - ))); - let source_account_ledger_key = LedgerKey::Account(LedgerKeyAccount { - account_id: source_account.clone(), - }); - if !state - .ledger_entries - .iter() - .any(|(k, _)| **k == source_account_ledger_key) - { - state.ledger_entries.push(( - Box::new(source_account_ledger_key), - ( - Box::new(default_account_ledger_entry(source_account.clone())), - None, - ), - )); - } - - let snap = Rc::new(state.clone()); - let storage = Storage::with_recording_footprint(snap); - let spec_entries = if let Some(spec) = self.spec_entries()? { - spec - } else { - utils::get_contract_spec_from_state(&state, contract_id) - .map_err(Error::CannotParseContractSpec)? - }; - let budget = Budget::default(); - if self.unlimited_budget { - budget.reset_unlimited()?; - }; - let h = Host::with_storage_and_budget(storage, budget); - h.switch_to_recording_auth(true)?; - h.set_source_account(source_account)?; - h.set_base_prng_seed(rand::Rng::gen(&mut rand::thread_rng()))?; - - let mut ledger_info = state.ledger_info(); - ledger_info.sequence_number += 1; - ledger_info.timestamp += 5; - h.set_ledger_info(ledger_info.clone())?; - - let (function, spec, host_function_params, _signers) = - self.build_host_function_parameters(contract_id, &spec_entries)?; - h.set_diagnostic_level(DiagnosticLevel::Debug)?; - let resv = h - .invoke_function(HostFunction::InvokeContract(host_function_params)) - .map_err(|host_error| { - if let Ok(error) = spec.find_error_type(host_error.error.get_code()) { - Error::ContractInvoke(error.name.to_string_lossy(), error.doc.to_string_lossy()) - } else { - host_error.into() - } - })?; - - let res_str = output_to_string(&spec, &resv, &function)?; - - state.update(&h); - - let contract_auth: Vec = h - .get_recorded_auth_payloads()? - .into_iter() - .map(|payload| SorobanAuthorizationEntry { - credentials: match (payload.address, payload.nonce) { - (Some(address), Some(nonce)) => { - SorobanCredentials::Address(SorobanAddressCredentials { - address, - nonce, - signature_expiration_ledger: ledger_info.sequence_number + 1, - signature: ScVal::Void, - }) - } - _ => SorobanCredentials::SourceAccount, - }, - root_invocation: payload.invocation, - }) - .collect(); - let budget = h.budget_cloned(); - let (storage, events) = h.try_finish()?; - let footprint = &create_ledger_footprint(&storage.footprint); - - crate::log::host_events(&events.0); - log_events(footprint, &[contract_auth.try_into()?], &[]); - if global_args.verbose || global_args.very_verbose || self.cost { - log_budget(&budget); - } - - let ledger_changes = - get_ledger_changes(&budget, &storage, &state, ExpirationEntryMap::new())?; - let mut expiration_ledger_bumps: HashMap = HashMap::new(); - for ledger_entry_change in ledger_changes { - if let Some(exp_change) = ledger_entry_change.expiration_change { - let key = xdr::LedgerKey::from_xdr(ledger_entry_change.encoded_key)?; - expiration_ledger_bumps.insert(key, exp_change.new_expiration_ledger); - } - } - utils::bump_ledger_entry_expirations(&mut state.ledger_entries, &expiration_ledger_bumps); - - self.config.set_state(&state)?; - if !events.0.is_empty() { - self.events_file - .commit(&events.0, &state, &self.config.locator.config_dir()?)?; - } - Ok(res_str) - } - - pub fn deploy_contract_in_sandbox( - &self, - state: &mut soroban_ledger_snapshot::LedgerSnapshot, - contract_id: &[u8; 32], - ) -> Result<(), Error> { - if let Some(contract) = self.read_wasm()? { - let wasm_hash = utils::add_contract_code_to_ledger_entries( - &mut state.ledger_entries, - contract, - state.min_persistent_entry_expiration, - ) - .map_err(Error::CannotAddContractToLedgerEntries)? - .0; - utils::add_contract_to_ledger_entries( - &mut state.ledger_entries, - *contract_id, - wasm_hash, - state.min_persistent_entry_expiration, - ); - } - Ok(()) - } - pub fn read_wasm(&self) -> Result>, Error> { Ok(if let Some(wasm) = self.wasm.as_ref() { Some(fs::read(wasm).map_err(|e| Error::CannotReadContractFile(wasm.clone(), e))?) @@ -511,10 +352,6 @@ fn log_events( crate::log::footprint(footprint); } -fn log_budget(budget: &Budget) { - crate::log::budget(budget); -} - fn log_resources(resources: &SorobanResources) { crate::log::cost(resources); } diff --git a/cmd/soroban-cli/src/commands/contract/mod.rs b/cmd/soroban-cli/src/commands/contract/mod.rs index c2dc1a677..b07011a28 100644 --- a/cmd/soroban-cli/src/commands/contract/mod.rs +++ b/cmd/soroban-cli/src/commands/contract/mod.rs @@ -1,7 +1,7 @@ pub mod bindings; pub mod build; -pub mod bump; pub mod deploy; +pub mod extend; pub mod fetch; pub mod inspect; pub mod install; @@ -22,13 +22,13 @@ pub enum Cmd { /// Extend the expiry ledger of a contract-data ledger entry. /// - /// If no keys are specified the contract itself is bumped. - Bump(bump::Cmd), + /// If no keys are specified the contract itself is extended. + Extend(extend::Cmd), /// Deploy a contract Deploy(deploy::Cmd), - /// Fetch a contract's Wasm binary from a network or local sandbox + /// Fetch a contract's Wasm binary Fetch(fetch::Cmd), /// Inspect a WASM file listing contract functions, meta, etc @@ -68,7 +68,7 @@ pub enum Error { Build(#[from] build::Error), #[error(transparent)] - Bump(#[from] bump::Error), + Extend(#[from] extend::Error), #[error(transparent)] Deploy(#[from] deploy::Error), @@ -100,7 +100,7 @@ impl Cmd { match &self { Cmd::Bindings(bindings) => bindings.run().await?, Cmd::Build(build) => build.run()?, - Cmd::Bump(bump) => bump.run().await?, + Cmd::Extend(extend) => extend.run().await?, Cmd::Deploy(deploy) => deploy.run().await?, Cmd::Inspect(inspect) => inspect.run()?, Cmd::Install(install) => install.run().await?, diff --git a/cmd/soroban-cli/src/commands/contract/read.rs b/cmd/soroban-cli/src/commands/contract/read.rs index 4c47f8887..8fa943273 100644 --- a/cmd/soroban-cli/src/commands/contract/read.rs +++ b/cmd/soroban-cli/src/commands/contract/read.rs @@ -90,11 +90,7 @@ pub enum Error { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let entries = if self.config.is_no_network() { - self.run_in_sandbox()? - } else { - self.run_against_rpc_server().await? - }; + let entries = self.run_against_rpc_server().await?; self.output_entries(&entries) } @@ -107,31 +103,6 @@ impl Cmd { Ok(client.get_full_ledger_entries(&keys).await?) } - #[allow(clippy::too_many_lines)] - fn run_in_sandbox(&self) -> Result { - let state = self.config.get_state()?; - let ledger_entries = &state.ledger_entries; - let latest_ledger = u32::try_from(state.ledger_entries.len()).unwrap(); - let keys = self.key.parse_keys()?; - let entries = ledger_entries - .iter() - .map(|(k, v)| (k.as_ref().clone(), (v.0.as_ref().clone(), v.1))) - .filter(|(k, _v)| keys.contains(k)) - .map(|(key, (v, expiration))| { - Ok(FullLedgerEntry { - expiration_ledger_seq: expiration.unwrap_or_default(), - last_modified_ledger: latest_ledger, - key, - val: v.data, - }) - }) - .collect::, Error>>()?; - Ok(FullLedgerEntries { - entries, - latest_ledger: 0, - }) - } - fn output_entries(&self, entries: &FullLedgerEntries) -> Result<(), Error> { if entries.entries.is_empty() { return Err(Error::NoContractDataEntryFoundForContractID); @@ -141,7 +112,7 @@ impl Cmd { for FullLedgerEntry { key, val, - expiration_ledger_seq, + live_until_ledger_seq, last_modified_ledger, } in &entries.entries { @@ -163,7 +134,7 @@ impl Cmd { error: e, })?, last_modified_ledger.to_string(), - expiration_ledger_seq.to_string(), + live_until_ledger_seq.to_string(), ], Output::Json => [ serde_json::to_string_pretty(&key).map_err(|error| { @@ -184,7 +155,7 @@ impl Cmd { error, } })?, - serde_json::to_string_pretty(&expiration_ledger_seq).map_err(|error| { + serde_json::to_string_pretty(&live_until_ledger_seq).map_err(|error| { Error::CannotPrintJsonResult { result: val.clone(), error, @@ -195,7 +166,7 @@ impl Cmd { key.to_xdr_base64()?, val.to_xdr_base64()?, last_modified_ledger.to_xdr_base64()?, - expiration_ledger_seq.to_xdr_base64()?, + live_until_ledger_seq.to_xdr_base64()?, ], }; out.write_record(output) diff --git a/cmd/soroban-cli/src/commands/contract/restore.rs b/cmd/soroban-cli/src/commands/contract/restore.rs index b6c8cd385..f10cdb780 100644 --- a/cmd/soroban-cli/src/commands/contract/restore.rs +++ b/cmd/soroban-cli/src/commands/contract/restore.rs @@ -2,17 +2,17 @@ use std::{fmt::Debug, path::Path, str::FromStr}; use clap::{command, Parser}; use soroban_env_host::xdr::{ - Error as XdrError, ExpirationEntry, ExtensionPoint, LedgerEntry, LedgerEntryChange, - LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation, OperationBody, OperationMeta, - Preconditions, RestoreFootprintOp, SequenceNumber, SorobanResources, SorobanTransactionData, - Transaction, TransactionExt, TransactionMeta, TransactionMetaV3, Uint256, + Error as XdrError, ExtensionPoint, LedgerEntry, LedgerEntryChange, LedgerEntryData, + LedgerFootprint, Memo, MuxedAccount, Operation, OperationBody, OperationMeta, Preconditions, + RestoreFootprintOp, SequenceNumber, SorobanResources, SorobanTransactionData, Transaction, + TransactionExt, TransactionMeta, TransactionMetaV3, TtlEntry, Uint256, }; use stellar_strkey::DecodeError; use crate::{ commands::{ config::{self, locator}, - contract::bump, + contract::extend, }, key, rpc::{self, Client}, @@ -26,7 +26,7 @@ pub struct Cmd { pub key: key::Args, /// Number of ledgers to extend the entry #[arg(long)] - pub ledgers_to_expire: Option, + pub ledgers_to_extend: Option, #[command(flatten)] pub config: config::Args, #[command(flatten)] @@ -78,30 +78,26 @@ pub enum Error { #[error(transparent)] Key(#[from] key::Error), #[error(transparent)] - Bump(#[from] bump::Error), + Extend(#[from] extend::Error), } impl Cmd { #[allow(clippy::too_many_lines)] pub async fn run(&self) -> Result<(), Error> { - let expiration_ledger_seq = if self.config.is_no_network() { - self.run_in_sandbox()? - } else { - self.run_against_rpc_server().await? - }; + let expiration_ledger_seq = self.run_against_rpc_server().await?; - if let Some(ledgers_to_expire) = self.ledgers_to_expire { - bump::Cmd { + if let Some(ledgers_to_extend) = self.ledgers_to_extend { + extend::Cmd { key: self.key.clone(), - ledgers_to_expire, + ledgers_to_extend, config: self.config.clone(), fee: self.fee.clone(), - expiration_ledger_only: false, + extension_ledger_only: false, } .run() .await?; } else { - println!("New expiration ledger: {expiration_ledger_seq}"); + println!("New ttl ledger: {expiration_ledger_seq}"); } Ok(()) @@ -145,7 +141,7 @@ impl Cmd { read_bytes: 0, write_bytes: 0, }, - refundable_fee: 0, + resource_fee: 0, }), }; @@ -166,7 +162,7 @@ impl Cmd { }; tracing::debug!("Operations:\nlen:{}\n{operations:#?}", operations.len()); - // Simply check if there is exactly one entry here. We only support bumping a single + // Simply check if there is exactly one entry here. We only support extending a single // entry via this command (which we should fix separately, but). if operations.len() == 0 { return Err(Error::LedgerEntryNotFound); @@ -180,12 +176,6 @@ impl Cmd { } parse_operations(&operations).ok_or(Error::MissingOperationResult) } - - pub fn run_in_sandbox(&self) -> Result { - // TODO: Implement this. This means we need to store ledger entries somewhere, and handle - // eviction, and restoration with that evicted state store. - todo!("Restoring ledger entries is not supported in the local sandbox mode"); - } } fn parse_operations(ops: &[OperationMeta]) -> Option { @@ -193,20 +183,20 @@ fn parse_operations(ops: &[OperationMeta]) -> Option { op.changes.iter().find_map(|entry| match entry { LedgerEntryChange::Updated(LedgerEntry { data: - LedgerEntryData::Expiration(ExpirationEntry { - expiration_ledger_seq, + LedgerEntryData::Ttl(TtlEntry { + live_until_ledger_seq, .. }), .. }) | LedgerEntryChange::Created(LedgerEntry { data: - LedgerEntryData::Expiration(ExpirationEntry { - expiration_ledger_seq, + LedgerEntryData::Ttl(TtlEntry { + live_until_ledger_seq, .. }), .. - }) => Some(*expiration_ledger_seq), + }) => Some(*live_until_ledger_seq), _ => None, }) }) diff --git a/cmd/soroban-cli/src/commands/events.rs b/cmd/soroban-cli/src/commands/events.rs index 83809d428..002920de2 100644 --- a/cmd/soroban-cli/src/commands/events.rs +++ b/cmd/soroban-cli/src/commands/events.rs @@ -3,18 +3,16 @@ use std::io; use soroban_env_host::xdr::{self, ReadXdr}; -use super::config::{events_file, locator, network}; -use crate::{rpc, toid, utils}; +use super::config::{locator, network}; +use crate::{rpc, utils}; #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { - /// The first ledger sequence number in the range to pull events (required - /// if not in sandbox mode). + /// The first ledger sequence number in the range to pull events /// https://developers.stellar.org/docs/encyclopedia/ledger-headers#ledger-sequence #[arg(long, conflicts_with = "cursor", required_unless_present = "cursor")] start_ledger: Option, - /// The cursor corresponding to the start of the event range. #[arg( long, @@ -22,17 +20,12 @@ pub struct Cmd { required_unless_present = "start_ledger" )] cursor: Option, - /// Output formatting options for event stream #[arg(long, value_enum, default_value = "pretty")] output: OutputFormat, - - /// The maximum number of events to display (specify "0" to show all events - /// when using sandbox, or to defer to the server-defined limit if using - /// RPC). + /// The maximum number of events to display (defer to the server-defined limit). #[arg(short, long, default_value = "10")] count: usize, - /// A set of (up to 5) contract IDs to filter events on. This parameter can /// be passed multiple times, e.g. `--id C123.. --id C456..`, or passed with /// multiple parameters, e.g. `--id C123 C456`. @@ -46,7 +39,6 @@ pub struct Cmd { help_heading = "FILTERS" )] contract_ids: Vec, - /// A set of (up to 4) topic filters to filter event topics on. A single /// topic filter can contain 1-4 different segment filters, separated by /// commas, with an asterisk (* character) indicating a wildcard segment. @@ -67,7 +59,6 @@ pub struct Cmd { help_heading = "FILTERS" )] topic_filters: Vec, - /// Specifies which type of contract events to display. #[arg( long = "type", @@ -76,79 +67,56 @@ pub struct Cmd { help_heading = "FILTERS" )] event_type: rpc::EventType, - #[command(flatten)] locator: locator::Args, - #[command(flatten)] network: network::Args, - - #[command(flatten)] - events_file: events_file::Args, } #[derive(thiserror::Error, Debug)] pub enum Error { #[error("cursor is not valid")] InvalidCursor, - #[error("filepath does not exist: {path}")] InvalidFile { path: String }, - #[error("filepath ({path}) cannot be read: {error}")] CannotReadFile { path: String, error: String }, - #[error("cannot parse topic filter {topic} into 1-4 segments")] InvalidTopicFilter { topic: String }, - #[error("invalid segment ({segment}) in topic filter ({topic}): {error}")] InvalidSegment { topic: String, segment: String, error: xdr::Error, }, - #[error("cannot parse contract ID {contract_id}: {error}")] InvalidContractId { contract_id: String, error: stellar_strkey::DecodeError, }, - #[error("invalid JSON string: {error} ({debug})")] InvalidJson { debug: String, error: serde_json::Error, }, - #[error("invalid timestamp in event: {ts}")] InvalidTimestamp { ts: String }, - #[error("missing start_ledger and cursor")] MissingStartLedgerAndCursor, #[error("missing target")] MissingTarget, - #[error(transparent)] Rpc(#[from] rpc::Error), - #[error(transparent)] Generic(#[from] Box), - #[error(transparent)] Io(#[from] io::Error), - #[error(transparent)] Xdr(#[from] xdr::Error), - #[error(transparent)] Serde(#[from] serde_json::Error), - #[error(transparent)] Network(#[from] network::Error), - - #[error(transparent)] - EventsFile(#[from] events_file::Error), - #[error(transparent)] Locator(#[from] locator::Error), } @@ -194,11 +162,7 @@ impl Cmd { })?; } - let response = if self.network.is_no_network() { - self.run_in_sandbox() - } else { - self.run_against_rpc_server().await - }?; + let response = self.run_against_rpc_server().await?; for event in &response.events { match self.output { @@ -245,36 +209,6 @@ impl Cmd { .map_err(Error::Rpc) } - pub fn run_in_sandbox(&self) -> Result { - let start = self.start()?; - let count: usize = if self.count == 0 { - std::usize::MAX - } else { - self.count - }; - - let start_cursor = match start { - rpc::EventStart::Ledger(l) => (toid::Toid::new(l, 0, 0).into(), -1), - rpc::EventStart::Cursor(c) => rpc::parse_cursor(&c)?, - }; - let path = self.locator.config_dir()?; - let file = self.events_file.read(&path)?; - - // Read the JSON events from disk and find the ones that match the - // contract ID filter(s) that were passed in. - Ok(rpc::GetEventsResponse { - events: events_file::Args::filter_events( - &file.events, - &path, - start_cursor, - &self.contract_ids, - &self.topic_filters, - count, - ), - latest_ledger: file.latest_ledger, - }) - } - fn start(&self) -> Result { let start = match (self.start_ledger, self.cursor.clone()) { (Some(start), _) => rpc::EventStart::Ledger(start), @@ -285,95 +219,3 @@ impl Cmd { Ok(start) } } - -#[cfg(test)] -mod tests { - use std::path; - - use assert_fs::NamedTempFile; - use soroban_env_host::events; - use soroban_sdk::xdr::VecM; - - use super::*; - - use events_file::Args; - #[test] - fn test_does_event_serialization_match() { - let temp = NamedTempFile::new("events.json").unwrap(); - let events_file = Args { - events_file: Some(temp.to_path_buf()), - }; - // Make a couple of fake events with slightly different properties and - // write them to disk, then read the serialized versions from disk and - // ensure the properties match. - - let events: Vec = vec![ - events::HostEvent { - event: xdr::ContractEvent { - ext: xdr::ExtensionPoint::V0, - contract_id: Some(xdr::Hash([0; 32])), - type_: xdr::ContractEventType::Contract, - body: xdr::ContractEventBody::V0(xdr::ContractEventV0 { - topics: VecM::default(), - data: xdr::ScVal::U32(12345), - }), - }, - failed_call: false, - }, - events::HostEvent { - event: xdr::ContractEvent { - ext: xdr::ExtensionPoint::V0, - contract_id: Some(xdr::Hash([0x1; 32])), - type_: xdr::ContractEventType::Contract, - body: xdr::ContractEventBody::V0(xdr::ContractEventV0 { - topics: VecM::default(), - data: xdr::ScVal::I32(67890), - }), - }, - failed_call: false, - }, - ]; - - let ledger_info = soroban_ledger_snapshot::LedgerSnapshot { - protocol_version: 1, - sequence_number: 2, // this is the only value that matters - timestamp: 3, - network_id: [0x1; 32], - base_reserve: 5, - ledger_entries: vec![], - max_entry_expiration: 6, - min_persistent_entry_expiration: 7, - min_temp_entry_expiration: 8, - }; - - events_file.commit(&events, &ledger_info, &temp).unwrap(); - - let file = events_file.read(&std::env::current_dir().unwrap()).unwrap(); - assert_eq!(file.events.len(), 2); - assert_eq!(file.events[0].ledger, "2"); - assert_eq!(file.events[1].ledger, "2"); - assert_eq!( - file.events[0].contract_id, - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSC4" - ); - assert_eq!( - file.events[1].contract_id, - "CAAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQC526" - ); - assert_eq!(file.latest_ledger, 2); - } - - #[test] - fn test_does_event_fixture_load() { - // This test ensures that the included JSON fixture file matches the - // correct event format (for the purposes of human readability). - let filename = - path::PathBuf::from("../crates/soroban-test/tests/fixtures/test-jsons/get-events.json"); - let events_file = Args { - events_file: Some(filename), - }; - let result = events_file.read(&std::env::current_dir().unwrap()); - println!("{result:?}"); - assert!(result.is_ok()); - } -} diff --git a/cmd/soroban-cli/src/commands/lab/token/wrap.rs b/cmd/soroban-cli/src/commands/lab/token/wrap.rs index 4cd2dfb08..2b6f4dd4f 100644 --- a/cmd/soroban-cli/src/commands/lab/token/wrap.rs +++ b/cmd/soroban-cli/src/commands/lab/token/wrap.rs @@ -1,17 +1,15 @@ use clap::{arg, command, Parser}; use soroban_env_host::{ - budget::Budget, - storage::Storage, xdr::{ Asset, ContractDataDurability, ContractExecutable, ContractIdPreimage, CreateContractArgs, Error as XdrError, Hash, HostFunction, InvokeHostFunctionOp, LedgerKey::ContractData, LedgerKeyContractData, Memo, MuxedAccount, Operation, OperationBody, Preconditions, ScAddress, ScVal, SequenceNumber, Transaction, TransactionExt, Uint256, VecM, }, - Host, HostError, + HostError, }; use std::convert::Infallible; -use std::{array::TryFromSliceError, fmt::Debug, num::ParseIntError, rc::Rc}; +use std::{array::TryFromSliceError, fmt::Debug, num::ParseIntError}; use crate::{ commands::config, @@ -63,42 +61,11 @@ impl Cmd { // Parse asset let asset = parse_asset(&self.asset)?; - let res_str = if self.config.is_no_network() { - self.run_in_sandbox(&asset)? - } else { - self.run_against_rpc_server(asset).await? - }; + let res_str = self.run_against_rpc_server(asset).await?; println!("{res_str}"); Ok(()) } - pub fn run_in_sandbox(&self, asset: &Asset) -> Result { - // Initialize storage and host - // TODO: allow option to separate input and output file - let mut state = self.config.get_state()?; - - let snap = Rc::new(state.clone()); - let h = Host::with_storage_and_budget( - Storage::with_recording_footprint(snap), - Budget::default(), - ); - - let mut ledger_info = state.ledger_info(); - ledger_info.sequence_number += 1; - ledger_info.timestamp += 5; - h.set_ledger_info(ledger_info)?; - - let res = h.invoke_function(HostFunction::CreateContract(CreateContractArgs { - contract_id_preimage: ContractIdPreimage::Asset(asset.clone()), - executable: ContractExecutable::Token, - }))?; - - let contract_id = vec_to_hash(&res)?; - state.update(&h); - self.config.set_state(&state)?; - Ok(stellar_strkey::Contract(contract_id.0).to_string()) - } - async fn run_against_rpc_server(&self, asset: Asset) -> Result { let network = self.config.get_network()?; let client = Client::new(&network.rpc_url)?; @@ -185,7 +152,7 @@ fn build_wrap_token_tx( body: OperationBody::InvokeHostFunction(InvokeHostFunctionOp { host_function: HostFunction::CreateContract(CreateContractArgs { contract_id_preimage: ContractIdPreimage::Asset(asset.clone()), - executable: ContractExecutable::Token, + executable: ContractExecutable::StellarAsset, }), auth: VecM::default(), }), diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index 295144f9d..a9f668082 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -11,7 +11,6 @@ pub mod lab; pub mod plugin; pub mod version; -pub const HEADING_SANDBOX: &str = "Options (Sandbox)"; pub const HEADING_RPC: &str = "Options (RPC)"; const ABOUT: &str = "Build, deploy, & interact with contracts; set identities to sign with; configure networks; generate keys; and more. @@ -33,11 +32,13 @@ Commands that relate to smart contract interactions are organized under the `con A Soroban contract has its interface schema types embedded in the binary that gets deployed on-chain, making it possible to dynamically generate a custom CLI for each. `soroban contract invoke` makes use of this: - soroban contract invoke --id 1 --source alice -- --help + soroban contract invoke --id CCR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OTE2 --source alice --network testnet -- \ + --help Anything after the `--` double dash (the \"slop\") is parsed as arguments to the contract-specific CLI, generated on-the-fly from the embedded schema. For the hello world example, with a function called `hello` that takes one string argument `to`, here's how you invoke it: - soroban contract invoke --id 1 --source alice -- hello --to world + soroban contract invoke --id CCR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OTE2 --source alice --network testnet -- \ + hello --to world Full CLI reference: https://github.com/stellar/soroban-tools/tree/main/docs/soroban-cli-full-docs.md"; diff --git a/cmd/soroban-cli/src/key.rs b/cmd/soroban-cli/src/key.rs index d48c61683..ae3086f54 100644 --- a/cmd/soroban-cli/src/key.rs +++ b/cmd/soroban-cli/src/key.rs @@ -26,7 +26,7 @@ pub enum Error { #[group(skip)] pub struct Args { /// Contract ID to which owns the data entries. - /// If no keys provided the Contract's instance will be bumped + /// If no keys provided the Contract's instance will be extended #[arg( long = "id", required_unless_present = "wasm", @@ -39,7 +39,7 @@ pub struct Args { /// Storage key (base64-encoded XDR) #[arg(long = "key-xdr", conflicts_with = "key")] pub key_xdr: Option>, - /// Path to Wasm file of contract code to bump + /// Path to Wasm file of contract code to extend #[arg( long, conflicts_with = "contract_id", @@ -48,7 +48,7 @@ pub struct Args { conflicts_with = "wasm_hash" )] pub wasm: Option, - /// Path to Wasm file of contract code to bump + /// Path to Wasm file of contract code to extend #[arg( long, conflicts_with = "contract_id", diff --git a/cmd/soroban-cli/src/lib.rs b/cmd/soroban-cli/src/lib.rs index 1589bc485..3aad487c8 100644 --- a/cmd/soroban-cli/src/lib.rs +++ b/cmd/soroban-cli/src/lib.rs @@ -7,7 +7,6 @@ pub mod commands; pub mod fee; pub mod key; pub mod log; -pub mod network; pub mod rpc; pub mod toid; pub mod utils; diff --git a/cmd/soroban-cli/src/network.rs b/cmd/soroban-cli/src/network.rs deleted file mode 100644 index d0bc3427f..000000000 --- a/cmd/soroban-cli/src/network.rs +++ /dev/null @@ -1,8 +0,0 @@ -use sha2::{Digest, Sha256}; - -pub static SANDBOX_NETWORK_PASSPHRASE: &str = "Local Sandbox Stellar Network ; September 2022"; - -#[must_use] -pub fn sandbox_network_id() -> [u8; 32] { - Sha256::digest(SANDBOX_NETWORK_PASSPHRASE.as_bytes()).into() -} diff --git a/cmd/soroban-cli/src/rpc/mod.rs b/cmd/soroban-cli/src/rpc/mod.rs index 5123f0f17..46da57a91 100644 --- a/cmd/soroban-cli/src/rpc/mod.rs +++ b/cmd/soroban-cli/src/rpc/mod.rs @@ -98,8 +98,6 @@ pub enum Error { SpecBase64(#[from] soroban_spec::read::ParseSpecBase64Error), #[error("Fee was too large {0}")] LargeFee(u64), - #[error("Failed to parse LedgerEntryData\nkey:{0:?}\nvalue:{1:?}\nexpiration:{2:?}")] - FailedParseLedgerEntryData(LedgerKey, LedgerEntryData, LedgerEntryData), } #[derive(serde::Deserialize, serde::Serialize, Debug)] @@ -154,12 +152,12 @@ pub struct LedgerEntryResult { )] pub last_modified_ledger: u32, #[serde( - rename = "expirationLedgerSeq", + rename = "liveUntilLedgerSeqLedgerSeq", skip_serializing_if = "Option::is_none", deserialize_with = "deserialize_option_number_from_string", default )] - pub expiration_ledger_seq: Option, + pub live_until_ledger_seq_ledger_seq: Option, } #[derive(serde::Deserialize, serde::Serialize, Debug)] @@ -435,7 +433,7 @@ pub struct FullLedgerEntry { pub key: LedgerKey, pub val: LedgerEntryData, pub last_modified_ledger: u32, - pub expiration_ledger_seq: u32, + pub live_until_ledger_seq: u32, } #[derive(Debug)] @@ -777,7 +775,7 @@ soroban config identity fund {address} --helper-url "# ) -> Result { let keys = ledger_keys .iter() - .filter(|key| !matches!(key, LedgerKey::Expiration(_))) + .filter(|key| !matches!(key, LedgerKey::Ttl(_))) .map(Clone::clone) .collect::>(); tracing::trace!("keys: {keys:#?}"); @@ -794,12 +792,12 @@ soroban config identity fund {address} --helper-url "# key, xdr, last_modified_ledger, - expiration_ledger_seq, + live_until_ledger_seq_ledger_seq, }| { Ok(FullLedgerEntry { key: LedgerKey::from_xdr_base64(key)?, val: LedgerEntryData::from_xdr_base64(xdr)?, - expiration_ledger_seq: expiration_ledger_seq.unwrap_or_default(), + live_until_ledger_seq: live_until_ledger_seq_ledger_seq.unwrap_or_default(), last_modified_ledger: *last_modified_ledger, }) }, @@ -920,7 +918,7 @@ soroban config identity fund {address} --helper-url "# .map_err(Error::CouldNotParseContractSpec)? .spec), xdr::ScVal::ContractInstance(xdr::ScContractInstance { - executable: xdr::ContractExecutable::Token, + executable: xdr::ContractExecutable::StellarAsset, .. }) => Ok(soroban_spec::read::parse_raw( &token::StellarAssetSpec::spec_xdr(), diff --git a/cmd/soroban-cli/src/rpc/transaction.rs b/cmd/soroban-cli/src/rpc/transaction.rs index f2ed5eeee..bdd3dfc68 100644 --- a/cmd/soroban-cli/src/rpc/transaction.rs +++ b/cmd/soroban-cli/src/rpc/transaction.rs @@ -274,7 +274,7 @@ mod tests { read_bytes: 5, write_bytes: 0, }, - refundable_fee: 0, + resource_fee: 0, ext: ExtensionPoint::V0, } } diff --git a/cmd/soroban-cli/src/utils.rs b/cmd/soroban-cli/src/utils.rs index 0cbf9dfbc..fcc3964c9 100644 --- a/cmd/soroban-cli/src/utils.rs +++ b/cmd/soroban-cli/src/utils.rs @@ -1,28 +1,13 @@ -use std::hash::BuildHasher; -use std::{collections::HashMap, io::ErrorKind, path::Path}; - use ed25519_dalek::Signer; use sha2::{Digest, Sha256}; - -use soroban_env_host::{ - storage::{AccessType, Footprint}, - xdr::{ - AccountEntry, AccountEntryExt, AccountId, Asset, ContractCodeEntry, ContractDataDurability, - ContractDataEntry, ContractExecutable, ContractIdPreimage, DecoratedSignature, - Error as XdrError, ExtensionPoint, Hash, HashIdPreimage, HashIdPreimageContractId, - LedgerEntry, LedgerEntryData, LedgerEntryExt, LedgerFootprint, LedgerKey, - LedgerKeyContractCode, LedgerKeyContractData, ScAddress, ScContractInstance, ScSpecEntry, - ScVal, SequenceNumber, Signature, SignatureHint, String32, Thresholds, Transaction, - TransactionEnvelope, TransactionSignaturePayload, - TransactionSignaturePayloadTaggedTransaction, TransactionV1Envelope, VecM, WriteXdr, - }, -}; -use soroban_ledger_snapshot::LedgerSnapshot; -use soroban_sdk::token; -use soroban_spec::read::FromWasmError; use stellar_strkey::ed25519::PrivateKey; -use crate::network::sandbox_network_id; +use soroban_env_host::xdr::{ + Asset, ContractIdPreimage, DecoratedSignature, Error as XdrError, Hash, HashIdPreimage, + HashIdPreimageContractId, Signature, SignatureHint, Transaction, TransactionEnvelope, + TransactionSignaturePayload, TransactionSignaturePayloadTaggedTransaction, + TransactionV1Envelope, WriteXdr, +}; pub mod contract_spec; @@ -33,122 +18,6 @@ pub fn contract_hash(contract: &[u8]) -> Result { Ok(Hash(Sha256::digest(contract).into())) } -/// # Errors -/// -/// Might return an error -pub fn ledger_snapshot_read_or_default( - p: impl AsRef, -) -> Result { - match LedgerSnapshot::read_file(p) { - Ok(snapshot) => Ok(snapshot), - Err(soroban_ledger_snapshot::Error::Io(e)) if e.kind() == ErrorKind::NotFound => { - Ok(LedgerSnapshot { - network_id: sandbox_network_id(), - // These three "defaults" are not part of the actual default definition in - // rs-soroban-sdk, but if we don't have them the sandbox doesn't work right. - // Oof. - // TODO: Remove this hacky workaround. - min_persistent_entry_expiration: 4096, - min_temp_entry_expiration: 16, - max_entry_expiration: 6_312_000, - ..Default::default() - }) - } - Err(e) => Err(e), - } -} - -type LedgerSnapshotEntries = Vec<(Box, (Box, Option))>; - -/// # Errors -/// -/// Might return an error -pub fn add_contract_code_to_ledger_entries( - entries: &mut LedgerSnapshotEntries, - contract: Vec, - min_persistent_entry_expiration: u32, -) -> Result { - // Install the code - let hash = contract_hash(contract.as_slice())?; - let code_key = LedgerKey::ContractCode(LedgerKeyContractCode { hash: hash.clone() }); - let code_entry = LedgerEntry { - last_modified_ledger_seq: 0, - data: LedgerEntryData::ContractCode(ContractCodeEntry { - ext: ExtensionPoint::V0, - hash: hash.clone(), - code: contract.try_into()?, - }), - ext: LedgerEntryExt::V0, - }; - for (k, e) in &mut *entries { - if **k == code_key { - *e = (Box::new(code_entry), Some(min_persistent_entry_expiration)); - return Ok(hash); - } - } - entries.push(( - Box::new(code_key), - (Box::new(code_entry), Some(min_persistent_entry_expiration)), - )); - Ok(hash) -} - -pub fn add_contract_to_ledger_entries( - entries: &mut LedgerSnapshotEntries, - contract_id: [u8; 32], - wasm_hash: [u8; 32], - min_persistent_entry_expiration: u32, -) { - // Create the contract - let contract_key = LedgerKey::ContractData(LedgerKeyContractData { - contract: ScAddress::Contract(contract_id.into()), - key: ScVal::LedgerKeyContractInstance, - durability: ContractDataDurability::Persistent, - }); - - let contract_entry = LedgerEntry { - last_modified_ledger_seq: 0, - data: LedgerEntryData::ContractData(ContractDataEntry { - contract: ScAddress::Contract(contract_id.into()), - key: ScVal::LedgerKeyContractInstance, - durability: ContractDataDurability::Persistent, - val: ScVal::ContractInstance(ScContractInstance { - executable: ContractExecutable::Wasm(Hash(wasm_hash)), - storage: None, - }), - ext: ExtensionPoint::V0, - }), - ext: LedgerEntryExt::V0, - }; - for (k, e) in &mut *entries { - if **k == contract_key { - *e = ( - Box::new(contract_entry), - Some(min_persistent_entry_expiration), - ); - return; - } - } - entries.push(( - Box::new(contract_key), - ( - Box::new(contract_entry), - Some(min_persistent_entry_expiration), - ), - )); -} - -pub fn bump_ledger_entry_expirations( - entries: &mut LedgerSnapshotEntries, - lookup: &HashMap, -) { - for (k, (_, expiration)) in &mut *entries { - if let Some(min_expiration) = lookup.get(k.as_ref()) { - *expiration = Some(*min_expiration); - } - } -} - /// # Errors /// /// Might return an error @@ -198,129 +67,6 @@ pub fn contract_id_from_str(contract_id: &str) -> Result<[u8; 32], stellar_strke .map_err(|_| stellar_strkey::DecodeError::Invalid) } -fn get_entry_from_snapshot( - key: &LedgerKey, - entries: &LedgerSnapshotEntries, -) -> Option<(Box, Option)> { - for (k, result) in entries { - if *key == **k { - return Some((*result).clone()); - } - } - None -} - -/// # Errors -/// -/// Might return an error -pub fn get_contract_spec_from_state( - state: &LedgerSnapshot, - contract_id: [u8; 32], -) -> Result, FromWasmError> { - let current_ledger_seq = state.sequence_number; - let key = LedgerKey::ContractData(LedgerKeyContractData { - contract: ScAddress::Contract(contract_id.into()), - key: ScVal::LedgerKeyContractInstance, - durability: ContractDataDurability::Persistent, - }); - let (entry, expiration_ledger_seq) = match get_entry_from_snapshot(&key, &state.ledger_entries) - { - // It's a contract data entry, so it should have an expiration if present - Some((entry, expiration)) => (entry, expiration.unwrap()), - None => return Err(FromWasmError::NotFound), - }; - if expiration_ledger_seq <= current_ledger_seq { - return Err(FromWasmError::NotFound); - } - - match *entry { - LedgerEntry { - data: - LedgerEntryData::ContractData(ContractDataEntry { - val: ScVal::ContractInstance(ScContractInstance { executable, .. }), - .. - }), - .. - } => match executable { - ContractExecutable::Token => { - // TODO/FIXME: I don't think it will work for token contracts, since we don't store them in the state? - let res = soroban_spec::read::parse_raw(&token::StellarAssetSpec::spec_xdr()); - res.map_err(FromWasmError::Parse) - } - ContractExecutable::Wasm(hash) => { - // It's a contract code entry, so it should have an expiration if present - let (entry, expiration_ledger_seq) = match get_entry_from_snapshot( - &LedgerKey::ContractCode(LedgerKeyContractCode { hash: hash.clone() }), - &state.ledger_entries, - ) { - // It's a contract data entry, so it should have an expiration if present - Some((entry, expiration)) => (entry, expiration.unwrap()), - None => return Err(FromWasmError::NotFound), - }; - if expiration_ledger_seq <= current_ledger_seq { - return Err(FromWasmError::NotFound); - } - match *entry { - LedgerEntry { - data: LedgerEntryData::ContractCode(ContractCodeEntry { code, .. }), - .. - } => soroban_spec::read::from_wasm(code.as_vec()), - _ => Err(FromWasmError::NotFound), - } - } - }, - _ => Err(FromWasmError::NotFound), - } -} - -/// # Panics -/// -/// May panic -#[must_use] -pub fn create_ledger_footprint(footprint: &Footprint) -> LedgerFootprint { - let mut read_only: Vec = vec![]; - let mut read_write: Vec = vec![]; - let Footprint(m) = footprint; - for (k, v) in m { - let dest = match v { - AccessType::ReadOnly => &mut read_only, - AccessType::ReadWrite => &mut read_write, - }; - dest.push((**k).clone()); - } - LedgerFootprint { - read_only: read_only.try_into().unwrap(), - read_write: read_write.try_into().unwrap(), - } -} - -#[must_use] -pub fn default_account_ledger_entry(account_id: AccountId) -> LedgerEntry { - // TODO: Consider moving the definition of a default account ledger entry to - // a location shared by the SDK and CLI. The SDK currently defines the same - // value (see URL below). There's some benefit in only defining this once to - // prevent the two from diverging, which would cause inconsistent test - // behavior between the SDK and CLI. A good home for this is unclear at this - // time. - // https://github.com/stellar/rs-soroban-sdk/blob/b6f9a2c7ec54d2d5b5a1e02d1e38ae3158c22e78/soroban-sdk/src/accounts.rs#L470-L483. - LedgerEntry { - data: LedgerEntryData::Account(AccountEntry { - account_id, - balance: 0, - flags: 0, - home_domain: String32::default(), - inflation_dest: None, - num_sub_entries: 0, - seq_num: SequenceNumber(0), - thresholds: Thresholds([1; 4]), - signers: VecM::default(), - ext: AccountEntryExt::V0, - }), - last_modified_ledger_seq: 0, - ext: LedgerEntryExt::V0, - } -} - /// # Errors /// May not find a config dir pub fn find_config_dir(mut pwd: std::path::PathBuf) -> std::io::Result { diff --git a/cmd/soroban-rpc/internal/events/cursor.go b/cmd/soroban-rpc/internal/events/cursor.go index e872a31cc..9f37b5130 100644 --- a/cmd/soroban-rpc/internal/events/cursor.go +++ b/cmd/soroban-rpc/internal/events/cursor.go @@ -69,7 +69,7 @@ func ParseCursor(input string) (Cursor, error) { parsed := toid.Parse(idInt) // Parse the second part (event order) - eventOrder, err := strconv.ParseInt(parts[1], 10, 64) //lint:ignore gomnd + eventOrder, err := strconv.ParseUint(parts[1], 10, 32) //lint:ignore gomnd if err != nil { return Cursor{}, fmt.Errorf("invalid event id %s: %w", input, err) } diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index 436c1f264..1827a95b5 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -283,9 +283,10 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { handler = http.MaxBytesHandler(handler, maxHTTPRequestSize) corsMiddleware := cors.New(cors.Options{ - AllowedOrigins: []string{"*"}, - AllowedHeaders: []string{"*"}, - AllowedMethods: []string{"GET", "PUT", "POST", "PATCH", "DELETE", "HEAD", "OPTIONS"}, + AllowedOrigins: []string{}, + AllowOriginRequestFunc: func(*http.Request, string) bool { return true }, + AllowedHeaders: []string{"*"}, + AllowedMethods: []string{"GET", "PUT", "POST", "PATCH", "DELETE", "HEAD", "OPTIONS"}, }) return Handler{ diff --git a/cmd/soroban-rpc/internal/test/cli_test.go b/cmd/soroban-rpc/internal/test/cli_test.go index 4229fc289..4af05ccf4 100644 --- a/cmd/soroban-rpc/internal/test/cli_test.go +++ b/cmd/soroban-rpc/internal/test/cli_test.go @@ -26,7 +26,7 @@ import ( func cargoTest(t *testing.T, name string) { NewCLITest(t) - c := icmd.Command("cargo", "test", "--package", "soroban-test", "--test", "it", "--", name, "--exact", "--nocapture") + c := icmd.Command("cargo", "test", "--features", "integration", "--package", "soroban-test", "--test", "it", "--", name, "--exact", "--nocapture") c.Env = append(os.Environ(), fmt.Sprintf("SOROBAN_RPC_URL=http://localhost:%d/", sorobanRPCPort), fmt.Sprintf("SOROBAN_NETWORK_PASSPHRASE=%s", StandaloneNetworkPassphrase), @@ -36,10 +36,9 @@ func cargoTest(t *testing.T, name string) { } func TestCLICargoTest(t *testing.T) { - result := icmd.RunCmd(icmd.Command("cargo", "-q", "test", "integration_and_sandbox::", "--package", "soroban-test", "--", "--list")) - require.NoError(t, result.Error) - input := result.Stdout() - lines := strings.Split(input, "\n") + names := icmd.RunCmd(icmd.Command("cargo", "-q", "test", "integration::", "--package", "soroban-test", "--features", "integration", "--", "--list")) + input := names.Stdout() + lines := strings.Split(strings.TrimSpace(input), "\n") for _, line := range lines { testName := strings.TrimSuffix(line, ": test") t.Run(testName, func(t *testing.T) { @@ -127,7 +126,7 @@ func TestCLIRestorePreamble(t *testing.T) { require.Equal(t, "3", count) } -func TestCLIBump(t *testing.T) { +func TestCLIExtend(t *testing.T) { test := NewCLITest(t) strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) @@ -139,19 +138,19 @@ func TestCLIBump(t *testing.T) { ttlKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) initialLiveUntilSeq := getLedgerEntryLiveUntil(t, client, ttlKey) - bumpOutput := runSuccessfulCLICmd( + extendOutput := runSuccessfulCLICmd( t, fmt.Sprintf( - "contract bump --id %s --key COUNTER --durability persistent --ledgers-to-expire 20", + "contract extend --id %s --key COUNTER --durability persistent --ledgers-to-extend 20", strkeyContractID, ), ) newLiveUntilSeq := getLedgerEntryLiveUntil(t, client, ttlKey) assert.Greater(t, newLiveUntilSeq, initialLiveUntilSeq) - assert.Equal(t, fmt.Sprintf("New ttl ledger: %d", newLiveUntilSeq), bumpOutput) + assert.Equal(t, fmt.Sprintf("New ttl ledger: %d", newLiveUntilSeq), extendOutput) } -func TestCLIBumpTooLow(t *testing.T) { +func TestCLIExtendTooLow(t *testing.T) { test := NewCLITest(t) strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) @@ -163,17 +162,17 @@ func TestCLIBumpTooLow(t *testing.T) { ttlKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) initialLiveUntilSeq := parseInt(t, getLedgerEntryLiveUntil(t, client, ttlKey).GoString()) - bumpOutput := bump(t, strkeyContractID, "400", "--key COUNTER ") + extendOutput := extend(t, strkeyContractID, "400", "--key COUNTER ") newLiveUntilSeq := parseInt(t, getLedgerEntryLiveUntil(t, client, ttlKey).GoString()) assert.Greater(t, newLiveUntilSeq, initialLiveUntilSeq) - assert.Equal(t, newLiveUntilSeq, bumpOutput) + assert.Equal(t, newLiveUntilSeq, extendOutput) - updatedLiveUntilSeq := bump(t, strkeyContractID, "15", "--key COUNTER") - assert.Equal(t, bumpOutput, updatedLiveUntilSeq) + updatedLiveUntilSeq := extend(t, strkeyContractID, "15", "--key COUNTER") + assert.Equal(t, extendOutput, updatedLiveUntilSeq) } -func TestCLIBumpTooHigh(t *testing.T) { +func TestCLIExtendTooHigh(t *testing.T) { test := NewCLITest(t) strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) @@ -185,11 +184,11 @@ func TestCLIBumpTooHigh(t *testing.T) { ttlKey := getCounterLedgerKey(parseContractStrKey(t, strkeyContractID)) initialLiveUntilSeq := parseInt(t, getLedgerEntryLiveUntil(t, client, ttlKey).GoString()) - bumpOutput := bump(t, strkeyContractID, "100000000", "--key COUNTER ") + extendOutput := extend(t, strkeyContractID, "100000000", "--key COUNTER ") newLiveUntilSeq := parseInt(t, getLedgerEntryLiveUntil(t, client, ttlKey).GoString()) assert.Greater(t, newLiveUntilSeq, initialLiveUntilSeq) - assert.Equal(t, newLiveUntilSeq, bumpOutput) + assert.Equal(t, newLiveUntilSeq, extendOutput) } func TestCLIRestore(t *testing.T) { @@ -325,12 +324,12 @@ func parseInt(t *testing.T, s string) uint64 { return i } -func bump(t *testing.T, contractId string, amount string, rest string) uint64 { +func extend(t *testing.T, contractId string, amount string, rest string) uint64 { res := runSuccessfulCLICmd( t, fmt.Sprintf( - "contract bump --expiration-ledger-only --id=%s --durability persistent --ledgers-to-expire=%s %s", + "contract extend --extension-ledger-only --id=%s --durability persistent --ledgers-to-extend=%s %s", contractId, amount, rest, diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index 47f3de192..7a04c4d07 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -246,8 +246,8 @@ func TestSimulateTransactionSucceeds(t *testing.T) { assert.Equal(t, expectedTransactionData.Resources.Footprint, transactionData.Resources.Footprint) assert.InDelta(t, uint32(expectedTransactionData.Resources.Instructions), uint32(transactionData.Resources.Instructions), 200000) assert.InDelta(t, uint32(expectedTransactionData.Resources.ReadBytes), uint32(transactionData.Resources.ReadBytes), 10) - assert.InDelta(t, uint32(expectedTransactionData.Resources.WriteBytes), uint32(transactionData.Resources.WriteBytes), 100) - assert.InDelta(t, int64(expectedTransactionData.ResourceFee), int64(transactionData.ResourceFee), 1000) + assert.InDelta(t, uint32(expectedTransactionData.Resources.WriteBytes), uint32(transactionData.Resources.WriteBytes), 300) + assert.InDelta(t, int64(expectedTransactionData.ResourceFee), int64(transactionData.ResourceFee), 3000) // Then decode and check the result xdr, separately so we get a decent diff if it fails. assert.Len(t, result.Results, 1) @@ -1122,7 +1122,7 @@ func TestSimulateSystemEvent(t *testing.T) { require.NoError(t, err) assert.InDelta(t, 7260, uint32(transactionData.Resources.ReadBytes), 200) - assert.InDelta(t, 98339, int64(transactionData.ResourceFee), 10) + assert.InDelta(t, 98339, int64(transactionData.ResourceFee), 2000) assert.InDelta(t, 104, uint32(transactionData.Resources.WriteBytes), 15) require.GreaterOrEqual(t, len(response.Events), 3) } diff --git a/cmd/soroban-rpc/lib/preflight/src/fees.rs b/cmd/soroban-rpc/lib/preflight/src/fees.rs index 3e034422b..20e002b3d 100644 --- a/cmd/soroban-rpc/lib/preflight/src/fees.rs +++ b/cmd/soroban-rpc/lib/preflight/src/fees.rs @@ -23,6 +23,7 @@ use state_ttl::{get_restored_ledger_sequence, TTLLedgerEntry}; use std::cmp::max; use std::convert::{TryFrom, TryInto}; +#[allow(clippy::too_many_arguments)] pub(crate) fn compute_host_function_transaction_data_and_min_fee( op: &InvokeHostFunctionOp, pre_storage: &LedgerStorage, @@ -224,7 +225,7 @@ fn get_fee_configurations( } // Calculate the implicit TTLEntry bytes that will be read for TTLLedgerEntries -fn calculate_ttl_entry_bytes(ledger_entries: &Vec) -> u32 { +fn calculate_ttl_entry_bytes(ledger_entries: &[LedgerKey]) -> u32 { ledger_entries .iter() .map(|lk| match lk { @@ -319,7 +320,7 @@ pub(crate) fn compute_extend_footprint_ttl_transaction_data_and_min_fee( extend_to, current_ledger_seq, ) - .context("cannot compute bump rent changes")?; + .context("cannot compute extend rent changes")?; let ttl_bytes: u32 = calculate_ttl_entry_bytes(footprint.read_only.as_vec()); @@ -372,10 +373,10 @@ fn compute_extend_footprint_rent_changes( ) -> Result> { let mut rent_changes: Vec = Vec::with_capacity(footprint.read_only.len()); - for key in (&footprint).read_only.as_slice() { - let unmodified_entry_and_ttl = ledger_storage - .get(key, false) - .with_context(|| format!("cannot find bump footprint ledger entry with key {key:?}"))?; + for key in footprint.read_only.as_slice() { + let unmodified_entry_and_ttl = ledger_storage.get(key, false).with_context(|| { + format!("cannot find extend footprint ledger entry with key {key:?}") + })?; let size = (key.to_xdr()?.len() + unmodified_entry_and_ttl.0.to_xdr()?.len()) as u32; let ttl_entry: Box = (&unmodified_entry_and_ttl) @@ -385,7 +386,7 @@ fn compute_extend_footprint_rent_changes( })?; let new_live_until_ledger = current_ledger_seq + extend_to; if new_live_until_ledger <= ttl_entry.live_until_ledger_seq() { - // The bump would be ineffective + // The extend would be ineffective continue; } let rent_change = LedgerEntryRentChange { diff --git a/cmd/soroban-rpc/lib/preflight/src/ledger_storage.rs b/cmd/soroban-rpc/lib/preflight/src/ledger_storage.rs index 276252d76..3581e6956 100644 --- a/cmd/soroban-rpc/lib/preflight/src/ledger_storage.rs +++ b/cmd/soroban-rpc/lib/preflight/src/ledger_storage.rs @@ -247,7 +247,7 @@ impl SnapshotSource for LedgerStorage { return Ok((entry_and_ttl.0.into(), entry_and_ttl.1)); } let entry_and_ttl = ::get(self, key, false).map_err(HostError::from)?; - return Ok((entry_and_ttl.0.into(), entry_and_ttl.1)); + Ok((entry_and_ttl.0.into(), entry_and_ttl.1)) } fn has(&self, key: &Rc) -> Result { diff --git a/docs/soroban-cli-full-docs.md b/docs/soroban-cli-full-docs.md index 35bb76977..30ffbe4b7 100644 --- a/docs/soroban-cli-full-docs.md +++ b/docs/soroban-cli-full-docs.md @@ -12,7 +12,7 @@ This document contains the help content for the `soroban` command-line program. * [`soroban contract bindings rust`↴](#soroban-contract-bindings-rust) * [`soroban contract bindings typescript`↴](#soroban-contract-bindings-typescript) * [`soroban contract build`↴](#soroban-contract-build) -* [`soroban contract bump`↴](#soroban-contract-bump) +* [`soroban contract extend`↴](#soroban-contract-extend) * [`soroban contract deploy`↴](#soroban-contract-deploy) * [`soroban contract fetch`↴](#soroban-contract-fetch) * [`soroban contract inspect`↴](#soroban-contract-inspect) @@ -62,11 +62,11 @@ Commands that relate to smart contract interactions are organized under the `con A Soroban contract has its interface schema types embedded in the binary that gets deployed on-chain, making it possible to dynamically generate a custom CLI for each. `soroban contract invoke` makes use of this: - soroban contract invoke --id 1 --source alice -- --help + soroban contract invoke --id CCR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OTE2 --source alice --network testnet -- --help Anything after the `--` double dash (the "slop") is parsed as arguments to the contract-specific CLI, generated on-the-fly from the embedded schema. For the hello world example, with a function called `hello` that takes one string argument `to`, here's how you invoke it: - soroban contract invoke --id 1 --source alice -- hello --to world + soroban contract invoke --id CCR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OTE2 --source alice --network testnet -- hello --to world Full CLI reference: https://github.com/stellar/soroban-tools/tree/main/docs/soroban-cli-full-docs.md @@ -127,9 +127,9 @@ Tools for smart contract developers * `bindings` — Generate code client bindings for a contract * `build` — Build a contract from source -* `bump` — Extend the expiry ledger of a contract-data ledger entry +* `extend` — Extend the expiry ledger of a contract-data ledger entry * `deploy` — Deploy a contract -* `fetch` — Fetch a contract's Wasm binary from a network or local sandbox +* `fetch` — Fetch a contract's Wasm binary * `inspect` — Inspect a WASM file listing contract functions, meta, etc * `install` — Install a WASM file to the ledger without creating a contract instance * `invoke` — Invoke a contract function @@ -224,23 +224,23 @@ To view the commands that will be executed, without executing them, use the --pr -## `soroban contract bump` +## `soroban contract extend` Extend the expiry ledger of a contract-data ledger entry. -If no keys are specified the contract itself is bumped. +If no keys are specified the contract itself is extended. -**Usage:** `soroban contract bump [OPTIONS] --ledgers-to-expire --durability ` +**Usage:** `soroban contract extend [OPTIONS] --ledgers-to-extend --durability ` ###### **Options:** -* `--ledgers-to-expire ` — Number of ledgers to extend the entries -* `--expiration-ledger-only` — Only print the new expiration ledger -* `--id ` — Contract ID to which owns the data entries. If no keys provided the Contract's instance will be bumped +* `--ledgers-to-extend ` — Number of ledgers to extend the entries +* `--extension-ledger-only` — Only print the new TTL ledger +* `--id ` — Contract ID to which owns the data entries. If no keys provided the Contract's instance will be extended * `--key ` — Storage key (symbols only) * `--key-xdr ` — Storage key (base64-encoded XDR) -* `--wasm ` — Path to Wasm file of contract code to bump -* `--wasm-hash ` — Path to Wasm file of contract code to bump +* `--wasm ` — Path to Wasm file of contract code to extend +* `--wasm-hash ` — Path to Wasm file of contract code to extend * `--durability ` — Storage entry durability Possible values: @@ -252,7 +252,6 @@ If no keys are specified the contract itself is bumped. * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config @@ -273,12 +272,10 @@ Deploy a contract * `--wasm ` — WASM file to deploy * `--wasm-hash ` — Hash of the already installed/deployed WASM file -* `--id ` — Contract ID to deploy to * `--salt ` — Custom salt 32-byte salt for the token id * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config @@ -291,7 +288,7 @@ Deploy a contract ## `soroban contract fetch` -Fetch a contract's Wasm binary from a network or local sandbox +Fetch a contract's Wasm binary **Usage:** `soroban contract fetch [OPTIONS] --id ` @@ -304,7 +301,6 @@ Fetch a contract's Wasm binary from a network or local sandbox * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` @@ -345,7 +341,6 @@ Install a WASM file to the ledger without creating a contract instance * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config @@ -374,18 +369,14 @@ soroban contract invoke ... -- --help ###### **Options:** * `--id ` — Contract ID to invoke -* `--wasm ` — WASM file of the contract to invoke (if using sandbox will deploy this file) * `--cost` — Output the cost execution to stderr -* `--unlimited-budget` — Run with an unlimited budget * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` -* `--events-file ` — File to persist events, default is `.soroban/events.json` * `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm Default value: `100` @@ -425,11 +416,11 @@ Print the current value of a contract-data ledger entry - `xdr`: XDR -* `--id ` — Contract ID to which owns the data entries. If no keys provided the Contract's instance will be bumped +* `--id ` — Contract ID to which owns the data entries. If no keys provided the Contract's instance will be extended * `--key ` — Storage key (symbols only) * `--key-xdr ` — Storage key (base64-encoded XDR) -* `--wasm ` — Path to Wasm file of contract code to bump -* `--wasm-hash ` — Path to Wasm file of contract code to bump +* `--wasm ` — Path to Wasm file of contract code to extend +* `--wasm-hash ` — Path to Wasm file of contract code to extend * `--durability ` — Storage entry durability Possible values: @@ -441,7 +432,6 @@ Print the current value of a contract-data ledger entry * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config @@ -459,11 +449,11 @@ If no keys are specificed the contract itself is restored. ###### **Options:** -* `--id ` — Contract ID to which owns the data entries. If no keys provided the Contract's instance will be bumped +* `--id ` — Contract ID to which owns the data entries. If no keys provided the Contract's instance will be extended * `--key ` — Storage key (symbols only) * `--key-xdr ` — Storage key (base64-encoded XDR) -* `--wasm ` — Path to Wasm file of contract code to bump -* `--wasm-hash ` — Path to Wasm file of contract code to bump +* `--wasm ` — Path to Wasm file of contract code to extend +* `--wasm-hash ` — Path to Wasm file of contract code to extend * `--durability ` — Storage entry durability Possible values: @@ -472,11 +462,10 @@ If no keys are specificed the contract itself is restored. - `temporary`: Temporary -* `--ledgers-to-expire ` — Number of ledgers to extend the entry +* `--ledgers-to-extend ` — Number of ledgers to extend the entry * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config @@ -720,7 +709,7 @@ Watch the network for contract events ###### **Options:** -* `--start-ledger ` — The first ledger sequence number in the range to pull events (required if not in sandbox mode). https://developers.stellar.org/docs/encyclopedia/ledger-headers#ledger-sequence +* `--start-ledger ` — The first ledger sequence number in the range to pull events https://developers.stellar.org/docs/encyclopedia/ledger-headers#ledger-sequence * `--cursor ` — The cursor corresponding to the start of the event range * `--output ` — Output formatting options for event stream @@ -734,7 +723,7 @@ Watch the network for contract events - `json`: JSONified console output -* `-c`, `--count ` — The maximum number of events to display (specify "0" to show all events when using sandbox, or to defer to the server-defined limit if using RPC) +* `-c`, `--count ` — The maximum number of events to display (defer to the server-defined limit) Default value: `10` * `--id ` — A set of (up to 5) contract IDs to filter events on. This parameter can be passed multiple times, e.g. `--id C123.. --id C456..`, or passed with multiple parameters, e.g. `--id C123 C456` @@ -750,7 +739,6 @@ Watch the network for contract events * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--events-file ` — File to persist events, default is `.soroban/events.json` @@ -792,7 +780,6 @@ Deploy a token contract to wrap an existing Stellar classic asset for smart cont * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config @@ -815,7 +802,6 @@ Compute the expected contract id for the given asset * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config -* `--ledger-file ` — File to persist ledger state, default is `.soroban/ledger.json` * `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config @@ -845,7 +831,7 @@ Decode XDR * `--type ` — XDR type to decode to - Possible values: `Value`, `ScpBallot`, `ScpStatementType`, `ScpNomination`, `ScpStatement`, `ScpStatementPledges`, `ScpStatementPrepare`, `ScpStatementConfirm`, `ScpStatementExternalize`, `ScpEnvelope`, `ScpQuorumSet`, `ConfigSettingContractExecutionLanesV0`, `ConfigSettingContractComputeV0`, `ConfigSettingContractLedgerCostV0`, `ConfigSettingContractHistoricalDataV0`, `ConfigSettingContractEventsV0`, `ConfigSettingContractBandwidthV0`, `ContractCostType`, `ContractCostParamEntry`, `StateExpirationSettings`, `EvictionIterator`, `ContractCostParams`, `ConfigSettingId`, `ConfigSettingEntry`, `ScEnvMetaKind`, `ScEnvMetaEntry`, `ScMetaV0`, `ScMetaKind`, `ScMetaEntry`, `ScSpecType`, `ScSpecTypeOption`, `ScSpecTypeResult`, `ScSpecTypeVec`, `ScSpecTypeMap`, `ScSpecTypeTuple`, `ScSpecTypeBytesN`, `ScSpecTypeUdt`, `ScSpecTypeDef`, `ScSpecUdtStructFieldV0`, `ScSpecUdtStructV0`, `ScSpecUdtUnionCaseVoidV0`, `ScSpecUdtUnionCaseTupleV0`, `ScSpecUdtUnionCaseV0Kind`, `ScSpecUdtUnionCaseV0`, `ScSpecUdtUnionV0`, `ScSpecUdtEnumCaseV0`, `ScSpecUdtEnumV0`, `ScSpecUdtErrorEnumCaseV0`, `ScSpecUdtErrorEnumV0`, `ScSpecFunctionInputV0`, `ScSpecFunctionV0`, `ScSpecEntryKind`, `ScSpecEntry`, `ScValType`, `ScErrorType`, `ScErrorCode`, `ScError`, `UInt128Parts`, `Int128Parts`, `UInt256Parts`, `Int256Parts`, `ContractExecutableType`, `ContractExecutable`, `ScAddressType`, `ScAddress`, `ScVec`, `ScMap`, `ScBytes`, `ScString`, `ScSymbol`, `ScNonceKey`, `ScContractInstance`, `ScVal`, `ScMapEntry`, `StoredTransactionSet`, `PersistedScpStateV0`, `PersistedScpStateV1`, `PersistedScpState`, `Thresholds`, `String32`, `String64`, `SequenceNumber`, `DataValue`, `PoolId`, `AssetCode4`, `AssetCode12`, `AssetType`, `AssetCode`, `AlphaNum4`, `AlphaNum12`, `Asset`, `Price`, `Liabilities`, `ThresholdIndexes`, `LedgerEntryType`, `Signer`, `AccountFlags`, `SponsorshipDescriptor`, `AccountEntryExtensionV3`, `AccountEntryExtensionV2`, `AccountEntryExtensionV2Ext`, `AccountEntryExtensionV1`, `AccountEntryExtensionV1Ext`, `AccountEntry`, `AccountEntryExt`, `TrustLineFlags`, `LiquidityPoolType`, `TrustLineAsset`, `TrustLineEntryExtensionV2`, `TrustLineEntryExtensionV2Ext`, `TrustLineEntry`, `TrustLineEntryExt`, `TrustLineEntryV1`, `TrustLineEntryV1Ext`, `OfferEntryFlags`, `OfferEntry`, `OfferEntryExt`, `DataEntry`, `DataEntryExt`, `ClaimPredicateType`, `ClaimPredicate`, `ClaimantType`, `Claimant`, `ClaimantV0`, `ClaimableBalanceIdType`, `ClaimableBalanceId`, `ClaimableBalanceFlags`, `ClaimableBalanceEntryExtensionV1`, `ClaimableBalanceEntryExtensionV1Ext`, `ClaimableBalanceEntry`, `ClaimableBalanceEntryExt`, `LiquidityPoolConstantProductParameters`, `LiquidityPoolEntry`, `LiquidityPoolEntryBody`, `LiquidityPoolEntryConstantProduct`, `ContractDataDurability`, `ContractDataEntry`, `ContractCodeEntry`, `ExpirationEntry`, `LedgerEntryExtensionV1`, `LedgerEntryExtensionV1Ext`, `LedgerEntry`, `LedgerEntryData`, `LedgerEntryExt`, `LedgerKey`, `LedgerKeyAccount`, `LedgerKeyTrustLine`, `LedgerKeyOffer`, `LedgerKeyData`, `LedgerKeyClaimableBalance`, `LedgerKeyLiquidityPool`, `LedgerKeyContractData`, `LedgerKeyContractCode`, `LedgerKeyConfigSetting`, `LedgerKeyExpiration`, `EnvelopeType`, `UpgradeType`, `StellarValueType`, `LedgerCloseValueSignature`, `StellarValue`, `StellarValueExt`, `LedgerHeaderFlags`, `LedgerHeaderExtensionV1`, `LedgerHeaderExtensionV1Ext`, `LedgerHeader`, `LedgerHeaderExt`, `LedgerUpgradeType`, `ConfigUpgradeSetKey`, `LedgerUpgrade`, `ConfigUpgradeSet`, `BucketEntryType`, `BucketMetadata`, `BucketMetadataExt`, `BucketEntry`, `TxSetComponentType`, `TxSetComponent`, `TxSetComponentTxsMaybeDiscountedFee`, `TransactionPhase`, `TransactionSet`, `TransactionSetV1`, `GeneralizedTransactionSet`, `TransactionResultPair`, `TransactionResultSet`, `TransactionHistoryEntry`, `TransactionHistoryEntryExt`, `TransactionHistoryResultEntry`, `TransactionHistoryResultEntryExt`, `LedgerHeaderHistoryEntry`, `LedgerHeaderHistoryEntryExt`, `LedgerScpMessages`, `ScpHistoryEntryV0`, `ScpHistoryEntry`, `LedgerEntryChangeType`, `LedgerEntryChange`, `LedgerEntryChanges`, `OperationMeta`, `TransactionMetaV1`, `TransactionMetaV2`, `ContractEventType`, `ContractEvent`, `ContractEventBody`, `ContractEventV0`, `DiagnosticEvent`, `SorobanTransactionMeta`, `TransactionMetaV3`, `InvokeHostFunctionSuccessPreImage`, `TransactionMeta`, `TransactionResultMeta`, `UpgradeEntryMeta`, `LedgerCloseMetaV0`, `LedgerCloseMetaV1`, `LedgerCloseMetaV2`, `LedgerCloseMeta`, `ErrorCode`, `SError`, `SendMore`, `SendMoreExtended`, `AuthCert`, `Hello`, `Auth`, `IpAddrType`, `PeerAddress`, `PeerAddressIp`, `MessageType`, `DontHave`, `SurveyMessageCommandType`, `SurveyMessageResponseType`, `SurveyRequestMessage`, `SignedSurveyRequestMessage`, `EncryptedBody`, `SurveyResponseMessage`, `SignedSurveyResponseMessage`, `PeerStats`, `PeerStatList`, `TopologyResponseBodyV0`, `TopologyResponseBodyV1`, `SurveyResponseBody`, `TxAdvertVector`, `FloodAdvert`, `TxDemandVector`, `FloodDemand`, `StellarMessage`, `AuthenticatedMessage`, `AuthenticatedMessageV0`, `LiquidityPoolParameters`, `MuxedAccount`, `MuxedAccountMed25519`, `DecoratedSignature`, `OperationType`, `CreateAccountOp`, `PaymentOp`, `PathPaymentStrictReceiveOp`, `PathPaymentStrictSendOp`, `ManageSellOfferOp`, `ManageBuyOfferOp`, `CreatePassiveSellOfferOp`, `SetOptionsOp`, `ChangeTrustAsset`, `ChangeTrustOp`, `AllowTrustOp`, `ManageDataOp`, `BumpSequenceOp`, `CreateClaimableBalanceOp`, `ClaimClaimableBalanceOp`, `BeginSponsoringFutureReservesOp`, `RevokeSponsorshipType`, `RevokeSponsorshipOp`, `RevokeSponsorshipOpSigner`, `ClawbackOp`, `ClawbackClaimableBalanceOp`, `SetTrustLineFlagsOp`, `LiquidityPoolDepositOp`, `LiquidityPoolWithdrawOp`, `HostFunctionType`, `ContractIdPreimageType`, `ContractIdPreimage`, `ContractIdPreimageFromAddress`, `CreateContractArgs`, `InvokeContractArgs`, `HostFunction`, `SorobanAuthorizedFunctionType`, `SorobanAuthorizedFunction`, `SorobanAuthorizedInvocation`, `SorobanAddressCredentials`, `SorobanCredentialsType`, `SorobanCredentials`, `SorobanAuthorizationEntry`, `InvokeHostFunctionOp`, `BumpFootprintExpirationOp`, `RestoreFootprintOp`, `Operation`, `OperationBody`, `HashIdPreimage`, `HashIdPreimageOperationId`, `HashIdPreimageRevokeId`, `HashIdPreimageContractId`, `HashIdPreimageSorobanAuthorization`, `MemoType`, `Memo`, `TimeBounds`, `LedgerBounds`, `PreconditionsV2`, `PreconditionType`, `Preconditions`, `LedgerFootprint`, `SorobanResources`, `SorobanTransactionData`, `TransactionV0`, `TransactionV0Ext`, `TransactionV0Envelope`, `Transaction`, `TransactionExt`, `TransactionV1Envelope`, `FeeBumpTransaction`, `FeeBumpTransactionInnerTx`, `FeeBumpTransactionExt`, `FeeBumpTransactionEnvelope`, `TransactionEnvelope`, `TransactionSignaturePayload`, `TransactionSignaturePayloadTaggedTransaction`, `ClaimAtomType`, `ClaimOfferAtomV0`, `ClaimOfferAtom`, `ClaimLiquidityAtom`, `ClaimAtom`, `CreateAccountResultCode`, `CreateAccountResult`, `PaymentResultCode`, `PaymentResult`, `PathPaymentStrictReceiveResultCode`, `SimplePaymentResult`, `PathPaymentStrictReceiveResult`, `PathPaymentStrictReceiveResultSuccess`, `PathPaymentStrictSendResultCode`, `PathPaymentStrictSendResult`, `PathPaymentStrictSendResultSuccess`, `ManageSellOfferResultCode`, `ManageOfferEffect`, `ManageOfferSuccessResult`, `ManageOfferSuccessResultOffer`, `ManageSellOfferResult`, `ManageBuyOfferResultCode`, `ManageBuyOfferResult`, `SetOptionsResultCode`, `SetOptionsResult`, `ChangeTrustResultCode`, `ChangeTrustResult`, `AllowTrustResultCode`, `AllowTrustResult`, `AccountMergeResultCode`, `AccountMergeResult`, `InflationResultCode`, `InflationPayout`, `InflationResult`, `ManageDataResultCode`, `ManageDataResult`, `BumpSequenceResultCode`, `BumpSequenceResult`, `CreateClaimableBalanceResultCode`, `CreateClaimableBalanceResult`, `ClaimClaimableBalanceResultCode`, `ClaimClaimableBalanceResult`, `BeginSponsoringFutureReservesResultCode`, `BeginSponsoringFutureReservesResult`, `EndSponsoringFutureReservesResultCode`, `EndSponsoringFutureReservesResult`, `RevokeSponsorshipResultCode`, `RevokeSponsorshipResult`, `ClawbackResultCode`, `ClawbackResult`, `ClawbackClaimableBalanceResultCode`, `ClawbackClaimableBalanceResult`, `SetTrustLineFlagsResultCode`, `SetTrustLineFlagsResult`, `LiquidityPoolDepositResultCode`, `LiquidityPoolDepositResult`, `LiquidityPoolWithdrawResultCode`, `LiquidityPoolWithdrawResult`, `InvokeHostFunctionResultCode`, `InvokeHostFunctionResult`, `BumpFootprintExpirationResultCode`, `BumpFootprintExpirationResult`, `RestoreFootprintResultCode`, `RestoreFootprintResult`, `OperationResultCode`, `OperationResult`, `OperationResultTr`, `TransactionResultCode`, `InnerTransactionResult`, `InnerTransactionResultResult`, `InnerTransactionResultExt`, `InnerTransactionResultPair`, `TransactionResult`, `TransactionResultResult`, `TransactionResultExt`, `Hash`, `Uint256`, `Uint32`, `Int32`, `Uint64`, `Int64`, `TimePoint`, `Duration`, `ExtensionPoint`, `CryptoKeyType`, `PublicKeyType`, `SignerKeyType`, `PublicKey`, `SignerKey`, `SignerKeyEd25519SignedPayload`, `Signature`, `SignatureHint`, `NodeId`, `AccountId`, `Curve25519Secret`, `Curve25519Public`, `HmacSha256Key`, `HmacSha256Mac` + Possible values: `Value`, `ScpBallot`, `ScpStatementType`, `ScpNomination`, `ScpStatement`, `ScpStatementPledges`, `ScpStatementPrepare`, `ScpStatementConfirm`, `ScpStatementExternalize`, `ScpEnvelope`, `ScpQuorumSet`, `ConfigSettingContractExecutionLanesV0`, `ConfigSettingContractComputeV0`, `ConfigSettingContractLedgerCostV0`, `ConfigSettingContractHistoricalDataV0`, `ConfigSettingContractEventsV0`, `ConfigSettingContractBandwidthV0`, `ContractCostType`, `ContractCostParamEntry`, `StateArchivalSettings`, `EvictionIterator`, `ContractCostParams`, `ConfigSettingId`, `ConfigSettingEntry`, `ScEnvMetaKind`, `ScEnvMetaEntry`, `ScMetaV0`, `ScMetaKind`, `ScMetaEntry`, `ScSpecType`, `ScSpecTypeOption`, `ScSpecTypeResult`, `ScSpecTypeVec`, `ScSpecTypeMap`, `ScSpecTypeTuple`, `ScSpecTypeBytesN`, `ScSpecTypeUdt`, `ScSpecTypeDef`, `ScSpecUdtStructFieldV0`, `ScSpecUdtStructV0`, `ScSpecUdtUnionCaseVoidV0`, `ScSpecUdtUnionCaseTupleV0`, `ScSpecUdtUnionCaseV0Kind`, `ScSpecUdtUnionCaseV0`, `ScSpecUdtUnionV0`, `ScSpecUdtEnumCaseV0`, `ScSpecUdtEnumV0`, `ScSpecUdtErrorEnumCaseV0`, `ScSpecUdtErrorEnumV0`, `ScSpecFunctionInputV0`, `ScSpecFunctionV0`, `ScSpecEntryKind`, `ScSpecEntry`, `ScValType`, `ScErrorType`, `ScErrorCode`, `ScError`, `UInt128Parts`, `Int128Parts`, `UInt256Parts`, `Int256Parts`, `ContractExecutableType`, `ContractExecutable`, `ScAddressType`, `ScAddress`, `ScVec`, `ScMap`, `ScBytes`, `ScString`, `ScSymbol`, `ScNonceKey`, `ScContractInstance`, `ScVal`, `ScMapEntry`, `StoredTransactionSet`, `StoredDebugTransactionSet`, `PersistedScpStateV0`, `PersistedScpStateV1`, `PersistedScpState`, `Thresholds`, `String32`, `String64`, `SequenceNumber`, `DataValue`, `PoolId`, `AssetCode4`, `AssetCode12`, `AssetType`, `AssetCode`, `AlphaNum4`, `AlphaNum12`, `Asset`, `Price`, `Liabilities`, `ThresholdIndexes`, `LedgerEntryType`, `Signer`, `AccountFlags`, `SponsorshipDescriptor`, `AccountEntryExtensionV3`, `AccountEntryExtensionV2`, `AccountEntryExtensionV2Ext`, `AccountEntryExtensionV1`, `AccountEntryExtensionV1Ext`, `AccountEntry`, `AccountEntryExt`, `TrustLineFlags`, `LiquidityPoolType`, `TrustLineAsset`, `TrustLineEntryExtensionV2`, `TrustLineEntryExtensionV2Ext`, `TrustLineEntry`, `TrustLineEntryExt`, `TrustLineEntryV1`, `TrustLineEntryV1Ext`, `OfferEntryFlags`, `OfferEntry`, `OfferEntryExt`, `DataEntry`, `DataEntryExt`, `ClaimPredicateType`, `ClaimPredicate`, `ClaimantType`, `Claimant`, `ClaimantV0`, `ClaimableBalanceIdType`, `ClaimableBalanceId`, `ClaimableBalanceFlags`, `ClaimableBalanceEntryExtensionV1`, `ClaimableBalanceEntryExtensionV1Ext`, `ClaimableBalanceEntry`, `ClaimableBalanceEntryExt`, `LiquidityPoolConstantProductParameters`, `LiquidityPoolEntry`, `LiquidityPoolEntryBody`, `LiquidityPoolEntryConstantProduct`, `ContractDataDurability`, `ContractDataEntry`, `ContractCodeEntry`, `TtlEntry`, `LedgerEntryExtensionV1`, `LedgerEntryExtensionV1Ext`, `LedgerEntry`, `LedgerEntryData`, `LedgerEntryExt`, `LedgerKey`, `LedgerKeyAccount`, `LedgerKeyTrustLine`, `LedgerKeyOffer`, `LedgerKeyData`, `LedgerKeyClaimableBalance`, `LedgerKeyLiquidityPool`, `LedgerKeyContractData`, `LedgerKeyContractCode`, `LedgerKeyConfigSetting`, `LedgerKeyTtl`, `EnvelopeType`, `UpgradeType`, `StellarValueType`, `LedgerCloseValueSignature`, `StellarValue`, `StellarValueExt`, `LedgerHeaderFlags`, `LedgerHeaderExtensionV1`, `LedgerHeaderExtensionV1Ext`, `LedgerHeader`, `LedgerHeaderExt`, `LedgerUpgradeType`, `ConfigUpgradeSetKey`, `LedgerUpgrade`, `ConfigUpgradeSet`, `BucketEntryType`, `BucketMetadata`, `BucketMetadataExt`, `BucketEntry`, `TxSetComponentType`, `TxSetComponent`, `TxSetComponentTxsMaybeDiscountedFee`, `TransactionPhase`, `TransactionSet`, `TransactionSetV1`, `GeneralizedTransactionSet`, `TransactionResultPair`, `TransactionResultSet`, `TransactionHistoryEntry`, `TransactionHistoryEntryExt`, `TransactionHistoryResultEntry`, `TransactionHistoryResultEntryExt`, `LedgerHeaderHistoryEntry`, `LedgerHeaderHistoryEntryExt`, `LedgerScpMessages`, `ScpHistoryEntryV0`, `ScpHistoryEntry`, `LedgerEntryChangeType`, `LedgerEntryChange`, `LedgerEntryChanges`, `OperationMeta`, `TransactionMetaV1`, `TransactionMetaV2`, `ContractEventType`, `ContractEvent`, `ContractEventBody`, `ContractEventV0`, `DiagnosticEvent`, `SorobanTransactionMeta`, `TransactionMetaV3`, `InvokeHostFunctionSuccessPreImage`, `TransactionMeta`, `TransactionResultMeta`, `UpgradeEntryMeta`, `LedgerCloseMetaV0`, `LedgerCloseMetaV1`, `LedgerCloseMeta`, `ErrorCode`, `SError`, `SendMore`, `SendMoreExtended`, `AuthCert`, `Hello`, `Auth`, `IpAddrType`, `PeerAddress`, `PeerAddressIp`, `MessageType`, `DontHave`, `SurveyMessageCommandType`, `SurveyMessageResponseType`, `SurveyRequestMessage`, `SignedSurveyRequestMessage`, `EncryptedBody`, `SurveyResponseMessage`, `SignedSurveyResponseMessage`, `PeerStats`, `PeerStatList`, `TopologyResponseBodyV0`, `TopologyResponseBodyV1`, `SurveyResponseBody`, `TxAdvertVector`, `FloodAdvert`, `TxDemandVector`, `FloodDemand`, `StellarMessage`, `AuthenticatedMessage`, `AuthenticatedMessageV0`, `LiquidityPoolParameters`, `MuxedAccount`, `MuxedAccountMed25519`, `DecoratedSignature`, `OperationType`, `CreateAccountOp`, `PaymentOp`, `PathPaymentStrictReceiveOp`, `PathPaymentStrictSendOp`, `ManageSellOfferOp`, `ManageBuyOfferOp`, `CreatePassiveSellOfferOp`, `SetOptionsOp`, `ChangeTrustAsset`, `ChangeTrustOp`, `AllowTrustOp`, `ManageDataOp`, `BumpSequenceOp`, `CreateClaimableBalanceOp`, `ClaimClaimableBalanceOp`, `BeginSponsoringFutureReservesOp`, `RevokeSponsorshipType`, `RevokeSponsorshipOp`, `RevokeSponsorshipOpSigner`, `ClawbackOp`, `ClawbackClaimableBalanceOp`, `SetTrustLineFlagsOp`, `LiquidityPoolDepositOp`, `LiquidityPoolWithdrawOp`, `HostFunctionType`, `ContractIdPreimageType`, `ContractIdPreimage`, `ContractIdPreimageFromAddress`, `CreateContractArgs`, `InvokeContractArgs`, `HostFunction`, `SorobanAuthorizedFunctionType`, `SorobanAuthorizedFunction`, `SorobanAuthorizedInvocation`, `SorobanAddressCredentials`, `SorobanCredentialsType`, `SorobanCredentials`, `SorobanAuthorizationEntry`, `InvokeHostFunctionOp`, `ExtendFootprintTtlOp`, `RestoreFootprintOp`, `Operation`, `OperationBody`, `HashIdPreimage`, `HashIdPreimageOperationId`, `HashIdPreimageRevokeId`, `HashIdPreimageContractId`, `HashIdPreimageSorobanAuthorization`, `MemoType`, `Memo`, `TimeBounds`, `LedgerBounds`, `PreconditionsV2`, `PreconditionType`, `Preconditions`, `LedgerFootprint`, `SorobanResources`, `SorobanTransactionData`, `TransactionV0`, `TransactionV0Ext`, `TransactionV0Envelope`, `Transaction`, `TransactionExt`, `TransactionV1Envelope`, `FeeBumpTransaction`, `FeeBumpTransactionInnerTx`, `FeeBumpTransactionExt`, `FeeBumpTransactionEnvelope`, `TransactionEnvelope`, `TransactionSignaturePayload`, `TransactionSignaturePayloadTaggedTransaction`, `ClaimAtomType`, `ClaimOfferAtomV0`, `ClaimOfferAtom`, `ClaimLiquidityAtom`, `ClaimAtom`, `CreateAccountResultCode`, `CreateAccountResult`, `PaymentResultCode`, `PaymentResult`, `PathPaymentStrictReceiveResultCode`, `SimplePaymentResult`, `PathPaymentStrictReceiveResult`, `PathPaymentStrictReceiveResultSuccess`, `PathPaymentStrictSendResultCode`, `PathPaymentStrictSendResult`, `PathPaymentStrictSendResultSuccess`, `ManageSellOfferResultCode`, `ManageOfferEffect`, `ManageOfferSuccessResult`, `ManageOfferSuccessResultOffer`, `ManageSellOfferResult`, `ManageBuyOfferResultCode`, `ManageBuyOfferResult`, `SetOptionsResultCode`, `SetOptionsResult`, `ChangeTrustResultCode`, `ChangeTrustResult`, `AllowTrustResultCode`, `AllowTrustResult`, `AccountMergeResultCode`, `AccountMergeResult`, `InflationResultCode`, `InflationPayout`, `InflationResult`, `ManageDataResultCode`, `ManageDataResult`, `BumpSequenceResultCode`, `BumpSequenceResult`, `CreateClaimableBalanceResultCode`, `CreateClaimableBalanceResult`, `ClaimClaimableBalanceResultCode`, `ClaimClaimableBalanceResult`, `BeginSponsoringFutureReservesResultCode`, `BeginSponsoringFutureReservesResult`, `EndSponsoringFutureReservesResultCode`, `EndSponsoringFutureReservesResult`, `RevokeSponsorshipResultCode`, `RevokeSponsorshipResult`, `ClawbackResultCode`, `ClawbackResult`, `ClawbackClaimableBalanceResultCode`, `ClawbackClaimableBalanceResult`, `SetTrustLineFlagsResultCode`, `SetTrustLineFlagsResult`, `LiquidityPoolDepositResultCode`, `LiquidityPoolDepositResult`, `LiquidityPoolWithdrawResultCode`, `LiquidityPoolWithdrawResult`, `InvokeHostFunctionResultCode`, `InvokeHostFunctionResult`, `ExtendFootprintTtlResultCode`, `ExtendFootprintTtlResult`, `RestoreFootprintResultCode`, `RestoreFootprintResult`, `OperationResultCode`, `OperationResult`, `OperationResultTr`, `TransactionResultCode`, `InnerTransactionResult`, `InnerTransactionResultResult`, `InnerTransactionResultExt`, `InnerTransactionResultPair`, `TransactionResult`, `TransactionResultResult`, `TransactionResultExt`, `Hash`, `Uint256`, `Uint32`, `Int32`, `Uint64`, `Int64`, `TimePoint`, `Duration`, `ExtensionPoint`, `CryptoKeyType`, `PublicKeyType`, `SignerKeyType`, `PublicKey`, `SignerKey`, `SignerKeyEd25519SignedPayload`, `Signature`, `SignatureHint`, `NodeId`, `AccountId`, `Curve25519Secret`, `Curve25519Public`, `HmacSha256Key`, `HmacSha256Mac` * `--xdr ` — XDR (base64 encoded) to decode * `--output ` — Type of output diff --git a/go.mod b/go.mod index 62feb34a4..5e29662fe 100644 --- a/go.mod +++ b/go.mod @@ -5,82 +5,93 @@ go 1.20 require ( github.com/Masterminds/squirrel v1.5.4 github.com/cenkalti/backoff/v4 v4.2.1 - github.com/creachadair/jrpc2 v1.1.0 + github.com/creachadair/jrpc2 v1.1.1 github.com/go-chi/chi v4.1.2+incompatible - github.com/go-git/go-git/v5 v5.4.2 + github.com/go-git/go-git/v5 v5.9.0 github.com/mattn/go-sqlite3 v1.14.17 github.com/pelletier/go-toml v1.9.5 - github.com/prometheus/client_golang v1.16.0 - github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 + github.com/prometheus/client_golang v1.17.0 + github.com/rs/cors v1.10.1 github.com/rubenv/sql-migrate v1.5.2 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/stellar/go v0.0.0-20231016174715-c7d3a47ee7a2 github.com/stretchr/testify v1.8.4 - golang.org/x/mod v0.12.0 + golang.org/x/mod v0.13.0 gotest.tools/v3 v3.5.0 ) require ( - github.com/BurntSushi/toml v0.3.1 // indirect - github.com/Microsoft/go-winio v0.4.16 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect - github.com/acomagu/bufpipe v1.0.3 // indirect - github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/aws/aws-sdk-go v1.44.326 // indirect + dario.cat/mergo v1.0.0 // indirect + github.com/cloudflare/circl v1.3.5 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/sagikazarmark/locafero v0.3.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/skeema/knownhosts v1.2.1 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/xdrpp/goxdr v0.1.1 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/tools v0.14.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect + github.com/acomagu/bufpipe v1.0.4 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/aws/aws-sdk-go v1.45.27 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/creachadair/mds v0.0.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emirpasic/gods v1.12.0 // indirect + github.com/creachadair/mds v0.2.3 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emirpasic/gods v1.18.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-errors/errors v0.0.0-20150906023321-a41850380601 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.3.1 // indirect + github.com/go-errors/errors v1.5.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/jmoiron/sqlx v1.2.0 // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect + github.com/jmoiron/sqlx v1.3.5 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/lib/pq v1.10.7 // indirect - github.com/magiconair/properties v1.8.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.1.2 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/segmentio/go-loggly v0.5.1-0.20171222203950-eb91657e62b2 // indirect - github.com/sergi/go-diff v1.1.0 // indirect - github.com/spf13/afero v1.1.2 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/jwalterweatherman v1.0.0 // indirect - github.com/spf13/viper v1.3.2 // indirect + github.com/sergi/go-diff v1.3.1 // indirect + github.com/spf13/afero v1.10.0 // indirect + github.com/spf13/cast v1.5.1 // indirect + github.com/spf13/viper v1.17.0 // indirect github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/xanzy/ssh-agent v0.3.0 // indirect - github.com/xdrpp/goxdr v0.1.1 // indirect - golang.org/x/crypto v0.12.0 // indirect - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect - golang.org/x/net v0.14.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/text v0.12.0 // indirect + github.com/stretchr/objx v0.5.1 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/tylerb/graceful.v1 v1.2.13 // indirect + gopkg.in/tylerb/graceful.v1 v1.2.15 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 19be596c9..f0d20235f 100644 --- a/go.sum +++ b/go.sum @@ -1,115 +1,244 @@ -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE= +github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f h1:zvClvFQwU++UpIUBGC8YmDlfhUrweEy1R1Fj1gu5iIM= +github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.44.326 h1:/6xD/9mKZ2RMTDfbhh9qCxw+CaTbJRvfHJ/NHPFbI38= -github.com/aws/aws-sdk-go v1.44.326/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.45.27 h1:b+zOTPkAG4i2RvqPdHxkJZafmhhVaVHBp4r41Tu4I6U= +github.com/aws/aws-sdk-go v1.45.27/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.5 h1:g+wWynZqVALYAlpSQFAa7TscDnUK8mKYtrxMpw6AUKo= +github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creachadair/jrpc2 v1.1.0 h1:SgpJf0v1rVCZx68+4APv6dgsTFsIHlpgFD1NlQAWA0A= -github.com/creachadair/jrpc2 v1.1.0/go.mod h1:5jN7MKwsm8qvgfTsTzLX3JIfidsAkZ1c8DZSQmp+g38= -github.com/creachadair/mds v0.0.1 h1:2nX6Sww4dXpScx3b6aYjH1n7iuEH715+jj+cKkKw9BY= -github.com/creachadair/mds v0.0.1/go.mod h1:caBACU+n1Q/rZ252FTzfnG0/H+ZUi+UnIQtEOraMv/g= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creachadair/jrpc2 v1.1.1 h1:xa7p3C5eSvwn/dFwCCmksp+RyQ/ytFY0NYzY7npsoI0= +github.com/creachadair/jrpc2 v1.1.1/go.mod h1:KajsO5dx7yfcwmuRJb5SHXsCVTzBoq7EsPzu5wxnsc0= +github.com/creachadair/mds v0.2.3 h1:Svuw/AXrUUMxGHdRyuDsWJ36oFJRprqP8+iI86XzZjM= +github.com/creachadair/mds v0.2.3/go.mod h1:PmXHgspUECelJVsAgDxWvjblna5BGjPxdEpr7SIEvNs= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/monotime v0.0.0-20161010190848-47d58efa6955 h1:gmtGRvSexPU4B1T/yYo0sLOKzER1YT+b4kPxPpm0Ty4= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/gavv/monotime v0.0.0-20161010190848-47d58efa6955/go.mod h1:vmp8DIyckQMXOPl0AQVHt+7n5h7Gb7hS6CUydiV8QeA= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-errors/errors v0.0.0-20150906023321-a41850380601 h1:jxTbmDuqQUTI6MscgbqB39vtxGfr2fi61nYIcFQUnlE= -github.com/go-errors/errors v0.0.0-20150906023321-a41850380601/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= +github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY= +github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= +github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= github.com/gobuffalo/packd v1.0.2 h1:Yg523YqnOxGIWCp69W12yYBKsoChwI7mtu6ceM9Bwfw= +github.com/gobuffalo/packd v1.0.2/go.mod h1:sUc61tDqGMXON80zpKGp92lDb86Km28jfvX7IAyxFT8= github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg= github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= +github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 h1:oERTZ1buOUYlpmKaqlO5fYmz8cZ1rYu5DieJzF4ZVmU= +github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= +github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jarcoal/httpmock v0.0.0-20161210151336-4442edb3db31 h1:Aw95BEvxJ3K6o9GGv5ppCd1P8hkeIeEJ30FO+OhOJpM= +github.com/jarcoal/httpmock v0.0.0-20161210151336-4442edb3db31/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= -github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -118,190 +247,509 @@ github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739 h1:ykXz+pRRTibcSjG1yRhpdSHInF8yZY/mfn+Rz2Nd1rE= +github.com/manucorporat/sse v0.0.0-20160126180136-ee05b128a739/go.mod h1:zUx1mhth20V3VKgL5jbd1BSQcW4Fy6Qs4PZvQwRFwzM= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= +github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= +github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moul/http2curl v0.0.0-20161031194548-4e24498b31db h1:eZgFHVkk9uOTaOQLC6tgjkzdp7Ays8eEVecBcfHZlJQ= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/moul/http2curl v0.0.0-20161031194548-4e24498b31db/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00 h1:8DPul/X0IT/1TNMIxoKLwdemEOBBHDC/K4EB16Cw5WE= -github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 h1:3hxavr+IHMsQBrYUPQM5v0CgENFktkkbg1sfpgM3h20= -github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= +github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/segmentio/go-loggly v0.5.1-0.20171222203950-eb91657e62b2 h1:S4OC0+OBKz6mJnzuHioeEat74PuQ4Sgvbf8eus695sc= github.com/segmentio/go-loggly v0.5.1-0.20171222203950-eb91657e62b2/go.mod h1:8zLRYR5npGjaOXgPSKat5+oOh+UHd8OdbS18iqX9F6Y= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= +github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= github.com/stellar/go v0.0.0-20231016174715-c7d3a47ee7a2 h1:IOOHd1yrwmK0wiAuNDmoHUPTucO0oGkkKa3CE1pgn2E= github.com/stellar/go v0.0.0-20231016174715-c7d3a47ee7a2/go.mod h1:g78pyZyDFnKMJUaBIXxH7xyQ7PdDrvrJTFCxdGMMb3c= github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206 h1:UFuvvpbWL8+jqO1QmKYWSVhiMp4MRiIFd8/zQlUINH0= github.com/stellar/go-xdr v0.0.0-20230919160922-6c7b68458206/go.mod h1:yoxyU/M8nl9LKeWIoBrbDPQ7Cy+4jxRcWcOayZ4BMps= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= +github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xdrpp/goxdr v0.1.1 h1:E1B2c6E8eYhOVyd7yEpOyopzTPirUeF6mVOfXfGyJyc= github.com/xdrpp/goxdr v0.1.1/go.mod h1:dXo1scL/l6s7iME1gxHWo2XCppbHEKZS7m/KyYWkNzA= github.com/xeipuuv/gojsonpointer v0.0.0-20151027082146-e0fe6f683076 h1:KM4T3G70MiR+JtqplcYkNVoNz7pDwYaBxWBXQK804So= +github.com/xeipuuv/gojsonpointer v0.0.0-20151027082146-e0fe6f683076/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c h1:XZWnr3bsDQWAZg4Ne+cPoXRPILrNlPNQfxBuwLl43is= +github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20161231055540-f06f290571ce h1:cVSRGH8cOveJNwFEEZLXtB+XMnRqKLjUP6V/ZFYQCXI= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xeipuuv/gojsonschema v0.0.0-20161231055540-f06f290571ce/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/yalp/jsonpath v0.0.0-20150812003900-31a79c7593bb h1:06WAhQa+mYv7BiOk13B/ywyTlkoE/S7uu6TBKU6FHnE= +github.com/yalp/jsonpath v0.0.0-20150812003900-31a79c7593bb/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d h1:yJIizrfO599ot2kQ6Af1enICnwBD3XoxgX3MrMwot2M= +github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20150405163532-d1c525dea8ce h1:888GrqRxabUce7lj4OaoShPxodm3kXOMpSa85wdYzfY= +github.com/yudai/golcs v0.0.0-20150405163532-d1c525dea8ce/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0 h1:r5ptJ1tBxVAeqw4CrYWhXIMr0SybY3CDHuIbCg5CFVw= +gopkg.in/gavv/httpexpect.v1 v1.0.0-20170111145843-40724cf1e4a0/go.mod h1:WtiW9ZA1LdaWqtQRo1VbIL/v4XZ8NDta+O/kSpGgVek= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tylerb/graceful.v1 v1.2.13 h1:UWJlWJHZepntB0PJ9RTgW3X+zVLjfmWbx/V1X/V/XoA= -gopkg.in/tylerb/graceful.v1 v1.2.13/go.mod h1:yBhekWvR20ACXVObSSdD3u6S9DeSylanL2PAbAC/uJ8= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/tylerb/graceful.v1 v1.2.15 h1:1JmOyhKqAyX3BgTXMI84LwT6FOJ4tP2N9e2kwTCM0nQ= +gopkg.in/tylerb/graceful.v1 v1.2.15/go.mod h1:yBhekWvR20ACXVObSSdD3u6S9DeSylanL2PAbAC/uJ8= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From d9f8affddd233c058c4e0a93ee85c53e5c9b80a5 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 23 Oct 2023 17:31:06 +0200 Subject: [PATCH 13/14] Fix test --- cmd/soroban-rpc/internal/test/simulate_transaction_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index 7a04c4d07..04ac395ea 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -1121,7 +1121,7 @@ func TestSimulateSystemEvent(t *testing.T) { err = xdr.SafeUnmarshalBase64(response.TransactionData, &transactionData) require.NoError(t, err) - assert.InDelta(t, 7260, uint32(transactionData.Resources.ReadBytes), 200) + assert.InDelta(t, 7464, uint32(transactionData.Resources.ReadBytes), 200) assert.InDelta(t, 98339, int64(transactionData.ResourceFee), 2000) assert.InDelta(t, 104, uint32(transactionData.Resources.WriteBytes), 15) require.GreaterOrEqual(t, len(response.Events), 3) From db1723f075c680c0c30863f7d838ca8b018c96ed Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 23 Oct 2023 18:19:30 +0200 Subject: [PATCH 14/14] Fix yet another test --- .../internal/test/transaction_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/soroban-rpc/internal/test/transaction_test.go b/cmd/soroban-rpc/internal/test/transaction_test.go index b53c8f25b..ff8473420 100644 --- a/cmd/soroban-rpc/internal/test/transaction_test.go +++ b/cmd/soroban-rpc/internal/test/transaction_test.go @@ -161,19 +161,19 @@ func TestSendTransactionFailedInLedger(t *testing.T) { address := kp.Address() account := txnbuild.NewSimpleAccount(address, 0) - op := createInstallContractCodeOperation(account.AccountID, getHelloWorldContract(t)) - // without the presources the tx will fail - op.Ext = xdr.TransactionExt{ - V: 1, - SorobanData: &xdr.SorobanTransactionData{}, - } tx, err := txnbuild.NewTransaction(txnbuild.TransactionParams{ SourceAccount: &account, IncrementSequenceNum: true, Operations: []txnbuild.Operation{ - op, + &txnbuild.Payment{ + // Destination doesn't exist, making the transaction fail + Destination: "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ", + Amount: "100000.0000000", + Asset: txnbuild.NativeAsset{}, + SourceAccount: "", + }, }, - BaseFee: txnbuild.MinBaseFee * 1000, + BaseFee: txnbuild.MinBaseFee, Preconditions: txnbuild.Preconditions{ TimeBounds: txnbuild.NewInfiniteTimeout(), },