From 5b5485a578b921f87395fad1c90438a65a32bac8 Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Thu, 11 Jul 2024 18:15:09 +0530 Subject: [PATCH 01/17] fix::> introduced comman AddTransaction function in account package --- account/account.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/account/account.go b/account/account.go index 1607e34b..40eaec16 100644 --- a/account/account.go +++ b/account/account.go @@ -533,6 +533,27 @@ func (account *Account) WaitForTransactionReceipt(ctx context.Context, transacti } } +// AddTransaction calls dynamically one of AddTransaction methods +// +// Parameters: +// - ctx: the context.Context object for the transaction. +// - txn: this Broadcast Transaction to be called. +// Returns: +// - interface{} returns required Broadcast txn return value. +// - error: an error if any. +func (account *Account) AddTransaction(ctx context.Context, txn rpc.BroadcastTxn) (interface{}, error) { + switch tx := txn.(type) { + case rpc.BroadcastInvokeTxnType: + return account.AddInvokeTransaction(ctx, tx) + case rpc.BroadcastDeclareTxnType: + return account.AddDeclareTransaction(ctx, tx) + case rpc.BroadcastAddDeployTxnType: + return account.AddDeployAccountTransaction(ctx, tx) + default: + return nil, errors.New("unsupported transaction type") + } +} + // AddInvokeTransaction generates an invoke transaction and adds it to the account's provider. // // Parameters: From db1fefc6b028b017364db2d46706995d75c51062 Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Thu, 11 Jul 2024 18:41:44 +0530 Subject: [PATCH 02/17] fix::> replace all the instances of AddTransaction in example/test with AddTransaction --- account/account_test.go | 14 +++++++------- examples/deployAccount/main.go | 7 ++++--- examples/deployContractUDC/main.go | 6 +++--- examples/simpleInvoke/main.go | 6 +++--- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/account/account_test.go b/account/account_test.go index 0e0a36df..63941f3d 100644 --- a/account/account_test.go +++ b/account/account_test.go @@ -526,10 +526,10 @@ func TestAddInvoke(t *testing.T) { err = acnt.SignInvokeTransaction(context.Background(), &test.InvokeTx.InvokeTxnV1) require.NoError(t, err) - resp, err := acnt.AddInvokeTransaction(context.Background(), test.InvokeTx) + resp, err := acnt.AddTransaction(context.Background(), test.InvokeTx) if err != nil { require.Equal(t, test.ExpectedErr.Error(), err.Error(), "AddInvokeTransaction returned an unexpected error") - require.Nil(t, resp) + require.Nil(t, resp.(*rpc.AddInvokeTransactionResponse)) } } @@ -595,9 +595,9 @@ func TestAddDeployAccountDevnet(t *testing.T) { _, err = devnet.Mint(precomputedAddress, new(big.Int).SetUint64(10000000000000000000)) require.NoError(t, err) - resp, err := acnt.AddDeployAccountTransaction(context.Background(), rpc.BroadcastDeployAccountTxn{DeployAccountTxn: tx}) + resp, err := acnt.AddTransaction(context.Background(), rpc.BroadcastDeployAccountTxn{DeployAccountTxn: tx}) require.Nil(t, err, "AddDeployAccountTransaction gave an Error") - require.NotNil(t, resp, "AddDeployAccountTransaction resp not nil") + require.NotNil(t, resp.(*rpc.AddDeployAccountTransactionResponse), "AddDeployAccountTransaction resp not nil") } // TestTransactionHashDeclare tests the TransactionHashDeclare function. @@ -1175,13 +1175,13 @@ func TestAddDeclareTxn(t *testing.T) { ContractClass: class, } - resp, err := acnt.AddDeclareTransaction(context.Background(), broadcastTx) + resp, err := acnt.AddTransaction(context.Background(), broadcastTx) if err != nil { require.Equal(t, rpc.ErrDuplicateTx.Error(), err.Error(), "AddDeclareTransaction error not what expected") } else { - require.Equal(t, expectedTxHash.String(), resp.TransactionHash.String(), "AddDeclareTransaction TxHash not what expected") - require.Equal(t, expectedClassHash.String(), resp.ClassHash.String(), "AddDeclareTransaction ClassHash not what expected") + require.Equal(t, expectedTxHash.String(), resp.(*rpc.AddDeclareTransactionResponse).TransactionHash.String(), "AddDeclareTransaction TxHash not what expected") + require.Equal(t, expectedClassHash.String(), resp.(*rpc.AddDeclareTransactionResponse).ClassHash.String(), "AddDeclareTransaction ClassHash not what expected") } } diff --git a/examples/deployAccount/main.go b/examples/deployAccount/main.go index 24152bf0..8357ba45 100644 --- a/examples/deployAccount/main.go +++ b/examples/deployAccount/main.go @@ -121,13 +121,14 @@ func main() { fmt.Scan(&input) // Send transaction to the network - resp, err := accnt.AddDeployAccountTransaction(context.Background(), tx) + // resp, err := accnt.AddDeployAccountTransaction(context.Background(), tx) + resp, err := accnt.AddTransaction(context.Background(), tx) if err != nil { fmt.Println("Error returned from AddDeployAccountTransaction: ") setup.PanicRPC(err) } fmt.Println("AddDeployAccountTransaction successfully submitted! Wait a few minutes to see it in Voyager.") - fmt.Printf("Transaction hash: %v \n", resp.TransactionHash) - fmt.Printf("Contract address: %v \n", resp.ContractAddress) + fmt.Printf("Transaction hash: %v \n", resp.(*rpc.AddDeployAccountTransactionResponse).TransactionHash) + fmt.Printf("Contract address: %v \n", resp.(*rpc.AddDeployAccountTransactionResponse).ContractAddress) } diff --git a/examples/deployContractUDC/main.go b/examples/deployContractUDC/main.go index 31ddc0c5..43a83365 100644 --- a/examples/deployContractUDC/main.go +++ b/examples/deployContractUDC/main.go @@ -128,7 +128,7 @@ func main() { } // After the signing we finally call the AddInvokeTransaction in order to invoke the contract function - resp, err := accnt.AddInvokeTransaction(context.Background(), InvokeTx) + resp, err := accnt.AddTransaction(context.Background(), InvokeTx) if err != nil { setup.PanicRPC(err) } @@ -137,13 +137,13 @@ func main() { time.Sleep(time.Second * 3) // Waiting 3 seconds //Getting the transaction status - txStatus, err := client.GetTransactionStatus(context.Background(), resp.TransactionHash) + txStatus, err := client.GetTransactionStatus(context.Background(), resp.(*rpc.AddInvokeTransactionResponse).TransactionHash) if err != nil { setup.PanicRPC(err) } // This returns us with the transaction hash and status - fmt.Printf("Transaction hash response: %v\n", resp.TransactionHash) + fmt.Printf("Transaction hash response: %v\n", resp.(*rpc.AddInvokeTransactionResponse).TransactionHash) fmt.Printf("Transaction execution status: %s\n", txStatus.ExecutionStatus) fmt.Printf("Transaction status: %s\n", txStatus.FinalityStatus) } diff --git a/examples/simpleInvoke/main.go b/examples/simpleInvoke/main.go index 2ed8ca89..9f3a5b2d 100644 --- a/examples/simpleInvoke/main.go +++ b/examples/simpleInvoke/main.go @@ -120,7 +120,7 @@ func main() { } // After the signing we finally call the AddInvokeTransaction in order to invoke the contract function - resp, err := accnt.AddInvokeTransaction(context.Background(), InvokeTx) + resp, err := accnt.AddTransaction(context.Background(), InvokeTx) if err != nil { setup.PanicRPC(err) } @@ -129,13 +129,13 @@ func main() { time.Sleep(time.Second * 3) // Waiting 3 seconds //Getting the transaction status - txStatus, err := client.GetTransactionStatus(context.Background(), resp.TransactionHash) + txStatus, err := client.GetTransactionStatus(context.Background(), resp.(*rpc.AddInvokeTransactionResponse).TransactionHash) if err != nil { setup.PanicRPC(err) } // This returns us with the transaction hash and status - fmt.Printf("Transaction hash response: %v\n", resp.TransactionHash) + fmt.Printf("Transaction hash response: %v\n", resp.(*rpc.AddInvokeTransactionResponse).TransactionHash) fmt.Printf("Transaction execution status: %s\n", txStatus.ExecutionStatus) fmt.Printf("Transaction status: %s\n", txStatus.FinalityStatus) From 5132f1dbb3a1e89ed7aa607165dd23e28e3d76e9 Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Mon, 15 Jul 2024 11:10:13 +0530 Subject: [PATCH 03/17] fix::> func name and doc changes made --- account/account.go | 68 ++++++++++++------------------- rpc/types_transaction_response.go | 6 +++ 2 files changed, 32 insertions(+), 42 deletions(-) diff --git a/account/account.go b/account/account.go index 40eaec16..180e23ed 100644 --- a/account/account.go +++ b/account/account.go @@ -40,7 +40,6 @@ type AccountInterface interface { } var _ AccountInterface = &Account{} -var _ rpc.RpcProvider = &Account{} type Account struct { provider rpc.RpcProvider @@ -533,62 +532,47 @@ func (account *Account) WaitForTransactionReceipt(ctx context.Context, transacti } } -// AddTransaction calls dynamically one of AddTransaction methods +// SendTransaction can send Invoke, Declare, and Deploy transactions. It provides a unified way to send different transactions. // // Parameters: // - ctx: the context.Context object for the transaction. -// - txn: this Broadcast Transaction to be called. +// - txn: this Broadcast Transaction to be sent. // Returns: // - interface{} returns required Broadcast txn return value. // - error: an error if any. -func (account *Account) AddTransaction(ctx context.Context, txn rpc.BroadcastTxn) (interface{}, error) { +func (account *Account) SendTransaction(ctx context.Context, txn rpc.BroadcastTxn) (interface{}, error) { switch tx := txn.(type) { case rpc.BroadcastInvokeTxnType: - return account.AddInvokeTransaction(ctx, tx) + return account.provider.AddInvokeTransaction(ctx, tx) case rpc.BroadcastDeclareTxnType: - return account.AddDeclareTransaction(ctx, tx) + return account.provider.AddDeclareTransaction(ctx, tx) case rpc.BroadcastAddDeployTxnType: - return account.AddDeployAccountTransaction(ctx, tx) + return account.provider.AddDeployAccountTransaction(ctx, tx) default: return nil, errors.New("unsupported transaction type") } } -// AddInvokeTransaction generates an invoke transaction and adds it to the account's provider. -// -// Parameters: -// - ctx: the context.Context object for the transaction. -// - invokeTx: the invoke transaction to be added. -// Returns: -// - *rpc.AddInvokeTransactionResponse: The response for the AddInvokeTransactionResponse -// - error: an error if any. -func (account *Account) AddInvokeTransaction(ctx context.Context, invokeTx rpc.BroadcastInvokeTxnType) (*rpc.AddInvokeTransactionResponse, error) { - return account.provider.AddInvokeTransaction(ctx, invokeTx) -} - -// AddDeclareTransaction adds a declare transaction to the account. -// -// Parameters: -// - ctx: The context.Context for the request. -// - declareTransaction: The input for adding a declare transaction. -// Returns: -// - *rpc.AddDeclareTransactionResponse: The response for adding a declare transaction -// - error: an error, if any -func (account *Account) AddDeclareTransaction(ctx context.Context, declareTransaction rpc.BroadcastDeclareTxnType) (*rpc.AddDeclareTransactionResponse, error) { - return account.provider.AddDeclareTransaction(ctx, declareTransaction) -} - -// AddDeployAccountTransaction adds a deploy account transaction to the account. -// -// Parameters: -// - ctx: The context.Context object for the function. -// - deployAccountTransaction: The rpc.DeployAccountTxn object representing the deploy account transaction. -// Returns: -// - *rpc.AddDeployAccountTransactionResponse: a pointer to rpc.AddDeployAccountTransactionResponse -// - error: an error if any -func (account *Account) AddDeployAccountTransaction(ctx context.Context, deployAccountTransaction rpc.BroadcastAddDeployTxnType) (*rpc.AddDeployAccountTransactionResponse, error) { - return account.provider.AddDeployAccountTransaction(ctx, deployAccountTransaction) -} +// func convertToTransactionResponse(resp interface{}) *rpc.TransactionResponse { +// switch r := resp.(type) { +// case *rpc.AddInvokeTransactionResponse: +// return &rpc.TransactionResponse{ +// TransactionHash: r.TransactionHash, +// } +// case *rpc.AddDeclareTransactionResponse: +// return &rpc.TransactionResponse{ +// TransactionHash: r.TransactionHash, +// ClassHash: r.ClassHash, +// } +// case *rpc.AddDeployAccountTransactionResponse: +// return &rpc.TransactionResponse{ +// TransactionHash: r.TransactionHash, +// ContractAddress: r.ContractAddress, +// } +// default: +// return nil +// } +// } // BlockHashAndNumber returns the block hash and number for the account. // diff --git a/rpc/types_transaction_response.go b/rpc/types_transaction_response.go index 3e94c07d..15920f94 100644 --- a/rpc/types_transaction_response.go +++ b/rpc/types_transaction_response.go @@ -18,3 +18,9 @@ type AddDeployAccountTransactionResponse struct { type AddInvokeTransactionResponse struct { TransactionHash *felt.Felt `json:"transaction_hash"` } + +// type TransactionResponse struct { +// TransactionHash *felt.Felt `json:"transaction_hash"` +// ClassHash *felt.Felt `json:"class_hash"` +// ContractAddress *felt.Felt `json:"contract_address"` +// } From cc8dab37b6d8afc172055ec2ab2a5ab267b58cec Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Mon, 15 Jul 2024 11:11:19 +0530 Subject: [PATCH 04/17] fix::> account_test.go changed --- account/account_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/account/account_test.go b/account/account_test.go index 63941f3d..d2ab4c09 100644 --- a/account/account_test.go +++ b/account/account_test.go @@ -526,7 +526,7 @@ func TestAddInvoke(t *testing.T) { err = acnt.SignInvokeTransaction(context.Background(), &test.InvokeTx.InvokeTxnV1) require.NoError(t, err) - resp, err := acnt.AddTransaction(context.Background(), test.InvokeTx) + resp, err := acnt.SendTransaction(context.Background(), test.InvokeTx) if err != nil { require.Equal(t, test.ExpectedErr.Error(), err.Error(), "AddInvokeTransaction returned an unexpected error") require.Nil(t, resp.(*rpc.AddInvokeTransactionResponse)) @@ -595,7 +595,7 @@ func TestAddDeployAccountDevnet(t *testing.T) { _, err = devnet.Mint(precomputedAddress, new(big.Int).SetUint64(10000000000000000000)) require.NoError(t, err) - resp, err := acnt.AddTransaction(context.Background(), rpc.BroadcastDeployAccountTxn{DeployAccountTxn: tx}) + resp, err := acnt.SendTransaction(context.Background(), rpc.BroadcastDeployAccountTxn{DeployAccountTxn: tx}) require.Nil(t, err, "AddDeployAccountTransaction gave an Error") require.NotNil(t, resp.(*rpc.AddDeployAccountTransactionResponse), "AddDeployAccountTransaction resp not nil") } @@ -1175,7 +1175,7 @@ func TestAddDeclareTxn(t *testing.T) { ContractClass: class, } - resp, err := acnt.AddTransaction(context.Background(), broadcastTx) + resp, err := acnt.SendTransaction(context.Background(), broadcastTx) if err != nil { require.Equal(t, rpc.ErrDuplicateTx.Error(), err.Error(), "AddDeclareTransaction error not what expected") From 0de86de28a099f94906551b36072b0457159ff1c Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Mon, 15 Jul 2024 11:13:19 +0530 Subject: [PATCH 05/17] fix::> examples error solved --- examples/deployAccount/main.go | 2 +- examples/deployContractUDC/main.go | 2 +- examples/simpleInvoke/main.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/deployAccount/main.go b/examples/deployAccount/main.go index 8357ba45..cae67f6b 100644 --- a/examples/deployAccount/main.go +++ b/examples/deployAccount/main.go @@ -122,7 +122,7 @@ func main() { // Send transaction to the network // resp, err := accnt.AddDeployAccountTransaction(context.Background(), tx) - resp, err := accnt.AddTransaction(context.Background(), tx) + resp, err := accnt.SendTransaction(context.Background(), tx) if err != nil { fmt.Println("Error returned from AddDeployAccountTransaction: ") setup.PanicRPC(err) diff --git a/examples/deployContractUDC/main.go b/examples/deployContractUDC/main.go index 43a83365..95a08137 100644 --- a/examples/deployContractUDC/main.go +++ b/examples/deployContractUDC/main.go @@ -128,7 +128,7 @@ func main() { } // After the signing we finally call the AddInvokeTransaction in order to invoke the contract function - resp, err := accnt.AddTransaction(context.Background(), InvokeTx) + resp, err := accnt.SendTransaction(context.Background(), InvokeTx) if err != nil { setup.PanicRPC(err) } diff --git a/examples/simpleInvoke/main.go b/examples/simpleInvoke/main.go index 9f3a5b2d..1e9a2df9 100644 --- a/examples/simpleInvoke/main.go +++ b/examples/simpleInvoke/main.go @@ -120,7 +120,7 @@ func main() { } // After the signing we finally call the AddInvokeTransaction in order to invoke the contract function - resp, err := accnt.AddTransaction(context.Background(), InvokeTx) + resp, err := accnt.SendTransaction(context.Background(), InvokeTx) if err != nil { setup.PanicRPC(err) } From 3b3d684ed63ed2e3c093ba2c5f42c1a7c57d9ab3 Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Mon, 15 Jul 2024 11:24:12 +0530 Subject: [PATCH 06/17] fix::> Removed type assertions, created generic TransactionResponse struct, and transaction type converter --- account/account.go | 41 ++++++++++++------------------ account/account_test.go | 8 +++--- examples/deployAccount/main.go | 4 +-- examples/deployContractUDC/main.go | 4 +-- examples/simpleInvoke/main.go | 4 +-- rpc/types_transaction_response.go | 31 ++++++++++++++++++---- 6 files changed, 52 insertions(+), 40 deletions(-) diff --git a/account/account.go b/account/account.go index 180e23ed..c8d222db 100644 --- a/account/account.go +++ b/account/account.go @@ -540,40 +540,31 @@ func (account *Account) WaitForTransactionReceipt(ctx context.Context, transacti // Returns: // - interface{} returns required Broadcast txn return value. // - error: an error if any. -func (account *Account) SendTransaction(ctx context.Context, txn rpc.BroadcastTxn) (interface{}, error) { +func (account *Account) SendTransaction(ctx context.Context, txn rpc.BroadcastTxn) (*rpc.TransactionResponse, error) { switch tx := txn.(type) { case rpc.BroadcastInvokeTxnType: - return account.provider.AddInvokeTransaction(ctx, tx) + resp, err := account.provider.AddInvokeTransaction(ctx, tx) + if err != nil { + return nil, err + } + return rpc.ConvertToTransactionResponse(resp), nil case rpc.BroadcastDeclareTxnType: - return account.provider.AddDeclareTransaction(ctx, tx) + resp, err := account.provider.AddDeclareTransaction(ctx, tx) + if err != nil { + return nil, err + } + return rpc.ConvertToTransactionResponse(resp), nil case rpc.BroadcastAddDeployTxnType: - return account.provider.AddDeployAccountTransaction(ctx, tx) + resp, err := account.provider.AddDeployAccountTransaction(ctx, tx) + if err != nil { + return nil, err + } + return rpc.ConvertToTransactionResponse(resp), nil default: return nil, errors.New("unsupported transaction type") } } -// func convertToTransactionResponse(resp interface{}) *rpc.TransactionResponse { -// switch r := resp.(type) { -// case *rpc.AddInvokeTransactionResponse: -// return &rpc.TransactionResponse{ -// TransactionHash: r.TransactionHash, -// } -// case *rpc.AddDeclareTransactionResponse: -// return &rpc.TransactionResponse{ -// TransactionHash: r.TransactionHash, -// ClassHash: r.ClassHash, -// } -// case *rpc.AddDeployAccountTransactionResponse: -// return &rpc.TransactionResponse{ -// TransactionHash: r.TransactionHash, -// ContractAddress: r.ContractAddress, -// } -// default: -// return nil -// } -// } - // BlockHashAndNumber returns the block hash and number for the account. // // Parameters: diff --git a/account/account_test.go b/account/account_test.go index d2ab4c09..bfef61d3 100644 --- a/account/account_test.go +++ b/account/account_test.go @@ -529,7 +529,7 @@ func TestAddInvoke(t *testing.T) { resp, err := acnt.SendTransaction(context.Background(), test.InvokeTx) if err != nil { require.Equal(t, test.ExpectedErr.Error(), err.Error(), "AddInvokeTransaction returned an unexpected error") - require.Nil(t, resp.(*rpc.AddInvokeTransactionResponse)) + require.Nil(t, resp) } } @@ -597,7 +597,7 @@ func TestAddDeployAccountDevnet(t *testing.T) { resp, err := acnt.SendTransaction(context.Background(), rpc.BroadcastDeployAccountTxn{DeployAccountTxn: tx}) require.Nil(t, err, "AddDeployAccountTransaction gave an Error") - require.NotNil(t, resp.(*rpc.AddDeployAccountTransactionResponse), "AddDeployAccountTransaction resp not nil") + require.NotNil(t, resp, "AddDeployAccountTransaction resp not nil") } // TestTransactionHashDeclare tests the TransactionHashDeclare function. @@ -1180,8 +1180,8 @@ func TestAddDeclareTxn(t *testing.T) { if err != nil { require.Equal(t, rpc.ErrDuplicateTx.Error(), err.Error(), "AddDeclareTransaction error not what expected") } else { - require.Equal(t, expectedTxHash.String(), resp.(*rpc.AddDeclareTransactionResponse).TransactionHash.String(), "AddDeclareTransaction TxHash not what expected") - require.Equal(t, expectedClassHash.String(), resp.(*rpc.AddDeclareTransactionResponse).ClassHash.String(), "AddDeclareTransaction ClassHash not what expected") + require.Equal(t, expectedTxHash.String(), resp.TransactionHash.String(), "AddDeclareTransaction TxHash not what expected") + require.Equal(t, expectedClassHash.String(), resp.ClassHash.String(), "AddDeclareTransaction ClassHash not what expected") } } diff --git a/examples/deployAccount/main.go b/examples/deployAccount/main.go index cae67f6b..e013fc7c 100644 --- a/examples/deployAccount/main.go +++ b/examples/deployAccount/main.go @@ -129,6 +129,6 @@ func main() { } fmt.Println("AddDeployAccountTransaction successfully submitted! Wait a few minutes to see it in Voyager.") - fmt.Printf("Transaction hash: %v \n", resp.(*rpc.AddDeployAccountTransactionResponse).TransactionHash) - fmt.Printf("Contract address: %v \n", resp.(*rpc.AddDeployAccountTransactionResponse).ContractAddress) + fmt.Printf("Transaction hash: %v \n", resp.TransactionHash) + fmt.Printf("Contract address: %v \n", resp.ContractAddress) } diff --git a/examples/deployContractUDC/main.go b/examples/deployContractUDC/main.go index 95a08137..90f66e85 100644 --- a/examples/deployContractUDC/main.go +++ b/examples/deployContractUDC/main.go @@ -137,13 +137,13 @@ func main() { time.Sleep(time.Second * 3) // Waiting 3 seconds //Getting the transaction status - txStatus, err := client.GetTransactionStatus(context.Background(), resp.(*rpc.AddInvokeTransactionResponse).TransactionHash) + txStatus, err := client.GetTransactionStatus(context.Background(), resp.TransactionHash) if err != nil { setup.PanicRPC(err) } // This returns us with the transaction hash and status - fmt.Printf("Transaction hash response: %v\n", resp.(*rpc.AddInvokeTransactionResponse).TransactionHash) + fmt.Printf("Transaction hash response: %v\n", resp.TransactionHash) fmt.Printf("Transaction execution status: %s\n", txStatus.ExecutionStatus) fmt.Printf("Transaction status: %s\n", txStatus.FinalityStatus) } diff --git a/examples/simpleInvoke/main.go b/examples/simpleInvoke/main.go index 1e9a2df9..09be957e 100644 --- a/examples/simpleInvoke/main.go +++ b/examples/simpleInvoke/main.go @@ -129,13 +129,13 @@ func main() { time.Sleep(time.Second * 3) // Waiting 3 seconds //Getting the transaction status - txStatus, err := client.GetTransactionStatus(context.Background(), resp.(*rpc.AddInvokeTransactionResponse).TransactionHash) + txStatus, err := client.GetTransactionStatus(context.Background(), resp.TransactionHash) if err != nil { setup.PanicRPC(err) } // This returns us with the transaction hash and status - fmt.Printf("Transaction hash response: %v\n", resp.(*rpc.AddInvokeTransactionResponse).TransactionHash) + fmt.Printf("Transaction hash response: %v\n", resp.TransactionHash) fmt.Printf("Transaction execution status: %s\n", txStatus.ExecutionStatus) fmt.Printf("Transaction status: %s\n", txStatus.FinalityStatus) diff --git a/rpc/types_transaction_response.go b/rpc/types_transaction_response.go index 15920f94..5d0b319d 100644 --- a/rpc/types_transaction_response.go +++ b/rpc/types_transaction_response.go @@ -19,8 +19,29 @@ type AddInvokeTransactionResponse struct { TransactionHash *felt.Felt `json:"transaction_hash"` } -// type TransactionResponse struct { -// TransactionHash *felt.Felt `json:"transaction_hash"` -// ClassHash *felt.Felt `json:"class_hash"` -// ContractAddress *felt.Felt `json:"contract_address"` -// } +type TransactionResponse struct { + TransactionHash *felt.Felt `json:"transaction_hash"` + ClassHash *felt.Felt `json:"class_hash"` + ContractAddress *felt.Felt `json:"contract_address"` +} + +func ConvertToTransactionResponse(resp interface{}) *TransactionResponse { + switch r := resp.(type) { + case *AddInvokeTransactionResponse: + return &TransactionResponse{ + TransactionHash: r.TransactionHash, + } + case *AddDeclareTransactionResponse: + return &TransactionResponse{ + TransactionHash: r.TransactionHash, + ClassHash: r.ClassHash, + } + case *AddDeployAccountTransactionResponse: + return &TransactionResponse{ + TransactionHash: r.TransactionHash, + ContractAddress: r.ContractAddress, + } + default: + return nil + } +} From 762544c6eca3a8fc78f052206a804fa5c06c83e7 Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Tue, 16 Jul 2024 17:19:57 +0530 Subject: [PATCH 07/17] fix::> removed unnecessary lines --- examples/deployAccount/main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/deployAccount/main.go b/examples/deployAccount/main.go index e013fc7c..8f56d68c 100644 --- a/examples/deployAccount/main.go +++ b/examples/deployAccount/main.go @@ -121,7 +121,6 @@ func main() { fmt.Scan(&input) // Send transaction to the network - // resp, err := accnt.AddDeployAccountTransaction(context.Background(), tx) resp, err := accnt.SendTransaction(context.Background(), tx) if err != nil { fmt.Println("Error returned from AddDeployAccountTransaction: ") From 91be01a66134209e9609d5e9d2bd343fc74bd1a7 Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Wed, 17 Jul 2024 20:23:23 +0530 Subject: [PATCH 08/17] fix:> made required changes --- account/account.go | 10 +++---- rpc/types_transaction_response.go | 44 +++++++++++++++---------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/account/account.go b/account/account.go index c8d222db..a12baede 100644 --- a/account/account.go +++ b/account/account.go @@ -536,9 +536,9 @@ func (account *Account) WaitForTransactionReceipt(ctx context.Context, transacti // // Parameters: // - ctx: the context.Context object for the transaction. -// - txn: this Broadcast Transaction to be sent. +// - txn: the Broadcast Transaction to be sent. // Returns: -// - interface{} returns required Broadcast txn return value. +// - *rpc.TransactionResponse: the transaction response. // - error: an error if any. func (account *Account) SendTransaction(ctx context.Context, txn rpc.BroadcastTxn) (*rpc.TransactionResponse, error) { switch tx := txn.(type) { @@ -547,19 +547,19 @@ func (account *Account) SendTransaction(ctx context.Context, txn rpc.BroadcastTx if err != nil { return nil, err } - return rpc.ConvertToTransactionResponse(resp), nil + return &rpc.TransactionResponse{TransactionHash: resp.TransactionHash}, nil case rpc.BroadcastDeclareTxnType: resp, err := account.provider.AddDeclareTransaction(ctx, tx) if err != nil { return nil, err } - return rpc.ConvertToTransactionResponse(resp), nil + return &rpc.TransactionResponse{TransactionHash: resp.TransactionHash, ClassHash: resp.ClassHash}, nil case rpc.BroadcastAddDeployTxnType: resp, err := account.provider.AddDeployAccountTransaction(ctx, tx) if err != nil { return nil, err } - return rpc.ConvertToTransactionResponse(resp), nil + return &rpc.TransactionResponse{TransactionHash: resp.TransactionHash, ContractAddress: resp.ContractAddress}, nil default: return nil, errors.New("unsupported transaction type") } diff --git a/rpc/types_transaction_response.go b/rpc/types_transaction_response.go index 5d0b319d..bfce40e1 100644 --- a/rpc/types_transaction_response.go +++ b/rpc/types_transaction_response.go @@ -21,27 +21,27 @@ type AddInvokeTransactionResponse struct { type TransactionResponse struct { TransactionHash *felt.Felt `json:"transaction_hash"` - ClassHash *felt.Felt `json:"class_hash"` - ContractAddress *felt.Felt `json:"contract_address"` + ClassHash *felt.Felt `json:"class_hash,omitempty"` + ContractAddress *felt.Felt `json:"contract_address,omitempty"` } -func ConvertToTransactionResponse(resp interface{}) *TransactionResponse { - switch r := resp.(type) { - case *AddInvokeTransactionResponse: - return &TransactionResponse{ - TransactionHash: r.TransactionHash, - } - case *AddDeclareTransactionResponse: - return &TransactionResponse{ - TransactionHash: r.TransactionHash, - ClassHash: r.ClassHash, - } - case *AddDeployAccountTransactionResponse: - return &TransactionResponse{ - TransactionHash: r.TransactionHash, - ContractAddress: r.ContractAddress, - } - default: - return nil - } -} +// func ConvertToTransactionResponse(resp interface{}) *TransactionResponse { +// switch r := resp.(type) { +// case *AddInvokeTransactionResponse: +// return &TransactionResponse{ +// TransactionHash: r.TransactionHash, +// } +// case *AddDeclareTransactionResponse: +// return &TransactionResponse{ +// TransactionHash: r.TransactionHash, +// ClassHash: r.ClassHash, +// } +// case *AddDeployAccountTransactionResponse: +// return &TransactionResponse{ +// TransactionHash: r.TransactionHash, +// ContractAddress: r.ContractAddress, +// } +// default: +// return nil +// } +// } From b9d9980a16cac2ba185993c1438312e12e7bad3b Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Thu, 18 Jul 2024 11:23:41 +0530 Subject: [PATCH 09/17] fix::> removed unnecessary comments --- rpc/types_transaction_response.go | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/rpc/types_transaction_response.go b/rpc/types_transaction_response.go index bfce40e1..cf4fd33d 100644 --- a/rpc/types_transaction_response.go +++ b/rpc/types_transaction_response.go @@ -24,24 +24,3 @@ type TransactionResponse struct { ClassHash *felt.Felt `json:"class_hash,omitempty"` ContractAddress *felt.Felt `json:"contract_address,omitempty"` } - -// func ConvertToTransactionResponse(resp interface{}) *TransactionResponse { -// switch r := resp.(type) { -// case *AddInvokeTransactionResponse: -// return &TransactionResponse{ -// TransactionHash: r.TransactionHash, -// } -// case *AddDeclareTransactionResponse: -// return &TransactionResponse{ -// TransactionHash: r.TransactionHash, -// ClassHash: r.ClassHash, -// } -// case *AddDeployAccountTransactionResponse: -// return &TransactionResponse{ -// TransactionHash: r.TransactionHash, -// ContractAddress: r.ContractAddress, -// } -// default: -// return nil -// } -// } From 0b5ac0b8395747415983043421dce802f6cbda98 Mon Sep 17 00:00:00 2001 From: Abhinav Prakash Date: Fri, 19 Jul 2024 12:17:49 +0530 Subject: [PATCH 10/17] fix::> renamed test function --- account/account_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/account/account_test.go b/account/account_test.go index bfef61d3..b254d04d 100644 --- a/account/account_test.go +++ b/account/account_test.go @@ -436,7 +436,7 @@ func TestSignMOCK(t *testing.T) { // Returns: // // none -func TestAddInvoke(t *testing.T) { +func TestSendInvokeTxn(t *testing.T) { type testSetType struct { ExpectedErr error @@ -552,7 +552,7 @@ func TestAddInvoke(t *testing.T) { // Returns: // // none -func TestAddDeployAccountDevnet(t *testing.T) { +func TestSendDeployAccountDevnet(t *testing.T) { if testEnv != "devnet" { t.Skip("Skipping test as it requires a devnet environment") } @@ -1106,7 +1106,7 @@ func TestWaitForTransactionReceipt(t *testing.T) { // Returns: // // none -func TestAddDeclareTxn(t *testing.T) { +func TestSendDeclareTxn(t *testing.T) { if testEnv != "testnet" { t.Skip("Skipping test as it requires a testnet environment") } From f35d88f480b46623287b7aca6d8e3df89b98b990 Mon Sep 17 00:00:00 2001 From: Thiago Ribeiro <62709592+thiagodeev@users.noreply.github.com> Date: Mon, 30 Sep 2024 06:19:04 -0300 Subject: [PATCH 11/17] Thiagodeev/rpcv08 write methods, blockHeader and error 53 (#626) Update write methods, error 53 and block header for rpc08 --- rpc/errors.go | 4 ++-- rpc/types_block.go | 2 ++ rpc/write.go | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/rpc/errors.go b/rpc/errors.go index b11dce85..337f4d42 100644 --- a/rpc/errors.go +++ b/rpc/errors.go @@ -150,9 +150,9 @@ var ( Code: 52, Message: "Invalid transaction nonce", } - ErrInsufficientMaxFee = &RPCError{ + ErrInsufficientResourcesForValidate = &RPCError{ Code: 53, - Message: "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)", + Message: "The transaction's resources don't cover validation or the minimal transaction fee", } ErrInsufficientAccountBalance = &RPCError{ Code: 54, diff --git a/rpc/types_block.go b/rpc/types_block.go index a58f0821..d54a63f3 100644 --- a/rpc/types_block.go +++ b/rpc/types_block.go @@ -174,6 +174,8 @@ type BlockHeader struct { SequencerAddress *felt.Felt `json:"sequencer_address"` // The price of l1 gas in the block L1GasPrice ResourcePrice `json:"l1_gas_price"` + // The price of l2 gas in the block + L2GasPrice ResourcePrice `json:"l2_gas_price"` // The price of l1 data gas in the block L1DataGasPrice ResourcePrice `json:"l1_data_gas_price"` // Specifies whether the data of this block is published via blob data or calldata diff --git a/rpc/write.go b/rpc/write.go index e91b3d52..123af2fc 100644 --- a/rpc/write.go +++ b/rpc/write.go @@ -18,7 +18,7 @@ func (provider *Provider) AddInvokeTransaction(ctx context.Context, invokeTxn Br return nil, tryUnwrapToRPCErr( err, ErrInsufficientAccountBalance, - ErrInsufficientMaxFee, + ErrInsufficientResourcesForValidate, ErrInvalidTransactionNonce, ErrValidationFailure, ErrNonAccount, @@ -47,7 +47,7 @@ func (provider *Provider) AddDeclareTransaction(ctx context.Context, declareTran ErrCompilationFailed, ErrCompiledClassHashMismatch, ErrInsufficientAccountBalance, - ErrInsufficientMaxFee, + ErrInsufficientResourcesForValidate, ErrInvalidTransactionNonce, ErrValidationFailure, ErrNonAccount, @@ -73,7 +73,7 @@ func (provider *Provider) AddDeployAccountTransaction(ctx context.Context, deplo return nil, tryUnwrapToRPCErr( err, ErrInsufficientAccountBalance, - ErrInsufficientMaxFee, + ErrInsufficientResourcesForValidate, ErrInvalidTransactionNonce, ErrValidationFailure, ErrNonAccount, From 34e41a74512bc96ebbc8b511be6dbb243d4b557a Mon Sep 17 00:00:00 2001 From: thiagodeev Date: Mon, 30 Sep 2024 09:31:31 -0300 Subject: [PATCH 12/17] Adjusts TransactionStatus --- rpc/transaction_test.go | 2 ++ rpc/types_transaction_receipt.go | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/rpc/transaction_test.go b/rpc/transaction_test.go index a674738a..6fb914a2 100644 --- a/rpc/transaction_test.go +++ b/rpc/transaction_test.go @@ -179,6 +179,8 @@ func TestTransactionReceipt(t *testing.T) { // TestGetTransactionStatus tests starknet_getTransactionStatus func TestGetTransactionStatus(t *testing.T) { + //TODO: implement a test case to 'failure_reason' before merge + testConfig := beforeEach(t) type testSetType struct { diff --git a/rpc/types_transaction_receipt.go b/rpc/types_transaction_receipt.go index d9d04d4a..755734a9 100644 --- a/rpc/types_transaction_receipt.go +++ b/rpc/types_transaction_receipt.go @@ -176,8 +176,9 @@ const ( ) type TxnStatusResp struct { - ExecutionStatus TxnExecutionStatus `json:"execution_status,omitempty"` FinalityStatus TxnStatus `json:"finality_status"` + ExecutionStatus TxnExecutionStatus `json:"execution_status,omitempty"` + FailureReason string `json:"failure_reason,omitempty"` } type TransactionReceiptWithBlockInfo struct { From cdd6056182118d89d9573aa1447c82739f19513e Mon Sep 17 00:00:00 2001 From: thiagodeev Date: Mon, 30 Sep 2024 10:07:56 -0300 Subject: [PATCH 13/17] Adjusts EstimateFee --- rpc/contract_test.go | 347 ++++++++++++++++++++++--------------------- rpc/mock_test.go | 36 +++-- rpc/types.go | 16 +- 3 files changed, 210 insertions(+), 189 deletions(-) diff --git a/rpc/contract_test.go b/rpc/contract_test.go index 5b621e5c..36762474 100644 --- a/rpc/contract_test.go +++ b/rpc/contract_test.go @@ -397,6 +397,7 @@ func TestNonce(t *testing.T) { // // none func TestEstimateMessageFee(t *testing.T) { + //TODO: upgrade the testnet test case before merge testConfig := beforeEach(t) type testSetType struct { @@ -426,25 +427,27 @@ func TestEstimateMessageFee(t *testing.T) { MsgFromL1: MsgFromL1{FromAddress: "0x0", ToAddress: &felt.Zero, Selector: &felt.Zero, Payload: []*felt.Felt{&felt.Zero}}, BlockID: BlockID{Tag: "latest"}, ExpectedFeeEst: &FeeEstimation{ - GasConsumed: new(felt.Felt).SetUint64(1), - GasPrice: new(felt.Felt).SetUint64(2), - OverallFee: new(felt.Felt).SetUint64(3), + L1GasConsumed: utils.RANDOM_FELT, + L1GasPrice: utils.RANDOM_FELT, + L2GasConsumed: utils.RANDOM_FELT, + L2GasPrice: utils.RANDOM_FELT, + OverallFee: utils.RANDOM_FELT, }, }, }, "testnet": { - { - MsgFromL1: l1Handler, - BlockID: WithBlockNumber(122476), - ExpectedFeeEst: &FeeEstimation{ - GasConsumed: utils.TestHexToFelt(t, "0x567b"), - GasPrice: utils.TestHexToFelt(t, "0x28fb3be9e"), - DataGasConsumed: &felt.Zero, - DataGasPrice: utils.TestHexToFelt(t, "0x216251c284"), - OverallFee: utils.TestHexToFelt(t, "0xdd816d65a9ea"), - FeeUnit: UnitWei, - }, - }, + // { + // MsgFromL1: l1Handler, + // BlockID: WithBlockNumber(122476), + // ExpectedFeeEst: &FeeEstimation{ + // GasConsumed: utils.TestHexToFelt(t, "0x567b"), + // GasPrice: utils.TestHexToFelt(t, "0x28fb3be9e"), + // DataGasConsumed: &felt.Zero, + // DataGasPrice: utils.TestHexToFelt(t, "0x216251c284"), + // OverallFee: utils.TestHexToFelt(t, "0xdd816d65a9ea"), + // FeeUnit: UnitWei, + // }, + // }, { // invalid msg data MsgFromL1: MsgFromL1{ FromAddress: "0x8453fc6cd1bcfe8d4dfc069c400b433054d47bdc", @@ -475,6 +478,8 @@ func TestEstimateMessageFee(t *testing.T) { } func TestEstimateFee(t *testing.T) { + //TODO: upgrade the mainnet and testnet test cases before merge + testConfig := beforeEach(t) type testSetType struct { @@ -492,86 +497,86 @@ func TestEstimateFee(t *testing.T) { require.NoError(t, err) testSet := map[string][]testSetType{ - "mainnet": { - { - txs: []BroadcastTxn{ - InvokeTxnV0{ - Type: TransactionType_Invoke, - Version: TransactionV0, - MaxFee: utils.TestHexToFelt(t, "0x95e566845d000"), - FunctionCall: FunctionCall{ - ContractAddress: utils.TestHexToFelt(t, "0x45e92c365ba0908382bc346159f896e528214470c60ae2cd4038a0fff747b1e"), - EntryPointSelector: utils.TestHexToFelt(t, "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad"), - Calldata: utils.TestHexArrToFelt(t, []string{ - "0x1", - "0x4a3621276a83251b557a8140e915599ae8e7b6207b067ea701635c0d509801e", - "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", - "0x0", - "0x3", - "0x3", - "0x697066733a2f2f516d57554c7a475135556a52616953514776717765347931", - "0x4731796f4757324e6a5a76564e77776a66514577756a", - "0x0", - "0x2"}), - }, - Signature: []*felt.Felt{ - utils.TestHexToFelt(t, "0x63e4618ca2e323a45b9f860f12a4f5c4984648f1d110aa393e79d596d82abcc"), - utils.TestHexToFelt(t, "0x2844257b088ad4f49e2fe3df1ea6a8530aa2d21d8990112b7e88c4bd0ce9d50"), - }, - }, - }, - simFlags: []SimulationFlag{}, - blockID: WithBlockNumber(15643), - expectedError: nil, - expectedResp: []FeeEstimation{ - { - GasConsumed: utils.TestHexToFelt(t, "0x3074"), - GasPrice: utils.TestHexToFelt(t, "0x350da9915"), - DataGasConsumed: &felt.Zero, - DataGasPrice: new(felt.Felt).SetUint64(1), - OverallFee: utils.TestHexToFelt(t, "0xa0a99fc14d84"), - FeeUnit: UnitWei, - }, - }, - }, - { - txs: []BroadcastTxn{ - DeployAccountTxn{ - - Type: TransactionType_DeployAccount, - Version: TransactionV1, - MaxFee: utils.TestHexToFelt(t, "0xdec823b1380c"), - Nonce: utils.TestHexToFelt(t, "0x0"), - Signature: []*felt.Felt{ - utils.TestHexToFelt(t, "0x41dbc4b41f6506502a09eb7aea85759de02e91f49d0565776125946e54a2ec6"), - utils.TestHexToFelt(t, "0x85dcf2bc8e3543071a6657947cc9c157a9f6ad7844a686a975b588199634a9"), - }, - ContractAddressSalt: utils.TestHexToFelt(t, "0x74ddc51af144d1bd805eb4184d07453d7c4388660270a7851fec387e654a50e"), - ClassHash: utils.TestHexToFelt(t, "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918"), - ConstructorCalldata: utils.TestHexArrToFelt(t, []string{ - "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", - "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", - "0x2", - "0x74ddc51af144d1bd805eb4184d07453d7c4388660270a7851fec387e654a50e", - "0x0", - }), - }, - }, - simFlags: []SimulationFlag{}, - blockID: WithBlockHash(utils.TestHexToFelt(t, "0x1b0df1bafcb826b1fc053495aef5cdc24d0345cbfa1259b15939d01b89dc6d9")), - expectedError: nil, - expectedResp: []FeeEstimation{ - { - GasConsumed: utils.TestHexToFelt(t, "0x1154"), - GasPrice: utils.TestHexToFelt(t, "0x378f962c4"), - DataGasConsumed: &felt.Zero, - DataGasPrice: new(felt.Felt).SetUint64(1), - OverallFee: utils.TestHexToFelt(t, "0x3c2c41636c50"), - FeeUnit: UnitWei, - }, - }, - }, - }, + // "mainnet": { + // { + // txs: []BroadcastTxn{ + // InvokeTxnV0{ + // Type: TransactionType_Invoke, + // Version: TransactionV0, + // MaxFee: utils.TestHexToFelt(t, "0x95e566845d000"), + // FunctionCall: FunctionCall{ + // ContractAddress: utils.TestHexToFelt(t, "0x45e92c365ba0908382bc346159f896e528214470c60ae2cd4038a0fff747b1e"), + // EntryPointSelector: utils.TestHexToFelt(t, "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad"), + // Calldata: utils.TestHexArrToFelt(t, []string{ + // "0x1", + // "0x4a3621276a83251b557a8140e915599ae8e7b6207b067ea701635c0d509801e", + // "0x2f0b3c5710379609eb5495f1ecd348cb28167711b73609fe565a72734550354", + // "0x0", + // "0x3", + // "0x3", + // "0x697066733a2f2f516d57554c7a475135556a52616953514776717765347931", + // "0x4731796f4757324e6a5a76564e77776a66514577756a", + // "0x0", + // "0x2"}), + // }, + // Signature: []*felt.Felt{ + // utils.TestHexToFelt(t, "0x63e4618ca2e323a45b9f860f12a4f5c4984648f1d110aa393e79d596d82abcc"), + // utils.TestHexToFelt(t, "0x2844257b088ad4f49e2fe3df1ea6a8530aa2d21d8990112b7e88c4bd0ce9d50"), + // }, + // }, + // }, + // simFlags: []SimulationFlag{}, + // blockID: WithBlockNumber(15643), + // expectedError: nil, + // expectedResp: []FeeEstimation{ + // { + // GasConsumed: utils.TestHexToFelt(t, "0x3074"), + // GasPrice: utils.TestHexToFelt(t, "0x350da9915"), + // DataGasConsumed: &felt.Zero, + // DataGasPrice: new(felt.Felt).SetUint64(1), + // OverallFee: utils.TestHexToFelt(t, "0xa0a99fc14d84"), + // FeeUnit: UnitWei, + // }, + // }, + // }, + // { + // txs: []BroadcastTxn{ + // DeployAccountTxn{ + + // Type: TransactionType_DeployAccount, + // Version: TransactionV1, + // MaxFee: utils.TestHexToFelt(t, "0xdec823b1380c"), + // Nonce: utils.TestHexToFelt(t, "0x0"), + // Signature: []*felt.Felt{ + // utils.TestHexToFelt(t, "0x41dbc4b41f6506502a09eb7aea85759de02e91f49d0565776125946e54a2ec6"), + // utils.TestHexToFelt(t, "0x85dcf2bc8e3543071a6657947cc9c157a9f6ad7844a686a975b588199634a9"), + // }, + // ContractAddressSalt: utils.TestHexToFelt(t, "0x74ddc51af144d1bd805eb4184d07453d7c4388660270a7851fec387e654a50e"), + // ClassHash: utils.TestHexToFelt(t, "0x25ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918"), + // ConstructorCalldata: utils.TestHexArrToFelt(t, []string{ + // "0x33434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2", + // "0x79dc0da7c54b95f10aa182ad0a46400db63156920adb65eca2654c0945a463", + // "0x2", + // "0x74ddc51af144d1bd805eb4184d07453d7c4388660270a7851fec387e654a50e", + // "0x0", + // }), + // }, + // }, + // simFlags: []SimulationFlag{}, + // blockID: WithBlockHash(utils.TestHexToFelt(t, "0x1b0df1bafcb826b1fc053495aef5cdc24d0345cbfa1259b15939d01b89dc6d9")), + // expectedError: nil, + // expectedResp: []FeeEstimation{ + // { + // GasConsumed: utils.TestHexToFelt(t, "0x1154"), + // GasPrice: utils.TestHexToFelt(t, "0x378f962c4"), + // DataGasConsumed: &felt.Zero, + // DataGasPrice: new(felt.Felt).SetUint64(1), + // OverallFee: utils.TestHexToFelt(t, "0x3c2c41636c50"), + // FeeUnit: UnitWei, + // }, + // }, + // }, + // }, "mock": { { // without flag txs: []BroadcastTxn{ @@ -582,12 +587,14 @@ func TestEstimateFee(t *testing.T) { expectedError: nil, expectedResp: []FeeEstimation{ { - GasConsumed: utils.RANDOM_FELT, - GasPrice: utils.RANDOM_FELT, - DataGasConsumed: utils.RANDOM_FELT, - DataGasPrice: utils.RANDOM_FELT, - OverallFee: utils.RANDOM_FELT, - FeeUnit: UnitWei, + L1GasConsumed: utils.RANDOM_FELT, + L1GasPrice: utils.RANDOM_FELT, + L2GasConsumed: utils.RANDOM_FELT, + L2GasPrice: utils.RANDOM_FELT, + L1DataGasConsumed: utils.RANDOM_FELT, + L1DataGasPrice: utils.RANDOM_FELT, + OverallFee: utils.RANDOM_FELT, + FeeUnit: UnitWei, }, }, }, @@ -600,78 +607,80 @@ func TestEstimateFee(t *testing.T) { expectedError: nil, expectedResp: []FeeEstimation{ { - GasConsumed: new(felt.Felt).SetUint64(1234), - GasPrice: new(felt.Felt).SetUint64(1234), - DataGasConsumed: new(felt.Felt).SetUint64(1234), - DataGasPrice: new(felt.Felt).SetUint64(1234), - OverallFee: new(felt.Felt).SetUint64(1234), - FeeUnit: UnitWei, + L1GasConsumed: new(felt.Felt).SetUint64(1234), + L1GasPrice: new(felt.Felt).SetUint64(1234), + L2GasConsumed: new(felt.Felt).SetUint64(1234), + L2GasPrice: new(felt.Felt).SetUint64(1234), + L1DataGasConsumed: new(felt.Felt).SetUint64(1234), + L1DataGasPrice: new(felt.Felt).SetUint64(1234), + OverallFee: new(felt.Felt).SetUint64(1234), + FeeUnit: UnitWei, }, }, }, }, - "testnet": { - { // without flag - txs: []BroadcastTxn{ - bradcastInvokeV1, - }, - simFlags: []SimulationFlag{}, - blockID: WithBlockNumber(100000), - expectedError: nil, - expectedResp: []FeeEstimation{ - { - GasConsumed: utils.TestHexToFelt(t, "0x123c"), - GasPrice: utils.TestHexToFelt(t, "0x831211d3b"), - DataGasConsumed: &felt.Zero, - DataGasPrice: utils.TestHexToFelt(t, "0x1b10c"), - OverallFee: utils.TestHexToFelt(t, "0x955fd7d0ffd4"), - FeeUnit: UnitWei, - }, - }, - }, - { // with flag - txs: []BroadcastTxn{ - bradcastInvokeV1, - }, - simFlags: []SimulationFlag{SKIP_VALIDATE}, - blockID: WithBlockNumber(100000), - expectedError: nil, - expectedResp: []FeeEstimation{ - { - GasConsumed: utils.TestHexToFelt(t, "0x1239"), - GasPrice: utils.TestHexToFelt(t, "0x831211d3b"), - DataGasConsumed: &felt.Zero, - DataGasPrice: utils.TestHexToFelt(t, "0x1b10c"), - OverallFee: utils.TestHexToFelt(t, "0x9547446da823"), - FeeUnit: UnitWei, - }, - }, - }, - { // invalid transaction - txs: []BroadcastTxn{ - InvokeTxnV1{ - MaxFee: utils.RANDOM_FELT, - Type: TransactionType_Invoke, - Version: TransactionV1, - SenderAddress: utils.RANDOM_FELT, - Nonce: utils.RANDOM_FELT, - Calldata: []*felt.Felt{}, - Signature: []*felt.Felt{}, - }, - }, - simFlags: []SimulationFlag{}, - blockID: WithBlockNumber(100000), - expectedError: ErrTxnExec, - }, - { // invalid block - txs: []BroadcastTxn{ - bradcastInvokeV1, - }, - simFlags: []SimulationFlag{}, - blockID: WithBlockNumber(9999999999999999999), - expectedError: ErrBlockNotFound, - }, - }, + // "testnet": { + // { // without flag + // txs: []BroadcastTxn{ + // bradcastInvokeV1, + // }, + // simFlags: []SimulationFlag{}, + // blockID: WithBlockNumber(100000), + // expectedError: nil, + // expectedResp: []FeeEstimation{ + // { + // GasConsumed: utils.TestHexToFelt(t, "0x123c"), + // GasPrice: utils.TestHexToFelt(t, "0x831211d3b"), + // DataGasConsumed: &felt.Zero, + // DataGasPrice: utils.TestHexToFelt(t, "0x1b10c"), + // OverallFee: utils.TestHexToFelt(t, "0x955fd7d0ffd4"), + // FeeUnit: UnitWei, + // }, + // }, + // }, + // { // with flag + // txs: []BroadcastTxn{ + // bradcastInvokeV1, + // }, + // simFlags: []SimulationFlag{SKIP_VALIDATE}, + // blockID: WithBlockNumber(100000), + // expectedError: nil, + // expectedResp: []FeeEstimation{ + // { + // GasConsumed: utils.TestHexToFelt(t, "0x1239"), + // GasPrice: utils.TestHexToFelt(t, "0x831211d3b"), + // DataGasConsumed: &felt.Zero, + // DataGasPrice: utils.TestHexToFelt(t, "0x1b10c"), + // OverallFee: utils.TestHexToFelt(t, "0x9547446da823"), + // FeeUnit: UnitWei, + // }, + // }, + // }, + // { // invalid transaction + // txs: []BroadcastTxn{ + // InvokeTxnV1{ + // MaxFee: utils.RANDOM_FELT, + // Type: TransactionType_Invoke, + // Version: TransactionV1, + // SenderAddress: utils.RANDOM_FELT, + // Nonce: utils.RANDOM_FELT, + // Calldata: []*felt.Felt{}, + // Signature: []*felt.Felt{}, + // }, + // }, + // simFlags: []SimulationFlag{}, + // blockID: WithBlockNumber(100000), + // expectedError: ErrTxnExec, + // }, + // { // invalid block + // txs: []BroadcastTxn{ + // bradcastInvokeV1, + // }, + // simFlags: []SimulationFlag{}, + // blockID: WithBlockNumber(9999999999999999999), + // expectedError: ErrBlockNotFound, + // }, + // }, }[testEnv] for _, test := range testSet { diff --git a/rpc/mock_test.go b/rpc/mock_test.go index cee0a729..71d009ef 100644 --- a/rpc/mock_test.go +++ b/rpc/mock_test.go @@ -682,21 +682,25 @@ func mock_starknet_estimateFee(result interface{}, args ...interface{}) error { if len(flags) > 0 { output = FeeEstimation{ - GasConsumed: new(felt.Felt).SetUint64(1234), - GasPrice: new(felt.Felt).SetUint64(1234), - DataGasConsumed: new(felt.Felt).SetUint64(1234), - DataGasPrice: new(felt.Felt).SetUint64(1234), - OverallFee: new(felt.Felt).SetUint64(1234), - FeeUnit: UnitWei, + L1GasConsumed: new(felt.Felt).SetUint64(1234), + L1GasPrice: new(felt.Felt).SetUint64(1234), + L2GasConsumed: new(felt.Felt).SetUint64(1234), + L2GasPrice: new(felt.Felt).SetUint64(1234), + L1DataGasConsumed: new(felt.Felt).SetUint64(1234), + L1DataGasPrice: new(felt.Felt).SetUint64(1234), + OverallFee: new(felt.Felt).SetUint64(1234), + FeeUnit: UnitWei, } } else { output = FeeEstimation{ - GasConsumed: utils.RANDOM_FELT, - GasPrice: utils.RANDOM_FELT, - DataGasConsumed: utils.RANDOM_FELT, - DataGasPrice: utils.RANDOM_FELT, - OverallFee: utils.RANDOM_FELT, - FeeUnit: UnitWei, + L1GasConsumed: utils.RANDOM_FELT, + L1GasPrice: utils.RANDOM_FELT, + L2GasConsumed: utils.RANDOM_FELT, + L2GasPrice: utils.RANDOM_FELT, + L1DataGasConsumed: utils.RANDOM_FELT, + L1DataGasPrice: utils.RANDOM_FELT, + OverallFee: utils.RANDOM_FELT, + FeeUnit: UnitWei, } } @@ -738,9 +742,11 @@ func mock_starknet_estimateMessageFee(result interface{}, args ...interface{}) e } output := FeeEstimation{ - GasConsumed: new(felt.Felt).SetUint64(1), - GasPrice: new(felt.Felt).SetUint64(2), - OverallFee: new(felt.Felt).SetUint64(3), + L1GasConsumed: utils.RANDOM_FELT, + L1GasPrice: utils.RANDOM_FELT, + L2GasConsumed: utils.RANDOM_FELT, + L2GasPrice: utils.RANDOM_FELT, + OverallFee: utils.RANDOM_FELT, } outputContent, err := json.Marshal(output) if err != nil { diff --git a/rpc/types.go b/rpc/types.go index 9634ea66..a412afae 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -188,17 +188,23 @@ type TxDetails struct { } type FeeEstimation struct { - // The Ethereum gas consumption of the transaction - GasConsumed *felt.Felt `json:"gas_consumed"` + // The Ethereum gas consumption of the transaction, charged for L1->L2 messages and, depending on the block's DA_MODE, state diffs + L1GasConsumed *felt.Felt `json:"l1_gas_consumed"` // The gas price (in wei or fri, depending on the tx version) that was used in the cost estimation. - GasPrice *felt.Felt `json:"gas_price"` + L1GasPrice *felt.Felt `json:"l1_gas_price"` + + // The L2 gas consumption of the transaction + L2GasConsumed *felt.Felt `json:"l2_gas_consumed"` + + // The L2 gas price (in wei or fri, depending on the tx version) that was used in the cost estimation. + L2GasPrice *felt.Felt `json:"l2_gas_price"` // The Ethereum data gas consumption of the transaction. - DataGasConsumed *felt.Felt `json:"data_gas_consumed"` + L1DataGasConsumed *felt.Felt `json:"l1_data_gas_consumed"` // The data gas price (in wei or fri, depending on the tx version) that was used in the cost estimation. - DataGasPrice *felt.Felt `json:"data_gas_price"` + L1DataGasPrice *felt.Felt `json:"l1_data_gas_price"` // The estimated fee for the transaction (in wei or fri, depending on the tx version), equals to gas_consumed*gas_price + data_gas_consumed*data_gas_price. OverallFee *felt.Felt `json:"overall_fee"` From 7ce62aaea0b26589add0628d5c12241c9e2efc1e Mon Sep 17 00:00:00 2001 From: thiagodeev Date: Mon, 30 Sep 2024 10:08:19 -0300 Subject: [PATCH 14/17] Fixes blockTest error --- rpc/block_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/rpc/block_test.go b/rpc/block_test.go index 71f046f9..fd5e7fc5 100644 --- a/rpc/block_test.go +++ b/rpc/block_test.go @@ -655,5 +655,4 @@ func validatePendingBlockHeader(t *testing.T, pBlock *PendingBlockHeader) { require.NotZero(t, pBlock.L1GasPrice) require.NotZero(t, pBlock.StarknetVersion) require.NotZero(t, pBlock.L1DataGasPrice) - require.NotZero(t, pBlock.L1DAMode) } From 470f18ca5d97c24020a584b37585ed22e0af2b8b Mon Sep 17 00:00:00 2001 From: Thiago Ribeiro <62709592+thiagodeev@users.noreply.github.com> Date: Mon, 28 Oct 2024 07:20:01 -0300 Subject: [PATCH 15/17] Adds GetStorageProof method (#635) * implement rpcv8 GetStorageProof method --- mocks/mock_rpc_provider.go | 15 +++++ rpc/contract.go | 18 ++++++ rpc/contract_test.go | 4 ++ rpc/errors.go | 4 ++ rpc/provider.go | 1 + rpc/types_contract.go | 110 +++++++++++++++++++++++++++++++++++++ 6 files changed, 152 insertions(+) diff --git a/mocks/mock_rpc_provider.go b/mocks/mock_rpc_provider.go index 6e86bf39..a8edd76f 100644 --- a/mocks/mock_rpc_provider.go +++ b/mocks/mock_rpc_provider.go @@ -296,6 +296,21 @@ func (mr *MockRpcProviderMockRecorder) Events(ctx, input any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Events", reflect.TypeOf((*MockRpcProvider)(nil).Events), ctx, input) } +// GetStorageProof mocks base method. +func (m *MockRpcProvider) GetStorageProof(ctx context.Context, storageProofInput rpc.StorageProofInput) (*rpc.StorageProofResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetStorageProof", ctx, storageProofInput) + ret0, _ := ret[0].(*rpc.StorageProofResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetStorageProof indicates an expected call of GetStorageProof. +func (mr *MockRpcProviderMockRecorder) GetStorageProof(ctx, storageProofInput any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageProof", reflect.TypeOf((*MockRpcProvider)(nil).GetStorageProof), ctx, storageProofInput) +} + // GetTransactionStatus mocks base method. func (m *MockRpcProvider) GetTransactionStatus(ctx context.Context, transactionHash *felt.Felt) (*rpc.TxnStatusResp, error) { m.ctrl.T.Helper() diff --git a/rpc/contract.go b/rpc/contract.go index 8dcbe64e..0cf00ba7 100644 --- a/rpc/contract.go +++ b/rpc/contract.go @@ -160,3 +160,21 @@ func (provider *Provider) EstimateMessageFee(ctx context.Context, msg MsgFromL1, } return &raw, nil } + +// Get merkle paths in one of the state tries: global state, classes, individual contract. +// A single request can query for any mix of the three types of storage proofs (classes, contracts, and storage) +// +// Parameters: +// - ctx: The context of the function call +// - storageProofInput: an input containing at least one of the fields filled +// Returns: +// - *StorageProofResult: the proofs of the field passed in the input +// - error: an error if any occurred during the execution +func (provider *Provider) GetStorageProof(ctx context.Context, storageProofInput StorageProofInput) (*StorageProofResult, error) { + var raw StorageProofResult + if err := do(ctx, provider.c, "starknet_getStorageProof", &raw, storageProofInput); err != nil { + + return nil, tryUnwrapToRPCErr(err, ErrBlockNotFound, ErrStorageProofNotSupported) + } + return &raw, nil +} diff --git a/rpc/contract_test.go b/rpc/contract_test.go index 36762474..7c0a23c2 100644 --- a/rpc/contract_test.go +++ b/rpc/contract_test.go @@ -692,3 +692,7 @@ func TestEstimateFee(t *testing.T) { } } } + +func TestGetStorageProof(t *testing.T) { + t.Skip("TODO: create a test before merge") +} diff --git a/rpc/errors.go b/rpc/errors.go index 337f4d42..d0effbf6 100644 --- a/rpc/errors.go +++ b/rpc/errors.go @@ -138,6 +138,10 @@ var ( Code: 41, Message: "Transaction execution error", } + ErrStorageProofNotSupported = &RPCError{ + Code: 42, + Message: "the node doesn't support storage proofs for blocks that are too far in the past", + } ErrInvalidContractClass = &RPCError{ Code: 50, Message: "Invalid contract class", diff --git a/rpc/provider.go b/rpc/provider.go index f7a5e53a..9159e7cc 100644 --- a/rpc/provider.go +++ b/rpc/provider.go @@ -59,6 +59,7 @@ type RpcProvider interface { EstimateMessageFee(ctx context.Context, msg MsgFromL1, blockID BlockID) (*FeeEstimation, error) Events(ctx context.Context, input EventsInput) (*EventChunk, error) BlockWithReceipts(ctx context.Context, blockID BlockID) (interface{}, error) + GetStorageProof(ctx context.Context, storageProofInput StorageProofInput) (*StorageProofResult, error) GetTransactionStatus(ctx context.Context, transactionHash *felt.Felt) (*TxnStatusResp, error) Nonce(ctx context.Context, blockID BlockID, contractAddress *felt.Felt) (*felt.Felt, error) SimulateTransactions(ctx context.Context, blockID BlockID, txns []BroadcastTxn, simulationFlags []SimulationFlag) ([]SimulatedTransaction, error) diff --git a/rpc/types_contract.go b/rpc/types_contract.go index 7dc88b25..d7ea97b7 100644 --- a/rpc/types_contract.go +++ b/rpc/types_contract.go @@ -74,6 +74,79 @@ type ContractClass struct { ABI string `json:"abi,omitempty"` } +type StorageProofInput struct { + // The hash of the requested block, or number (height) of the requested block, or a block tag + BlockID BlockID `json:"block_id"` + // A list of the class hashes for which we want to prove membership in the classes trie + ClassHashes []*felt.Felt `json:"class_hashes,omitempty"` + // A list of contracts for which we want to prove membership in the global state trie + ContractAddresses []*felt.Felt `json:"contract_addresses,omitempty"` + // A list of (contract_address, storage_keys) pairs + ContractsStorageKeys []ContractStorageKeys `json:"contracts_storage_keys,omitempty"` +} + +type ContractStorageKeys struct { + ContractAddress *felt.Felt `json:"contract_address"` + StorageKeys []*felt.Felt `json:"storage_keys"` +} + +// The requested storage proofs. Note that if a requested leaf has the default value, +// the path to it may end in an edge node whose path is not a prefix of the requested leaf, +// thus effecitvely proving non-membership +type StorageProofResult struct { + ClassesProof NodeHashToNode `json:"classes_proof"` + ContractsProof ContractsProof `json:"contracts_proof"` + ContractsStorageProofs []NodeHashToNode `json:"contracts_storage_proofs"` + GlobalRoots []NodeHashToNode `json:"global_roots"` +} + +type ContractsProof struct { + // The nodes in the union of the paths from the contracts tree root to the requested leaves + Nodes NodeHashToNode `json:"nodes"` + ContractLeavesData []ContractLeavesData `json:"contract_leaves_data"` +} + +// The nonce and class hash for each requested contract address, in the order in which +// they appear in the request. These values are needed to construct the associated leaf node +type ContractLeavesData struct { + Nonce *felt.Felt `json:"nonce"` + ClassHash *felt.Felt `json:"class_hash"` +} + +type GlobalRoots struct { + ContractsTreeRoot *felt.Felt `json:"contracts_tree_root"` + ClassesTreeRoot *felt.Felt `json:"classes_tree_root"` + // the associated block hash (needed in case the caller used a block tag for the block_id parameter) + BlockHash *felt.Felt `json:"block_hash"` +} + +// A node_hash -> node mapping of all the nodes in the union of the paths between the requested leaves and the root +type NodeHashToNode struct { + NodeHash *felt.Felt `json:"node_hash"` + Node MerkleNode `json:"node"` +} + +// A node in the Merkle-Patricia tree, can be a leaf, binary node, or an edge node +type MerkleNode interface{} // it should be an EdgeNode or BinaryNode + +// Represents a path to the highest non-zero descendant node +type EdgeNode struct { + // an integer whose binary representation represents the path from the current node to its highest non-zero descendant (bounded by 2^251) + Path NumAsHex `json:"path"` + // the length of the path (bounded by 251) + Length uint `json:"length"` + // the hash of the unique non-zero maximal-height descendant node + Child *felt.Felt `json:"child"` +} + +// An internal node whose both children are non-zero +type BinaryNode struct { + // the hash of the left child + Left *felt.Felt `json:"left"` + // the hash of the right child + Right *felt.Felt `json:"right"` +} + // UnmarshalJSON unmarshals the JSON content into the DeprecatedContractClass struct. // // It takes a byte array `content` as a parameter and returns an error if there is any. @@ -168,6 +241,43 @@ func (c *DeprecatedContractClass) UnmarshalJSON(content []byte) error { return nil } +func (nodeHashToNode *NodeHashToNode) UnmarshalJSON(bytes []byte) error { + valueMap := make(map[string]any) + if err := json.Unmarshal(bytes, &valueMap); err != nil { + return err + } + + nodeHash, ok := valueMap["node_hash"] + if !ok { + return fmt.Errorf("missing 'node_hash' in json object") + } + nodeHashFelt, ok := nodeHash.(felt.Felt) + if !ok { + return fmt.Errorf("error casting 'node_hash' to felt.Felt") + } + + node, ok := valueMap["node"] + if !ok { + return fmt.Errorf("missing 'node' in json object") + } + var merkleNode MerkleNode + switch nodeT := node.(type) { + case BinaryNode: + merkleNode = nodeT + case EdgeNode: + merkleNode = nodeT + default: + return fmt.Errorf("'node' should be an EdgeNode or BinaryNode") + } + + *nodeHashToNode = NodeHashToNode{ + NodeHash: &nodeHashFelt, + Node: merkleNode, + } + + return nil +} + type SierraEntryPoint struct { // The index of the function in the program FunctionIdx int `json:"function_idx"` From 2013420af8eb8202bba30e74cfad60a2470c837c Mon Sep 17 00:00:00 2001 From: Thiago Ribeiro <62709592+thiagodeev@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:24:53 -0300 Subject: [PATCH 16/17] Adds GetMessagesStatus method (#634) * Added GetMessagesStatus method * PR comment fixes --- mocks/mock_rpc_provider.go | 15 +++++++++++++++ rpc/provider.go | 3 ++- rpc/transaction.go | 17 +++++++++++++++++ rpc/transaction_test.go | 4 ++++ rpc/types_transaction_receipt.go | 9 +++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mocks/mock_rpc_provider.go b/mocks/mock_rpc_provider.go index a8edd76f..9a62fc94 100644 --- a/mocks/mock_rpc_provider.go +++ b/mocks/mock_rpc_provider.go @@ -296,6 +296,21 @@ func (mr *MockRpcProviderMockRecorder) Events(ctx, input any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Events", reflect.TypeOf((*MockRpcProvider)(nil).Events), ctx, input) } +// GetMessagesStatus mocks base method. +func (m *MockRpcProvider) GetMessagesStatus(ctx context.Context, transactionHash rpc.NumAsHex) ([]rpc.MessageStatusResp, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMessagesStatus", ctx, transactionHash) + ret0, _ := ret[0].([]rpc.MessageStatusResp) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetMessagesStatus indicates an expected call of GetMessagesStatus. +func (mr *MockRpcProviderMockRecorder) GetMessagesStatus(ctx, transactionHash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessagesStatus", reflect.TypeOf((*MockRpcProvider)(nil).GetMessagesStatus), ctx, transactionHash) +} + // GetStorageProof mocks base method. func (m *MockRpcProvider) GetStorageProof(ctx context.Context, storageProofInput rpc.StorageProofInput) (*rpc.StorageProofResult, error) { m.ctrl.T.Helper() diff --git a/rpc/provider.go b/rpc/provider.go index 9159e7cc..36852c5a 100644 --- a/rpc/provider.go +++ b/rpc/provider.go @@ -48,6 +48,7 @@ type RpcProvider interface { BlockHashAndNumber(ctx context.Context) (*BlockHashAndNumberOutput, error) BlockNumber(ctx context.Context) (uint64, error) BlockTransactionCount(ctx context.Context, blockID BlockID) (uint64, error) + BlockWithReceipts(ctx context.Context, blockID BlockID) (interface{}, error) BlockWithTxHashes(ctx context.Context, blockID BlockID) (interface{}, error) BlockWithTxs(ctx context.Context, blockID BlockID) (interface{}, error) Call(ctx context.Context, call FunctionCall, block BlockID) ([]*felt.Felt, error) @@ -58,9 +59,9 @@ type RpcProvider interface { EstimateFee(ctx context.Context, requests []BroadcastTxn, simulationFlags []SimulationFlag, blockID BlockID) ([]FeeEstimation, error) EstimateMessageFee(ctx context.Context, msg MsgFromL1, blockID BlockID) (*FeeEstimation, error) Events(ctx context.Context, input EventsInput) (*EventChunk, error) - BlockWithReceipts(ctx context.Context, blockID BlockID) (interface{}, error) GetStorageProof(ctx context.Context, storageProofInput StorageProofInput) (*StorageProofResult, error) GetTransactionStatus(ctx context.Context, transactionHash *felt.Felt) (*TxnStatusResp, error) + GetMessagesStatus(ctx context.Context, transactionHash NumAsHex) ([]MessageStatusResp, error) Nonce(ctx context.Context, blockID BlockID, contractAddress *felt.Felt) (*felt.Felt, error) SimulateTransactions(ctx context.Context, blockID BlockID, txns []BroadcastTxn, simulationFlags []SimulationFlag) ([]SimulatedTransaction, error) StateUpdate(ctx context.Context, blockID BlockID) (*StateUpdateOutput, error) diff --git a/rpc/transaction.go b/rpc/transaction.go index 7d2743e4..32485d10 100644 --- a/rpc/transaction.go +++ b/rpc/transaction.go @@ -71,3 +71,20 @@ func (provider *Provider) GetTransactionStatus(ctx context.Context, transactionH } return &receipt, nil } + +// Given an L1 tx hash, returns the associated l1_handler tx hashes and statuses for all L1 -> L2 messages sent by the l1 transaction, ordered by the L1 tx sending order +// +// Parameters: +// - ctx: the context.Context object for cancellation and timeouts. +// - transactionHash: The hash of the L1 transaction that sent L1->L2 messages +// Returns: +// - [] MessageStatusResp: An array containing the status of the messages sent by the L1 transaction +// - error, if one arose. +func (provider *Provider) GetMessagesStatus(ctx context.Context, transactionHash NumAsHex) ([]MessageStatusResp, error) { + var response []MessageStatusResp + err := do(ctx, provider.c, "starknet_getMessagesStatus", &response, transactionHash) + if err != nil { + return nil, tryUnwrapToRPCErr(err, ErrHashNotFound) + } + return response, nil +} diff --git a/rpc/transaction_test.go b/rpc/transaction_test.go index 6fb914a2..8525cc8d 100644 --- a/rpc/transaction_test.go +++ b/rpc/transaction_test.go @@ -205,3 +205,7 @@ func TestGetTransactionStatus(t *testing.T) { require.Equal(t, *resp, test.ExpectedResp) } } + +func TestGetMessagesStatus(t *testing.T) { + t.Skip("TODO: create a test before merge") +} diff --git a/rpc/types_transaction_receipt.go b/rpc/types_transaction_receipt.go index 755734a9..969c4fbd 100644 --- a/rpc/types_transaction_receipt.go +++ b/rpc/types_transaction_receipt.go @@ -28,6 +28,15 @@ type MsgFromL1 struct { Payload []*felt.Felt `json:"payload"` } +type MessageStatusResp struct { + // The hash of a L1 handler transaction + TransactionHash *felt.Felt `json:"transaction_hash"` + // The finality status of the transaction, including the case the txn is still in the mempool or failed validation during the block construction phase + FinalityStatus TxnStatus `json:"finality_status"` + // The failure reason, only appears if finality_status is REJECTED + FailureReason string `json:"failure_reason,omitempty"` +} + type OrderedMsg struct { // The order of the message within the transaction Order int `json:"order"` From 0672059954c368a6dcf4b894ddb04b579bea21c7 Mon Sep 17 00:00:00 2001 From: Thiago Ribeiro <62709592+thiagodeev@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:26:01 -0300 Subject: [PATCH 17/17] starknet_getCompiledCasm (#642) * implement starknet_getCompiledCasm for RPCv8 --- mocks/mock_rpc_provider.go | 15 ++ rpc/errors.go | 4 + rpc/executables.go | 24 +++ rpc/executables_test.go | 7 + rpc/provider.go | 1 + rpc/types_contract.go | 4 +- rpc/types_executables.go | 362 +++++++++++++++++++++++++++++++++++++ utils/data.go | 4 +- 8 files changed, 418 insertions(+), 3 deletions(-) create mode 100644 rpc/executables.go create mode 100644 rpc/executables_test.go create mode 100644 rpc/types_executables.go diff --git a/mocks/mock_rpc_provider.go b/mocks/mock_rpc_provider.go index 9a62fc94..cbaa68f6 100644 --- a/mocks/mock_rpc_provider.go +++ b/mocks/mock_rpc_provider.go @@ -251,6 +251,21 @@ func (mr *MockRpcProviderMockRecorder) ClassHashAt(ctx, blockID, contractAddress return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClassHashAt", reflect.TypeOf((*MockRpcProvider)(nil).ClassHashAt), ctx, blockID, contractAddress) } +// CompiledCasm mocks base method. +func (m *MockRpcProvider) CompiledCasm(ctx context.Context, classHash *felt.Felt) (*rpc.CasmCompiledContractClass, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CompiledCasm", ctx, classHash) + ret0, _ := ret[0].(*rpc.CasmCompiledContractClass) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CompiledCasm indicates an expected call of CompiledCasm. +func (mr *MockRpcProviderMockRecorder) CompiledCasm(ctx, classHash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CompiledCasm", reflect.TypeOf((*MockRpcProvider)(nil).CompiledCasm), ctx, classHash) +} + // EstimateFee mocks base method. func (m *MockRpcProvider) EstimateFee(ctx context.Context, requests []rpc.BroadcastTxn, simulationFlags []rpc.SimulationFlag, blockID rpc.BlockID) ([]rpc.FeeEstimation, error) { m.ctrl.T.Helper() diff --git a/rpc/errors.go b/rpc/errors.go index d0effbf6..d8d1cb49 100644 --- a/rpc/errors.go +++ b/rpc/errors.go @@ -198,4 +198,8 @@ var ( Code: 63, Message: "An unexpected error occurred", } + ErrCompilationError = &RPCError{ + Code: 9999, //placeholder number as this error has no code so far. TODO: change this with the next updates + Message: "More data about the compilation failure", + } ) diff --git a/rpc/executables.go b/rpc/executables.go new file mode 100644 index 00000000..48fcc686 --- /dev/null +++ b/rpc/executables.go @@ -0,0 +1,24 @@ +package rpc + +import ( + "context" + + "github.com/NethermindEth/juno/core/felt" +) + +// Get the contract class definition in the given block associated with the given hash +// +// Parameters: +// - ctx: The context.Context used for the request +// - classHash: The hash of the contract class whose CASM will be returned +// Returns: +// - CasmCompiledContractClass: The compiled contract class +// - error: An error if any occurred during the execution +func (provider *Provider) CompiledCasm(ctx context.Context, classHash *felt.Felt) (*CasmCompiledContractClass, error) { + var result CasmCompiledContractClass + if err := do(ctx, provider.c, "starknet_getCompiledCasm", &result, classHash); err != nil { + + return nil, tryUnwrapToRPCErr(err, ErrClassHashNotFound, ErrCompilationError) + } + return &result, nil +} diff --git a/rpc/executables_test.go b/rpc/executables_test.go new file mode 100644 index 00000000..f09e44fc --- /dev/null +++ b/rpc/executables_test.go @@ -0,0 +1,7 @@ +package rpc + +import "testing" + +func TestCompiledCasm(t *testing.T) { + t.Skip("TODO: create a test before merge") +} diff --git a/rpc/provider.go b/rpc/provider.go index 36852c5a..f29ab549 100644 --- a/rpc/provider.go +++ b/rpc/provider.go @@ -56,6 +56,7 @@ type RpcProvider interface { Class(ctx context.Context, blockID BlockID, classHash *felt.Felt) (ClassOutput, error) ClassAt(ctx context.Context, blockID BlockID, contractAddress *felt.Felt) (ClassOutput, error) ClassHashAt(ctx context.Context, blockID BlockID, contractAddress *felt.Felt) (*felt.Felt, error) + CompiledCasm(ctx context.Context, classHash *felt.Felt) (*CasmCompiledContractClass, error) EstimateFee(ctx context.Context, requests []BroadcastTxn, simulationFlags []SimulationFlag, blockID BlockID) ([]FeeEstimation, error) EstimateMessageFee(ctx context.Context, msg MsgFromL1, blockID BlockID) (*FeeEstimation, error) Events(ctx context.Context, input EventsInput) (*EventChunk, error) diff --git a/rpc/types_contract.go b/rpc/types_contract.go index d7ea97b7..affc336c 100644 --- a/rpc/types_contract.go +++ b/rpc/types_contract.go @@ -69,7 +69,7 @@ type ContractClass struct { // The version of the contract class object. Currently, the Starknet OS supports version 0.1.0 ContractClassVersion string `json:"contract_class_version"` - EntryPointsByType EntryPointsByType `json:"entry_points_by_type"` + EntryPointsByType SierraEntryPointsByType `json:"entry_points_by_type"` ABI string `json:"abi,omitempty"` } @@ -285,7 +285,7 @@ type SierraEntryPoint struct { Selector *felt.Felt `json:"selector"` } -type EntryPointsByType struct { +type SierraEntryPointsByType struct { Constructor []SierraEntryPoint `json:"CONSTRUCTOR"` External []SierraEntryPoint `json:"EXTERNAL"` L1Handler []SierraEntryPoint `json:"L1_HANDLER"` diff --git a/rpc/types_executables.go b/rpc/types_executables.go new file mode 100644 index 00000000..b320e4f9 --- /dev/null +++ b/rpc/types_executables.go @@ -0,0 +1,362 @@ +package rpc + +import ( + "github.com/NethermindEth/juno/core/felt" +) + +type CasmCompiledContractClass struct { + EntryPointsByType CasmEntryPointsByType `json:"entry_points_by_type"` + ByteCode []*felt.Felt `json:"bytecode"` + Prime NumAsHex `json:"prime"` + CompilerVersion string `json:"compiler_version"` + Hints []Hints `json:"hints"` + // a list of sizes of segments in the bytecode, each segment is hashed invidually when computing the bytecode hash + BytecodeSegmentLengths []int `json:"bytecode_segment_lengths,omitempty"` +} + +type CasmEntryPointsByType struct { + Constructor []CasmEntryPoint `json:"CONSTRUCTOR"` + External []CasmEntryPoint `json:"EXTERNAL"` + L1Handler []CasmEntryPoint `json:"L1_HANDLER"` +} + +type CasmEntryPoint struct { + DeprecatedCairoEntryPoint + // the hash of the right child + Builtin []string `json:"builtins"` +} + +// 2-tuple of pc value and an array of hints to execute, but adapted to a golang struct +type Hints struct { + Int int + HintArr []Hint +} + +func (hints *Hints) Values() (int, []Hint) { + return hints.Int, hints.HintArr +} + +func (hints *Hints) Tuple() [2]any { + return [2]any{hints.Int, hints.HintArr} +} + +type Hint struct { + DeprecatedHint + CoreHint + StarknetHint +} + +type DeprecatedHint struct { + DeprecatedHintEnum + AssertAllAccessesUsed AssertAllAccessesUsed `json:",omitempty"` + AssertLtAssertValidInput AssertLtAssertValidInput `json:",omitempty"` + Felt252DictRead Felt252DictRead `json:",omitempty"` + Felt252DictWrite Felt252DictWrite `json:",omitempty"` +} + +type CoreHint struct { + AllocConstantSize AllocConstantSize `json:",omitempty"` + AllocFelt252Dict AllocFelt252Dict `json:",omitempty"` + AllocSegment AllocSegment `json:",omitempty"` + AssertLeFindSmallArcs AssertLeFindSmallArcs `json:",omitempty"` + AssertLeIsFirstArcExcluded AssertLeIsFirstArcExcluded `json:",omitempty"` + AssertLeIsSecondArcExcluded AssertLeIsSecondArcExcluded `json:",omitempty"` + DebugPrint DebugPrint `json:",omitempty"` + DivMod DivMod `json:",omitempty"` + EvalCircuit EvalCircuit `json:",omitempty"` + Felt252DictEntryInit Felt252DictEntryInit `json:",omitempty"` + Felt252DictEntryUpdate Felt252DictEntryUpdate `json:",omitempty"` + FieldSqrt FieldSqrt `json:",omitempty"` + GetCurrentAccessDelta GetCurrentAccessDelta `json:",omitempty"` + GetCurrentAccessIndex GetCurrentAccessIndex `json:",omitempty"` + GetNextDictKey GetNextDictKey `json:",omitempty"` + GetSegmentArenaIndex GetSegmentArenaIndex `json:",omitempty"` + InitSquashData InitSquashData `json:",omitempty"` + LinearSplit LinearSplit `json:",omitempty"` + RandomEcPoint RandomEcPoint `json:",omitempty"` + ShouldContinueSquashLoop ShouldContinueSquashLoop `json:",omitempty"` + ShouldSkipSquashLoop ShouldSkipSquashLoop `json:",omitempty"` + SquareRoot SquareRoot `json:",omitempty"` + TestLessThan TestLessThan `json:",omitempty"` + TestLessThanOrEqual TestLessThanOrEqual `json:",omitempty"` + TestLessThanOrEqualAddress TestLessThanOrEqualAddress `json:",omitempty"` + U256InvModN U256InvModN `json:",omitempty"` + Uint256DivMod Uint256DivMod `json:",omitempty"` + Uint256SquareRoot Uint256SquareRoot `json:",omitempty"` + Uint512DivModByUint256 Uint512DivModByUint256 `json:",omitempty"` + WideMul128 WideMul128 `json:",omitempty"` +} + +type StarknetHint struct { + Cheatcode Cheatcode `json:",omitempty"` + SystemCall SystemCall `json:",omitempty"` +} + +type DeprecatedHintEnum string + +const ( + AssertCurrentAccessIndicesIsEmpty DeprecatedHintEnum = "AssertCurrentAccessIndicesIsEmpty" + AssertAllKeysUsed DeprecatedHintEnum = "AssertAllKeysUsed" + AssertLeAssertThirdArcExcluded DeprecatedHintEnum = "AssertLeAssertThirdArcExcluded" +) + +type AssertAllAccessesUsed struct { + NotUsedAccesses CellRef `json:"n_used_accesses"` +} + +type CellRef struct { + Register Register `json:"register"` + Offset int `json:"offset"` +} + +type Register string + +const ( + AP Register = "AP" + FP Register = "FP" +) + +type AssertLtAssertValidInput struct { + A ResOperand `json:"a"` + B ResOperand `json:"b"` +} + +type felt252Dict struct { + DictPtr ResOperand `json:"dict_ptr"` + Key ResOperand `json:"key"` +} + +type Felt252DictRead struct { + felt252Dict + ValueDst CellRef `json:"value_dst"` +} + +type Felt252DictWrite struct { + felt252Dict + Value ResOperand `json:"value"` +} + +type Felt252DictEntryInit felt252Dict + +type Felt252DictEntryUpdate struct { + DictPtr ResOperand `json:"dict_ptr"` + Value ResOperand `json:"value"` +} + +type ResOperand struct { + BinOp BinOp `json:",omitempty"` + Deref Deref `json:",omitempty"` + DoubleDeref DoubleDeref `json:",omitempty"` + Immediate Immediate `json:",omitempty"` +} + +type Deref CellRef + +// A (CellRef, offsest) tuple, but adapted to a golang struct +type DoubleDeref struct { + CellRef CellRef + Offset int +} + +func (dd *DoubleDeref) Values() (CellRef, int) { + return dd.CellRef, dd.Offset +} + +func (dd *DoubleDeref) Tuple() [2]any { + return [2]any{dd.CellRef, dd.Offset} +} + +type Immediate NumAsHex + +type Operation string + +const ( + Add Operation = "Add" + Mul Operation = "Mul" +) + +type BinOp struct { + Operation Operation `json:"op"` + A CellRef `json:"a"` + B B `json:"b"` +} + +type B struct { + Deref Deref `json:",omitempty"` + Immediate Immediate `json:",omitempty"` +} + +type AllocSegment struct { + Dst CellRef `json:"dst"` +} + +type baseLhsRhs struct { + Lhs ResOperand `json:"lhs"` + Rhs ResOperand `json:"rhs"` +} + +type TestLessThan struct { + baseLhsRhs + Dst CellRef `json:"dst"` +} + +type TestLessThanOrEqual TestLessThan + +type TestLessThanOrEqualAddress TestLessThan + +type WideMul128 struct { + baseLhsRhs + High CellRef `json:"high"` + Low CellRef `json:"low"` +} + +type DivMod struct { + baseLhsRhs + Quotient CellRef `json:"quotient"` + Remainder CellRef `json:"remainder"` +} + +type Uint256DivMod struct { + Dividend0 ResOperand `json:"dividend0"` + Dividend1 ResOperand `json:"dividend1"` + Divisor0 ResOperand `json:"divisor0"` + Divisor1 ResOperand `json:"divisor1"` + Quotient0 CellRef `json:"quotient0"` + Quotient1 CellRef `json:"quotient1"` + Remainder0 CellRef `json:"remainder0"` + Remainder1 CellRef `json:"remainder1"` +} + +type Uint512DivModByUint256 struct { + Uint256DivMod + Dividend2 ResOperand `json:"dividend2"` + Dividend3 ResOperand `json:"dividend3"` + Quotient2 CellRef `json:"quotient2"` + Quotient3 CellRef `json:"quotient3"` +} + +type SquareRoot struct { + Value ResOperand `json:"value"` + Dst CellRef `json:"dst"` +} + +type Uint256SquareRoot struct { + ValueLow ResOperand `json:"value_low"` + ValueHigh ResOperand `json:"value_high"` + Sqrt0 CellRef `json:"sqrt0"` + Sqrt1 CellRef `json:"sqrt1"` + RemainderLow CellRef `json:"remainder_low"` + RemainderHigh CellRef `json:"remainder_high"` + SqrtMul2MinusRemainderGeU128 CellRef `json:"sqrt_mul_2_minus_remainder_ge_u128"` +} + +type LinearSplit struct { + Value ResOperand `json:"value"` + Scalar ResOperand `json:"scalar"` + MaxX ResOperand `json:"max_x"` + X CellRef `json:"x"` + Y CellRef `json:"y"` +} + +type AllocFelt252Dict struct { + SegmentArenaPtr ResOperand `json:"segment_arena_ptr"` +} + +type GetSegmentArenaIndex struct { + DictEndPtr ResOperand `json:"dict_end_ptr"` + DictIndex CellRef `json:"dict_index"` +} + +type InitSquashData struct { + DictAccess ResOperand `json:"dict_access"` + PtrDiff ResOperand `json:"ptr_diff"` + NAccesses ResOperand `json:"n_accesses"` + BigKeys CellRef `json:"big_keys"` + FirstKeys CellRef `json:"first_key"` +} + +type GetCurrentAccessIndex struct { + RangeCheckPtr ResOperand `json:"range_check_ptr"` +} + +type GetCurrentAccessDelta struct { + IndexDeltaMinus1 CellRef `json:"index_delta_minus1"` +} + +type GetNextDictKey struct { + NextKey CellRef `json:"next_key"` +} + +type ShouldSkipSquashLoop struct { + ShouldSkipLoop CellRef `json:"should_skip_loop"` +} + +type ShouldContinueSquashLoop struct { + ShouldContinue CellRef `json:"should_continue"` +} + +type AssertLeFindSmallArcs struct { + RangeCheckPtr ResOperand `json:"range_check_ptr"` + A ResOperand `json:"a"` + B ResOperand `json:"b"` +} + +type AssertLeIsFirstArcExcluded struct { + SkipExcludeAFlag CellRef `json:"skip_exclude_a_flag"` +} + +type AssertLeIsSecondArcExcluded struct { + SkipExcludeBMinusA CellRef `json:"skip_exclude_b_minus_a"` +} + +type RandomEcPoint struct { + X CellRef `json:"x"` + Y CellRef `json:"y"` +} + +type FieldSqrt struct { + Val ResOperand `json:"val"` + Sqrt CellRef `json:"sqrt"` +} + +type DebugPrint struct { + Start ResOperand `json:"start"` + End ResOperand `json:"end"` +} + +type AllocConstantSize struct { + Size ResOperand `json:"size"` + Dst CellRef `json:"dst"` +} + +type U256InvModN struct { + B0 ResOperand `json:"b0"` + B1 ResOperand `json:"b1"` + N0 ResOperand `json:"n0"` + N1 ResOperand `json:"n1"` + G0OrNoInv CellRef `json:"g0_or_no_inv"` + G1Option CellRef `json:"g1_option"` + SOrR0 CellRef `json:"s_or_r0"` + SOrR1 CellRef `json:"s_or_r1"` + TOrR0 CellRef `json:"t_or_k0"` + TOrR1 CellRef `json:"t_or_k1"` +} + +type EvalCircuit struct { + NAddMods ResOperand `json:"n_add_mods"` + AddModBuiltin ResOperand `json:"add_mod_builtin"` + NMulMods ResOperand `json:"n_mul_mods"` + MulModBuiltin ResOperand `json:"mul_mod_builtin"` +} + +type SystemCall struct { + System ResOperand `json:"system"` +} + +type Cheatcode struct { + Selector NumAsHex `json:"selector"` + InputStart ResOperand `json:"input_start"` + InputEnd ResOperand `json:"input_end"` + OutputStart CellRef `json:"output_start"` + OutputEnd CellRef `json:"output_end"` +} diff --git a/utils/data.go b/utils/data.go index ce5d2098..2f94bcef 100644 --- a/utils/data.go +++ b/utils/data.go @@ -1,6 +1,8 @@ package utils -import "encoding/json" +import ( + "encoding/json" +) func UnwrapJSON(data map[string]interface{}, tag string) (map[string]interface{}, error) { if data[tag] != nil {