From ec6efbb8d298b8c6e09552f1cca3e57d75aeac79 Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Mon, 23 Jan 2023 13:18:47 +0000 Subject: [PATCH 1/2] Remove deprecated 'getContractData' rpc method --- cmd/soroban-cli/src/rpc/mod.rs | 7 - cmd/soroban-cli/src/serve.rs | 4 - cmd/soroban-rpc/internal/jsonrpc.go | 1 - .../internal/methods/get_contract_data.go | 119 ------------- .../internal/test/get_contract_data_test.go | 166 ------------------ 5 files changed, 297 deletions(-) delete mode 100644 cmd/soroban-rpc/internal/methods/get_contract_data.go delete mode 100644 cmd/soroban-rpc/internal/test/get_contract_data_test.go diff --git a/cmd/soroban-cli/src/rpc/mod.rs b/cmd/soroban-cli/src/rpc/mod.rs index b63a0baa21..84dc46e3ed 100644 --- a/cmd/soroban-cli/src/rpc/mod.rs +++ b/cmd/soroban-cli/src/rpc/mod.rs @@ -71,13 +71,6 @@ pub struct GetTransactionStatusResponse { pub results: Vec, } -// TODO: this should also be used by serve -#[derive(serde::Deserialize, serde::Serialize, Debug)] -pub struct GetContractDataResponse { - pub xdr: String, - // TODO: add lastModifiedLedgerSeq and latestLedger -} - // TODO: this should also be used by serve #[derive(serde::Deserialize, serde::Serialize, Debug)] pub struct GetLedgerEntryResponse { diff --git a/cmd/soroban-cli/src/serve.rs b/cmd/soroban-cli/src/serve.rs index 4fe8c0f0b0..b80b38b655 100644 --- a/cmd/soroban-cli/src/serve.rs +++ b/cmd/soroban-cli/src/serve.rs @@ -68,7 +68,6 @@ pub enum Error { #[serde(untagged)] enum Requests { NoArg(), - GetContractData((String, String)), StringArg(Box<[String]>), } @@ -141,9 +140,6 @@ async fn handler( let result = match (request.method.as_str(), request.params) { ("getAccount", Some(Requests::StringArg(b))) => get_account(b), ("getHealth", Some(Requests::NoArg()) | None) => Ok(get_health()), - ("getContractData", Some(Requests::GetContractData((contract_id, key)))) => { - get_contract_data(&contract_id, key, &ledger_file) - } ("getLedgerEntry", Some(Requests::StringArg(key))) => get_ledger_entry(key, &ledger_file), ("getTransactionStatus", Some(Requests::StringArg(b))) => { get_transaction_status(&transaction_status_map, b).await diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index 5bc4f70909..c33becb107 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -53,7 +53,6 @@ func NewJSONRPCHandler(params HandlerParams) (Handler, error) { "getTransactionStatus": methods.NewGetTransactionStatusHandler(params.TransactionProxy), "sendTransaction": methods.NewSendTransactionHandler(params.TransactionProxy), "simulateTransaction": methods.NewSimulateTransactionHandler(params.Logger, params.CoreClient), - "getContractData": methods.NewGetContractDataHandler(params.Logger, params.CoreClient), }, nil) corsMiddleware := cors.New(cors.Options{ AllowedOrigins: []string{"*"}, diff --git a/cmd/soroban-rpc/internal/methods/get_contract_data.go b/cmd/soroban-rpc/internal/methods/get_contract_data.go deleted file mode 100644 index b74eb0277f..0000000000 --- a/cmd/soroban-rpc/internal/methods/get_contract_data.go +++ /dev/null @@ -1,119 +0,0 @@ -package methods - -import ( - "context" - "encoding/hex" - - "github.com/creachadair/jrpc2" - "github.com/creachadair/jrpc2/code" - "github.com/creachadair/jrpc2/handler" - - "github.com/stellar/go/clients/stellarcore" - proto "github.com/stellar/go/protocols/stellarcore" - "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" -) - -type GetContractDataRequest struct { - ContractID string `json:"contractId"` - Key string `json:"key"` -} - -type GetContractDataResponse struct { - XDR string `json:"xdr"` - LastModifiedLedger int64 `json:"lastModifiedLedgerSeq,string"` - LatestLedger int64 `json:"latestLedger,string"` -} - -// NewGetContractDataHandler returns a json rpc handler to retrieve a contract data ledger entry from stellar cre -func NewGetContractDataHandler(logger *log.Entry, coreClient *stellarcore.Client) jrpc2.Handler { - return handler.New(func(ctx context.Context, request GetContractDataRequest) (GetContractDataResponse, error) { - var scVal xdr.ScVal - if err := xdr.SafeUnmarshalBase64(request.Key, &scVal); err != nil { - logger.WithError(err).WithField("request", request). - Info("could not unmarshal scVal from getContractData request") - return GetContractDataResponse{}, &jrpc2.Error{ - Code: code.InvalidParams, - Message: "cannot unmarshal key value", - } - } - contractIDBytes, err := hex.DecodeString(request.ContractID) - if err != nil { - logger.WithError(err).WithField("request", request). - Info("could not unmarshal contract id from getContractData request") - return GetContractDataResponse{}, &jrpc2.Error{ - Code: code.InvalidParams, - Message: "cannot unmarshal contract id", - } - } - if len(contractIDBytes) != 32 { - return GetContractDataResponse{}, &jrpc2.Error{ - Code: code.InvalidParams, - Message: "contract id is not 32 bytes", - } - } - var contractID xdr.Hash - copy(contractID[:], contractIDBytes) - lk := xdr.LedgerKey{ - Type: xdr.LedgerEntryTypeContractData, - ContractData: &xdr.LedgerKeyContractData{ - ContractId: contractID, - Key: scVal, - }, - } - - coreResponse, err := coreClient.GetLedgerEntry(ctx, lk) - if err != nil { - logger.WithError(err).WithField("request", request). - Info("could not submit getLedgerEntry request to core") - return GetContractDataResponse{}, &jrpc2.Error{ - Code: code.InternalError, - Message: "could not submit request to core", - } - } - - if coreResponse.State == proto.DeadState { - return GetContractDataResponse{}, &jrpc2.Error{ - Code: code.InvalidRequest, - Message: "not found", - } - } - - var ledgerEntry xdr.LedgerEntry - if err = xdr.SafeUnmarshalBase64(coreResponse.Entry, &ledgerEntry); err != nil { - logger.WithError(err).WithField("request", request). - WithField("response", coreResponse). - Info("could not parse ledger entry") - return GetContractDataResponse{}, &jrpc2.Error{ - Code: code.InternalError, - Message: "could not parse core response", - } - } - - contractData, ok := ledgerEntry.Data.GetContractData() - if !ok { - logger.WithError(err).WithField("request", request). - WithField("response", coreResponse). - Info("ledger entry does not contain contract data") - return GetContractDataResponse{}, &jrpc2.Error{ - Code: code.InvalidRequest, - Message: "ledger entry does not contain contract data", - } - } - response := GetContractDataResponse{ - LastModifiedLedger: int64(ledgerEntry.LastModifiedLedgerSeq), - LatestLedger: coreResponse.Ledger, - } - if response.XDR, err = xdr.MarshalBase64(contractData.Val); err != nil { - logger.WithError(err).WithField("request", request). - WithField("response", coreResponse). - Info("could not serialize contract data scval") - return GetContractDataResponse{}, &jrpc2.Error{ - Code: code.InternalError, - Message: "could not serialize contract data scval", - } - } - - return response, nil - }) -} diff --git a/cmd/soroban-rpc/internal/test/get_contract_data_test.go b/cmd/soroban-rpc/internal/test/get_contract_data_test.go deleted file mode 100644 index a8ec7718b1..0000000000 --- a/cmd/soroban-rpc/internal/test/get_contract_data_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package test - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "net/http" - "testing" - "time" - - "github.com/creachadair/jrpc2" - "github.com/creachadair/jrpc2/code" - "github.com/creachadair/jrpc2/jhttp" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/stellar/go/keypair" - "github.com/stellar/go/txnbuild" - "github.com/stellar/go/xdr" - "github.com/stellar/soroban-tools/cmd/soroban-rpc/internal/methods" -) - -func TestGetContractDataNotFound(t *testing.T) { - test := NewTest(t) - - ch := jhttp.NewChannel(test.server.URL, nil) - client := jrpc2.NewClient(ch, nil) - - sourceAccount := keypair.Root(StandaloneNetworkPassphrase).Address() - keyB64, err := xdr.MarshalBase64(getContractCodeLedgerKey()) - require.NoError(t, err) - contractID := getContractID(t, sourceAccount, testSalt, StandaloneNetworkPassphrase) - request := methods.GetContractDataRequest{ - ContractID: hex.EncodeToString(contractID[:]), - Key: keyB64, - } - - var result methods.GetContractDataResponse - jsonRPCErr := client.CallResult(context.Background(), "getContractData", request, &result).(*jrpc2.Error) - assert.Equal(t, "not found", jsonRPCErr.Message) - assert.Equal(t, code.InvalidRequest, jsonRPCErr.Code) -} - -func TestGetContractDataInvalidParams(t *testing.T) { - test := NewTest(t) - - ch := jhttp.NewChannel(test.server.URL, nil) - client := jrpc2.NewClient(ch, nil) - - keyB64, err := xdr.MarshalBase64(getContractCodeLedgerKey()) - require.NoError(t, err) - request := methods.GetContractDataRequest{ - ContractID: "<>@@#$", - Key: keyB64, - } - - var result methods.GetContractDataResponse - jsonRPCErr := client.CallResult(context.Background(), "getContractData", request, &result).(*jrpc2.Error) - assert.Equal(t, "cannot unmarshal contract id", jsonRPCErr.Message) - assert.Equal(t, code.InvalidParams, jsonRPCErr.Code) - - request.ContractID = "11" - jsonRPCErr = client.CallResult(context.Background(), "getContractData", request, &result).(*jrpc2.Error) - assert.Equal(t, "contract id is not 32 bytes", jsonRPCErr.Message) - assert.Equal(t, code.InvalidParams, jsonRPCErr.Code) - - contractID := getContractID(t, keypair.Root(StandaloneNetworkPassphrase).Address(), testSalt, StandaloneNetworkPassphrase) - request.ContractID = hex.EncodeToString(contractID[:]) - request.Key = "@#$!@#!@#" - jsonRPCErr = client.CallResult(context.Background(), "getContractData", request, &result).(*jrpc2.Error) - assert.Equal(t, "cannot unmarshal key value", jsonRPCErr.Message) - assert.Equal(t, code.InvalidParams, jsonRPCErr.Code) -} - -func TestGetContractDataDeadlineError(t *testing.T) { - test := NewTest(t) - test.coreClient.HTTP = &http.Client{ - Timeout: time.Microsecond, - } - - ch := jhttp.NewChannel(test.server.URL, nil) - client := jrpc2.NewClient(ch, nil) - - sourceAccount := keypair.Root(StandaloneNetworkPassphrase).Address() - keyB64, err := xdr.MarshalBase64(getContractCodeLedgerKey()) - require.NoError(t, err) - contractID := getContractID(t, sourceAccount, testSalt, StandaloneNetworkPassphrase) - request := methods.GetContractDataRequest{ - ContractID: hex.EncodeToString(contractID[:]), - Key: keyB64, - } - - var result methods.GetContractDataResponse - jsonRPCErr := client.CallResult(context.Background(), "getContractData", request, &result).(*jrpc2.Error) - assert.Equal(t, "could not submit request to core", jsonRPCErr.Message) - assert.Equal(t, code.InternalError, jsonRPCErr.Code) -} - -func TestGetContractDataSucceeds(t *testing.T) { - test := NewTest(t) - - ch := jhttp.NewChannel(test.server.URL, nil) - client := jrpc2.NewClient(ch, nil) - - kp := keypair.Root(StandaloneNetworkPassphrase) - account := txnbuild.NewSimpleAccount(kp.Address(), 0) - - // Install and create the contract first - for _, op := range []txnbuild.Operation{ - createInstallContractCodeOperation(t, account.AccountID, testContract, true), - createCreateContractOperation(t, account.AccountID, testContract, StandaloneNetworkPassphrase, true), - } { - assertSendTransaction(t, client, kp, txnbuild.TransactionParams{ - SourceAccount: &account, - IncrementSequenceNum: true, - Operations: []txnbuild.Operation{op}, - BaseFee: txnbuild.MinBaseFee, - Preconditions: txnbuild.Preconditions{ - TimeBounds: txnbuild.NewInfiniteTimeout(), - }, - }) - } - - keyB64, err := xdr.MarshalBase64(getContractCodeLedgerKey()) - require.NoError(t, err) - contractID := getContractID(t, kp.Address(), testSalt, StandaloneNetworkPassphrase) - request := methods.GetContractDataRequest{ - ContractID: hex.EncodeToString(contractID[:]), - Key: keyB64, - } - - var result methods.GetContractDataResponse - err = client.CallResult(context.Background(), "getContractData", request, &result) - assert.NoError(t, err) - assert.Greater(t, result.LatestLedger, int64(0)) - assert.GreaterOrEqual(t, result.LatestLedger, result.LastModifiedLedger) - var scVal xdr.ScVal - assert.NoError(t, xdr.SafeUnmarshalBase64(result.XDR, &scVal)) - - installContractCodeArgs, err := xdr.InstallContractCodeArgs{Code: testContract}.MarshalBinary() - assert.NoError(t, err) - contractHash := sha256.Sum256(installContractCodeArgs) - assert.Equal(t, xdr.Hash(contractHash), scVal.MustObj().MustContractCode().MustWasmId()) -} - -func assertSendTransaction(t *testing.T, client *jrpc2.Client, kp *keypair.Full, txnParams txnbuild.TransactionParams) { - tx, err := txnbuild.NewTransaction(txnParams) - assert.NoError(t, err) - tx, err = tx.Sign(StandaloneNetworkPassphrase, kp) - assert.NoError(t, err) - b64, err := tx.Base64() - assert.NoError(t, err) - - sendTxRequest := methods.SendTransactionRequest{Transaction: b64} - var sendTxResponse methods.SendTransactionResponse - err = client.CallResult(context.Background(), "sendTransaction", sendTxRequest, &sendTxResponse) - assert.NoError(t, err) - assert.Equal(t, methods.TransactionPending, sendTxResponse.Status) - - txStatusResponse := getTransactionStatus(t, client, sendTxResponse.ID) - errorMessage := "" - if txStatusResponse.Error != nil { - errorMessage = txStatusResponse.Error.Message - } - assert.Equal(t, methods.TransactionSuccess, txStatusResponse.Status, errorMessage) -} From 1c96cbe55f3a766aaa83dee47cb8ca4d18adf13b Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Mon, 23 Jan 2023 14:01:39 +0000 Subject: [PATCH 2/2] rustfmt & clippy --- cmd/soroban-cli/src/serve.rs | 39 ++---------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/cmd/soroban-cli/src/serve.rs b/cmd/soroban-cli/src/serve.rs index b80b38b655..9e84992eba 100644 --- a/cmd/soroban-cli/src/serve.rs +++ b/cmd/soroban-cli/src/serve.rs @@ -10,9 +10,8 @@ use soroban_env_host::{ budget::Budget, storage::Storage, xdr::{ - self, Error as XdrError, FeeBumpTransactionInnerTx, HostFunction, LedgerEntryData, - LedgerKey, LedgerKeyContractData, OperationBody, ReadXdr, ScHostStorageErrorCode, ScObject, - ScStatus, ScVal, TransactionEnvelope, WriteXdr, + self, Error as XdrError, FeeBumpTransactionInnerTx, HostFunction, LedgerKey, OperationBody, + ReadXdr, ScHostStorageErrorCode, ScObject, ScStatus, ScVal, TransactionEnvelope, WriteXdr, }, Host, HostError, }; @@ -195,40 +194,6 @@ fn reply( } } -fn get_contract_data( - contract_id_hex: &str, - key_xdr: String, - ledger_file: &PathBuf, -) -> Result { - // Initialize storage and host - let state = utils::ledger_snapshot_read_or_default(ledger_file)?; - let contract_id: [u8; 32] = utils::id_from_str(&contract_id_hex.to_string())?; - let key = ScVal::from_xdr_base64(key_xdr)?; - - let snap = Rc::new(state); - let mut storage = Storage::with_recording_footprint(snap); - let ledger_entry = storage.get( - &LedgerKey::ContractData(LedgerKeyContractData { - contract_id: xdr::Hash(contract_id), - key, - }), - &soroban_env_host::budget::Budget::default(), - )?; - - let value = if let LedgerEntryData::ContractData(entry) = ledger_entry.data { - entry.val - } else { - unreachable!(); - }; - - Ok(json!({ - "xdr": value.to_xdr_base64()?, - "lastModifiedLedgerSeq": ledger_entry.last_modified_ledger_seq, - // TODO: Find "real" ledger seq number here - "latestLedger": 1, - })) -} - fn get_ledger_entry(k: Box<[String]>, ledger_file: &PathBuf) -> Result { if let Some(key_xdr) = k.into_vec().first() { // Initialize storage and host