Skip to content

Commit

Permalink
Merge branch 'main' into v0.8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
thiagodeev authored Dec 18, 2024
2 parents 9007483 + 8ecf779 commit 4ca79eb
Show file tree
Hide file tree
Showing 37 changed files with 12,458 additions and 10,709 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/dependency_review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: 'Dependency Review'
on: [pull_request]

permissions:
contents: read

jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 #v4.2.0
- name: 'Dependency Review'
uses: actions/dependency-review-action@4081bf99e2866ebe428fc0477b69eb4fcda7220a #v4.4.0
with:
fail-on-severity: high
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ rpc*/.env.testnet

tmp/

examples/**/*.json
examples/**/*.sum

*/**/*abi.json
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ operations on the wallets. The package has excellent documentation for a smooth
- [deploy account example](./examples/deployAccount) to deploy a new account contract on testnet.
- [invoke transaction example](./examples/simpleInvoke) to add a new invoke transaction on testnet.
- [deploy contract UDC example](./examples/deployContractUDC) to deploy an ERC20 token using [UDC (Universal Deployer Contract)](https://docs.starknet.io/architecture-and-concepts/accounts/universal-deployer/) on testnet.
- [typed data example](./examples/typedData) to sign and verify a typed data.

### Run Examples

Expand Down
56 changes: 26 additions & 30 deletions account/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ type AccountInterface interface {
}

var _ AccountInterface = &Account{}
var _ rpc.RpcProvider = &Account{}

type Account struct {
provider rpc.RpcProvider
Expand Down Expand Up @@ -513,40 +512,37 @@ func (account *Account) WaitForTransactionReceipt(ctx context.Context, transacti
}
}

// AddInvokeTransaction generates an invoke transaction and adds it to the account's provider.
// 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.
// - invokeTx: the invoke transaction to be added.
// - txn: the Broadcast Transaction to be sent.
// Returns:
// - *rpc.AddInvokeTransactionResponse: The response for the AddInvokeTransactionResponse
// - *rpc.TransactionResponse: the transaction response.
// - 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 (account *Account) SendTransaction(ctx context.Context, txn rpc.BroadcastTxn) (*rpc.TransactionResponse, error) {
switch tx := txn.(type) {
case rpc.BroadcastInvokeTxnType:
resp, err := account.provider.AddInvokeTransaction(ctx, tx)
if err != nil {
return nil, err
}
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.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.TransactionResponse{TransactionHash: resp.TransactionHash, ContractAddress: resp.ContractAddress}, nil
default:
return nil, errors.New("unsupported transaction type")
}
}

// BlockHashAndNumber returns the block hash and number for the account.
Expand Down
12 changes: 6 additions & 6 deletions account/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -526,7 +526,7 @@ 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.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)
Expand All @@ -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")
}
Expand Down Expand Up @@ -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.AddDeployAccountTransaction(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, "AddDeployAccountTransaction resp not nil")
}
Expand Down Expand Up @@ -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")
}
Expand Down Expand Up @@ -1174,7 +1174,7 @@ func TestAddDeclareTxn(t *testing.T) {
ContractClass: class,
}

resp, err := acnt.AddDeclareTransaction(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")
Expand Down
62 changes: 60 additions & 2 deletions curve/curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,19 @@ func Pedersen(a, b *felt.Felt) *felt.Felt {
return junoCrypto.Pedersen(a, b)
}

// Poseidon is a function that implements the Poseidon hash.
// NOTE: This function just wraps the Juno implementation
// (ref: https://github.com/NethermindEth/juno/blob/32fd743c774ec11a1bb2ce3dceecb57515f4873e/core/crypto/poseidon_hash.go#L59)
//
// Parameters:
// - a: a pointers to felt.Felt to be hashed.
// - b: a pointers to felt.Felt to be hashed.
// Returns:
// - *felt.Felt: a pointer to a felt.Felt storing the resulting hash.
func Poseidon(a, b *felt.Felt) *felt.Felt {
return junoCrypto.Poseidon(a, b)
}

// PedersenArray is a function that takes a variadic number of felt.Felt pointers as parameters and
// calls the PedersenArray function from the junoCrypto package with the provided parameters.
// NOTE: This function just wraps the Juno implementation
Expand All @@ -590,7 +603,7 @@ func PedersenArray(felts ...*felt.Felt) *felt.Felt {
// - felts: A variadic number of pointers to felt.Felt
// Returns:
// - *felt.Felt: pointer to a felt.Felt
func (sc StarkCurve) PoseidonArray(felts ...*felt.Felt) *felt.Felt {
func PoseidonArray(felts ...*felt.Felt) *felt.Felt {
return junoCrypto.PoseidonArray(felts...)
}

Expand All @@ -603,7 +616,7 @@ func (sc StarkCurve) PoseidonArray(felts ...*felt.Felt) *felt.Felt {
// Returns:
// - *felt.Felt: pointer to a felt.Felt
// - error: An error if any
func (sc StarkCurve) StarknetKeccak(b []byte) *felt.Felt {
func StarknetKeccak(b []byte) *felt.Felt {
return junoCrypto.StarknetKeccak(b)
}

Expand Down Expand Up @@ -709,3 +722,48 @@ func (sc StarkCurve) PrivateToPoint(privKey *big.Int) (x, y *big.Int, err error)
x, y = sc.EcMult(privKey, sc.EcGenX, sc.EcGenY)
return x, y, nil
}

// VerifySignature verifies the ECDSA signature of a given message hash using the provided public key.
//
// It takes the message hash, the r and s values of the signature, and the public key as strings and
// verifies the signature using the public key.
//
// Parameters:
// - msgHash: The hash of the message to be verified as a string
// - r: The r value (the first part) of the signature as a string
// - s: The s value (the second part) of the signature as a string
// - pubKey: The public key (only the x coordinate) as a string
// Return values:
// - bool: A boolean indicating whether the signature is valid
// - error: An error if any occurred during the verification process
func VerifySignature(msgHash, r, s, pubKey string) bool {
feltMsgHash, err := new(felt.Felt).SetString(msgHash)
if err != nil {
return false
}
feltR, err := new(felt.Felt).SetString(r)
if err != nil {
return false
}
feltS, err := new(felt.Felt).SetString(s)
if err != nil {
return false
}
pubKeyFelt, err := new(felt.Felt).SetString(pubKey)
if err != nil {
return false
}

signature := junoCrypto.Signature{
R: *feltR,
S: *feltS,
}

pubKeyStruct := junoCrypto.NewPublicKey(pubKeyFelt)
resp, err := pubKeyStruct.Verify(&signature, feltMsgHash)
if err != nil {
return false
}

return resp
}
25 changes: 25 additions & 0 deletions curve/curve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,28 @@ func TestGeneral_SplitFactStr(t *testing.T) {
require.Equal(t, d["h"], h)
}
}

// TestGeneral_VerifySignature is a test function that verifies the correctness of the VerifySignature function.
//
// It checks if the signature of a given message hash is valid using the provided r, s values and the public key.
// The function takes no parameters and returns no values.
//
// Parameters:
// - t: The testing.T object for running the test
// Returns:
//
// none
func TestGeneral_VerifySignature(t *testing.T) {
// values verified with starknet.js

msgHash := "0x2789daed76c8b750d5a609a706481034db9dc8b63ae01f505d21e75a8fc2336"
r := "0x13e4e383af407f7ccc1f13195ff31a58cad97bbc6cf1d532798b8af616999d4"
s := "0x44dd06cf67b2ba7ea4af346d80b0b439e02a0b5893c6e4dfda9ee204211c879"
fullPubKey := "0x6c7c4408e178b2999cef9a5b3fa2a3dffc876892ad6a6bd19d1451a2256906c"

require.True(t, VerifySignature(msgHash, r, s, fullPubKey))

// Change the last digit of the message hash to test invalid signature
wrongMsgHash := "0x2789daed76c8b750d5a609a706481034db9dc8b63ae01f505d21e75a8fc2337"
require.False(t, VerifySignature(wrongMsgHash, r, s, fullPubKey))
}
2 changes: 2 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ To run an example:
R: See [simpleCall](./simpleCall/main.go).
1. How to make a function call?
R: See [simpleCall](./simpleCall/main.go).
1. How to sign and verify a typed data?
R: See [typedData](./typedData/main.go).

2 changes: 1 addition & 1 deletion examples/deployAccount/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ 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: ")
setup.PanicRPC(err)
Expand Down
2 changes: 1 addition & 1 deletion examples/deployContractUDC/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.SendTransaction(context.Background(), InvokeTx)
if err != nil {
setup.PanicRPC(err)
}
Expand Down
2 changes: 1 addition & 1 deletion examples/simpleInvoke/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.SendTransaction(context.Background(), InvokeTx)
if err != nil {
setup.PanicRPC(err)
}
Expand Down
12 changes: 12 additions & 0 deletions examples/typedData/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
This example shows how to sign and verify a typed data.

Steps:
1. Rename the ".env.template" file located at the root of the "examples" folder to ".env"
1. Uncomment, and assign your Sepolia testnet endpoint to the `RPC_PROVIDER_URL` variable in the ".env" file
1. Uncomment, and assign your account address to the `ACCOUNT_ADDRESS` variable in the ".env" file (make sure to have a few ETH in it)
1. Uncomment, and assign your starknet public key to the `PUBLIC_KEY` variable in the ".env" file
1. Uncomment, and assign your private key to the `PRIVATE_KEY` variable in the ".env" file
1. Make sure you are in the "typedData" directory
1. Execute `go run main.go`

The message hash, signature and the verification result will be printed at the end of the execution.
35 changes: 35 additions & 0 deletions examples/typedData/baseExample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"types": {
"StarkNetDomain": [
{ "name": "name", "type": "felt" },
{ "name": "version", "type": "felt" },
{ "name": "chainId", "type": "felt" }
],
"Person": [
{ "name": "name", "type": "felt" },
{ "name": "wallet", "type": "felt" }
],
"Mail": [
{ "name": "from", "type": "Person" },
{ "name": "to", "type": "Person" },
{ "name": "contents", "type": "felt" }
]
},
"primaryType": "Mail",
"domain": {
"name": "StarkNet Mail",
"version": "1",
"chainId": 1
},
"message": {
"from": {
"name": "Cow",
"wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
},
"to": {
"name": "Bob",
"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
},
"contents": "Hello, Bob!"
}
}
Loading

0 comments on commit 4ca79eb

Please sign in to comment.