Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code comments (issue #303). #415

Merged
merged 18 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
363 changes: 354 additions & 9 deletions account/account.go

Large diffs are not rendered by default.

173 changes: 173 additions & 0 deletions account/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ var (
)

// TestMain is used to trigger the tests and, in that case, check for the environment to use.
//
// It sets up the test environment by parsing command line flags and loading environment variables.
// The test environment can be set using the "env" flag.
// It then sets the base path for integration tests by reading the value from the "INTEGRATION_BASE" environment variable.
// If the base path is not set and the test environment is not "mock", it panics.
// Finally, it exits with the return value of the test suite
//
// Parameters:
// - m: is the test main
// Returns:
// none
func TestMain(m *testing.M) {
flag.StringVar(&testEnv, "env", "mock", "set the test environment")
flag.Parse()
Expand All @@ -42,6 +53,18 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}

// TestTransactionHashInvoke tests the TransactionHashInvoke function.
//
// This function tests the TransactionHashInvoke method of the Account struct.
// It generates a set of test cases and iterates over them to verify the correctness
// of the transaction hash. Each test case consists of the expected hash, a flag
// indicating whether the KeyStore should be set, account address, public key,
// private key, chain ID, function call, and transaction details.
//
// Parameters:
// - t: The testing.T object for running the test
// Returns:
// none
func TestTransactionHashInvoke(t *testing.T) {
mockCtrl := gomock.NewController(t)
t.Cleanup(mockCtrl.Finish)
Expand Down Expand Up @@ -157,6 +180,15 @@ func TestTransactionHashInvoke(t *testing.T) {

}

// TestFmtCallData tests the FmtCallData function.
//
// It tests the FmtCallData function by providing different test sets
// and comparing the output with the expected call data.
//
// Parameters:
// - t: The testing.T instance for running the test
// Return:
// none
func TestFmtCallData(t *testing.T) {
mockCtrl := gomock.NewController(t)
t.Cleanup(mockCtrl.Finish)
Expand Down Expand Up @@ -209,6 +241,19 @@ func TestFmtCallData(t *testing.T) {
}
}

// TestChainIdMOCK is a test function that tests the behavior of the ChainId function.
//
// It creates a mock controller and a mock RpcProvider. It defines a test set
// consisting of different ChainID and ExpectedID pairs. It then iterates over
// the test set and sets the expected behavior for the ChainID method of the
// mockRpcProvider. It creates a new account using the mockRpcProvider,
// Zero value, "pubkey", and a new in-memory keystore. It asserts that the
// account's ChainId matches the expected ID for each test case in the test set.
//
// Parameters:
// - t: The testing.T instance for running the test
// Return:
// none
func TestChainIdMOCK(t *testing.T) {
mockCtrl := gomock.NewController(t)
t.Cleanup(mockCtrl.Finish)
Expand Down Expand Up @@ -242,6 +287,16 @@ func TestChainIdMOCK(t *testing.T) {
}
}

// TestChainId tests the ChainId function.
//
// This function tests the ChainId function by setting up a mock controller, defining a test set,
// and running a series of assertions on the expected results.
// It checks if the ChainId function returns the correct ChainID and ExpectedID values
// for different test environments.
// Parameters:
// - t: The testing.T instance for running the test
// Return:
// none
func TestChainId(t *testing.T) {
mockCtrl := gomock.NewController(t)
t.Cleanup(mockCtrl.Finish)
Expand Down Expand Up @@ -274,6 +329,22 @@ func TestChainId(t *testing.T) {

}

// TestSignMOCK is a test function that tests the Sign method of the Account struct using mock objects.
//
// It sets up a mock controller and a mock RPC provider, and defines a test set containing different scenarios.
// Each scenario includes an address, private key, chain ID, a felt to sign, and the expected signatures.
// The function iterates over the test set and performs the following steps for each test case:
// - Converts the private key to a big.Int object and stores it in a memory keystore.
// - Mocks the ChainID method of the RPC provider to return the specified chain ID.
// - Creates an account using the mock RPC provider, the test address, the address string, and the keystore.
// - Converts the felt to sign to a big.Int object.
// - Calls the Sign method of the account with the felt to sign and retrieves the signature.
// - Verifies that the obtained signature matches the expected signature.
//
// Parameters:
// - t: The testing.T instance for running the test
// Returns:
// none
func TestSignMOCK(t *testing.T) {
mockCtrl := gomock.NewController(t)
t.Cleanup(mockCtrl.Finish)
Expand Down Expand Up @@ -325,6 +396,15 @@ func TestSignMOCK(t *testing.T) {

}

// TestAddInvoke is a test function that verifies the behavior of the AddInvokeTransaction method.
//
// This function tests the AddInvokeTransaction method by setting up test data and invoking the method with different test sets.
// It asserts that the expected hash and error values are returned for each test set.
//
// Parameters:
// - t: The testing.T instance for running the test
// Returns:
// none
func TestAddInvoke(t *testing.T) {

type testSetType struct {
Expand Down Expand Up @@ -490,6 +570,21 @@ func TestAddInvoke(t *testing.T) {
}
}

// TestAddDeployAccountDevnet tests the functionality of adding a deploy account in the devnet environment.
//
// The test checks if the environment is set to "devnet" and skips the test if not. It then initializes a new RPC client
// and provider using the base URL. After that, it sets up a devnet environment and creates a fake user account. The
// fake user's address and public key are converted to the appropriate format. The test also sets up a memory keystore
// and puts the fake user's public key and private key in it. Then, it creates a new account using the provider, fake
// user's address, public key, and keystore. Next, it converts a class hash to the appropriate format. The test
// constructs a deploy account transaction and precomputes the address. It then signs the transaction and mints coins to
// the precomputed address. Finally, it adds the deploy account transaction and verifies that no errors occurred and the
// response is not nil.
//
// Parameters:
// - t: is the testing framework
// Returns:
// none
func TestAddDeployAccountDevnet(t *testing.T) {
if testEnv != "devnet" {
t.Skip("Skipping test as it requires a devnet environment")
Expand Down Expand Up @@ -538,6 +633,16 @@ func TestAddDeployAccountDevnet(t *testing.T) {
require.NotNil(t, resp, "AddDeployAccountTransaction resp not nil")
}

// TestTransactionHashDeployAccountTestnet tests the TransactionHashDeployAccount function when using the testnet environment.
//
// It creates a client and provider, initializes the required addresses and keys, and sets up the transaction parameters.
// It then precomputes the address and calculates the hash of the transaction.
// Finally, it verifies that the calculated hash matches the expected hash.
//
// Parameters:
// - t: is the testing framework
// Returns:
// none
func TestTransactionHashDeployAccountTestnet(t *testing.T) {

if testEnv != "testnet" {
Expand Down Expand Up @@ -587,6 +692,24 @@ func TestTransactionHashDeployAccountTestnet(t *testing.T) {
require.Equal(t, hash.String(), ExpectedHash.String(), "Error with calulcating TransactionHashDeployAccount")
}

// TestTransactionHashDeclare tests the TransactionHashDeclare function.
//
// This function verifies that the TransactionHashDeclare function returns the
// expected hash value for a given transaction.
// The function requires a testnet environment to run.
// It creates a new client using the provided base URL and verifies that no
// error occurs.
// It then creates a new account using the provider and verifies that no error
// occurs.
// It constructs a DeclareTxnV2 struct with test hex values for the nonce,
// max fee, signature, sender address, compiled class hash, and class hash.
// Finally, it calls the TransactionHashDeclare function and compares the
// returned hash with the expected hash, ensuring they match.
//
// Parameters:
// - t: reference to the testing.T object
// Returns:
// none
func TestTransactionHashDeclare(t *testing.T) {
// https://goerli.voyager.online/tx/0x4e0519272438a3ae0d0fca776136e2bb6fcd5d3b2af47e53575c5874ccfce92
if testEnv != "testnet" {
Expand Down Expand Up @@ -617,6 +740,18 @@ func TestTransactionHashDeclare(t *testing.T) {
require.Equal(t, expectedHash.String(), hash.String(), "TransactionHashDeclare not what expected")
}

// TestWaitForTransactionReceiptMOCK is a unit test for the WaitForTransactionReceipt function.
//
// It tests the functionality of WaitForTransactionReceipt by mocking the RpcProvider and simulating different test scenarios.
// It creates a test set with different parameters and expectations, and iterates over the test set to run the test cases.
// For each test case, it sets up the necessary mocks, creates a context with a timeout, and calls the WaitForTransactionReceipt function.
// It then asserts the expected result against the actual result.
// The function uses the testify package for assertions and the gomock package for creating mocks.
//
// Parameters:
// - t: The testing.T object for test assertions and logging
// Returns:
// none
func TestWaitForTransactionReceiptMOCK(t *testing.T) {
mockCtrl := gomock.NewController(t)
t.Cleanup(mockCtrl.Finish)
Expand Down Expand Up @@ -679,6 +814,26 @@ func TestWaitForTransactionReceiptMOCK(t *testing.T) {
}
}

// TestWaitForTransactionReceipt is a test function that tests the WaitForTransactionReceipt method.
//
// It checks if the test environment is "devnet" and skips the test if it's not.
// It creates a new RPC client using the base URL and "/rpc" endpoint.
// It creates a new RPC provider using the client.
// It creates a new account using the provider, a zero-value Felt object, the "pubkey" string, and a new memory keystore.
// It defines a testSet variable that contains an array of testSetType structs.
// Each testSetType struct contains a Timeout integer, a Hash object, an ExpectedErr error, and an ExpectedReceipt TransactionReceipt object.
// It retrieves the testSet based on the testEnv variable.
// It iterates over each test in the testSet.
// For each test, it creates a new context with a timeout based on the test's Timeout value.
// It calls the WaitForTransactionReceipt method on the account object, passing the context, the test's Hash value, and a 1-second timeout.
// If the test's ExpectedErr is not nil, it asserts that the returned error matches the test's ExpectedErr error.
// Otherwise, it asserts that the ExecutionStatus of the returned receipt matches the ExecutionStatus of the test's ExpectedReceipt.
// It then cleans up the test environment.
//
// Parameters:
// - t: The testing.T instance for running the test
// Returns:
// none
func TestWaitForTransactionReceipt(t *testing.T) {
if testEnv != "devnet" {
t.Skip("Skipping test as it requires a devnet environment")
Expand Down Expand Up @@ -721,6 +876,15 @@ func TestWaitForTransactionReceipt(t *testing.T) {
}
}

// TestAddDeclareTxn is a test function that verifies the behavior of the AddDeclareTransaction method.
//
// This function tests the AddDeclareTransaction method by setting up test data and invoking the method with different test sets.
// It asserts that the expected hash and error values are returned for each test set.
//
// Parameters:
// - t: The testing.T instance for running the test
// Returns:
// none
func TestAddDeclareTxn(t *testing.T) {
// https://goerli.voyager.online/tx/0x76af2faec46130ffad1ab2f615ad16b30afcf49cfbd09f655a26e545b03a21d
if testEnv != "testnet" {
Expand Down Expand Up @@ -791,6 +955,15 @@ func TestAddDeclareTxn(t *testing.T) {
}
}

// newDevnet creates a new devnet with the given URL.
//
// Parameters:
// - t: The testing.T instance for running the test
// - url: The URL of the devnet to be created
// Returns:
// - *devnet.DevNet: a pointer to a devnet object
// - []devnet.TestAccount: a slice of test accounts
// - error: an error, if any
func newDevnet(t *testing.T, url string) (*devnet.DevNet, []devnet.TestAccount, error) {
devnet := devnet.NewDevNet(url)
acnts, err := devnet.Accounts()
Expand Down
56 changes: 54 additions & 2 deletions account/keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,36 @@ type MemKeystore struct {
keys map[string]*big.Int
}

// NewMemKeystore initializes and returns a new instance of MemKeystore.
//
// Parameters:
// none
// Returns:
// - *MemKeystore: a pointer to MemKeystore.
func NewMemKeystore() *MemKeystore {
return &MemKeystore{
keys: make(map[string]*big.Int),
}
}

// SetNewMemKeystore returns a new instance of MemKeystore and sets the given public key and private key in it.
//
// Parameters:
// - pub: a string representing the public key
// - priv: a pointer to a big.Int representing the private key
// Returns:
// - *MemKeystore: a pointer to the newly created MemKeystore instance
func SetNewMemKeystore(pub string, priv *big.Int) *MemKeystore {
ks := NewMemKeystore()
ks.Put(pub, priv)
return ks
}

// Put stores the given key in the keystore for the specified sender address.
//
// Parameters:
// - senderAddress: the address of the sender
// - k: the key to be stored
func (ks *MemKeystore) Put(senderAddress string, k *big.Int) {
ks.mu.Lock()
defer ks.mu.Unlock()
Expand All @@ -43,6 +61,13 @@ func (ks *MemKeystore) Put(senderAddress string, k *big.Int) {

var ErrSenderNoExist = errors.New("sender does not exist")

// Get retrieves the value associated with the senderAddress from the MemKeystore.
//
// Parameter:
// - senderAddress: The address of the sender
// Returns:
// - *big.Int: The value associated with the senderAddress
// - error: An error if the senderAddress does not exist in the keystore
func (ks *MemKeystore) Get(senderAddress string) (*big.Int, error) {
ks.mu.Lock()
defer ks.mu.Unlock()
Expand All @@ -53,6 +78,16 @@ func (ks *MemKeystore) Get(senderAddress string) (*big.Int, error) {
return k, nil
}

// Sign signs a message hash using the given key in the MemKeystore.
//
// Parameters:
// - ctx: the context of the operation.
// - id: is the identifier of the key.
// - msgHash: is the message hash to be signed.
// Returns:
// - *big.Int: the R component of the signature as *big.Int
// - *big.Int: the S component of the signature as *big.Int
// - error: an error if any
func (ks *MemKeystore) Sign(ctx context.Context, id string, msgHash *big.Int) (*big.Int, *big.Int, error) {

k, err := ks.Get(id)
Expand All @@ -63,7 +98,17 @@ func (ks *MemKeystore) Sign(ctx context.Context, id string, msgHash *big.Int) (*
return sign(ctx, msgHash, k)
}

// sign illustrates one way to handle context cancellation
// sign signs the given message hash with the provided key using the Curve.
// illustrates one way to handle context cancellation
//
// Parameters:
// - ctx: the context.Context object for cancellation and timeouts
// - msgHash: the message hash to be signed as a *big.Int
// - key: the private key as a *big.Int
// Returns:
// - x: the X coordinate of the signature point as a *big.Int
// - y: the Y coordinate of the signature point as a *big.Int
// - err: an error object if any error occurred during the signing process
func sign(ctx context.Context, msgHash *big.Int, key *big.Int) (x *big.Int, y *big.Int, err error) {

select {
Expand All @@ -78,7 +123,14 @@ func sign(ctx context.Context, msgHash *big.Int, key *big.Int) (x *big.Int, y *b
return x, y, err
}

// GetRandomKeys gets a random set of pub-priv keys. Note: This should be used for testing purposes only, do NOT send real funds to these addresses.
// GetRandomKeys gets a random set of pub-priv keys.
// Note: This should be used for testing purposes only, do NOT send real funds to these addresses.
// Parameters:
// none
// Returns:
// - *MemKeystore: a pointer to a MemKeystore instance
// - *felt.Felt: a pointer to a public key as a felt.Felt
// - *felt.Felt: a pointer to a private key as a felt.Felt
func GetRandomKeys() (*MemKeystore, *felt.Felt, *felt.Felt) {
// Get random keys
privateKey, err := curve.Curve.GetRandomPrivateKey()
Expand Down
4 changes: 4 additions & 0 deletions contracts/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ type CasmClassEntryPoint struct {
Builtins []string `json:"builtins"`
}

// UnmarshalCasmClass is a function that unmarshals a CasmClass object from a file.
// CASM = Cairo instructions
//
// It takes a file path as a parameter and returns a pointer to the unmarshaled CasmClass object and an error.
func UnmarshalCasmClass(filePath string) (*CasmClass, error) {

content, err := os.ReadFile(filePath)
Expand Down
Loading