package extension import ( "math/big" "testing" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" ) type MockBackend struct { wallets []accounts.Wallet } func (backend *MockBackend) Wallets() []accounts.Wallet { return backend.wallets } func (backend *MockBackend) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { return nil } type MockWallet struct { isContained bool } func (wallet *MockWallet) URL() accounts.URL { panic("not implemented") } func (wallet *MockWallet) Status() (string, error) { panic("not implemented") } func (wallet *MockWallet) Open(passphrase string) error { panic("not implemented") } func (wallet *MockWallet) Close() error { panic("not implemented") } func (wallet *MockWallet) Accounts() []accounts.Account { panic("not implemented") } func (wallet *MockWallet) Contains(account accounts.Account) bool { return wallet.isContained } func (wallet *MockWallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { panic("not implemented") } func (wallet *MockWallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { panic("not implemented") } func (wallet *MockWallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { panic("not implemented") } func (wallet *MockWallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { panic("not implemented") } func (wallet *MockWallet) SignText(account accounts.Account, text []byte) ([]byte, error) { panic("not implemented") } func (wallet *MockWallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { panic("not implemented") } func (wallet *MockWallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { panic("not implemented") } func (wallet *MockWallet) SignTextWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) { panic("not implemented") } type MockEthAPIBackend struct { eth.EthAPIBackend } func (b *MockEthAPIBackend) IsPrivacyMarkerTransactionCreationEnabled() bool { return false } func TestGenerateTransactionOptionsErrorsWhenNoPrivateParticipants(t *testing.T) { sendTxArgs := ethapi.SendTxArgs{ From: common.Address{}, } mockBackend := MockBackend{} accountManager := accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true}, &mockBackend) service := &PrivacyService{ accountManager: accountManager, } _, err := service.GenerateTransactOptions(sendTxArgs) if err == nil { t.Errorf("expected err to not be nil") return } expectedErr := "must specify private participants" if err.Error() != expectedErr { t.Errorf("expected err to be '%s', but was '%s'", expectedErr, err.Error()) } } func TestGenerateTransactionOptionsErrorsWhenAccountNotFound(t *testing.T) { privateTxArgs := ethapi.PrivateTxArgs{PrivateFor: []string{}} sendTxArgs := ethapi.SendTxArgs{ From: common.Address{}, PrivateTxArgs: privateTxArgs, } mockBackend := MockBackend{} accountManager := accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true}, &mockBackend) service := &PrivacyService{ accountManager: accountManager, } _, err := service.GenerateTransactOptions(sendTxArgs) if err == nil { t.Errorf("expected err to not be nil") return } expectedErr := "no wallet found for account 0x0000000000000000000000000000000000000000" if err.Error() != expectedErr { t.Errorf("expected err to be '%s', but was '%s'", expectedErr, err.Error()) } } func TestGenerateTransactionOptionsGivesDefaults(t *testing.T) { from := common.HexToAddress("0x2222222222222222222222222222222222222222") privateTxArgs := ethapi.PrivateTxArgs{PrivateFor: []string{"privateFor1", "privateFor2"}, PrivateFrom: "privateFrom"} sendTxArgs := ethapi.SendTxArgs{ From: from, PrivateTxArgs: privateTxArgs, } mockWallet := &MockWallet{isContained: true} mockBackend := MockBackend{wallets: []accounts.Wallet{mockWallet}} mockAPIBackendHelper := MockEthAPIBackend{} accountManager := accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true}, &mockBackend) config := params.ChainConfig{ ChainID: big.NewInt(1337), } service := &PrivacyService{ accountManager: accountManager, apiBackendHelper: &mockAPIBackendHelper, config: &config, } generatedOptions, err := service.GenerateTransactOptions(sendTxArgs) if err != nil { t.Errorf("expected err to be '%s', but was '%s'", "nil", err.Error()) return } if generatedOptions.PrivateFrom != sendTxArgs.PrivateFrom { t.Errorf("expected PrivateFrom to be '%s', but was '%s'", sendTxArgs.PrivateFrom, generatedOptions.PrivateFrom) return } if len(generatedOptions.PrivateFor) != 2 || generatedOptions.PrivateFor[0] != sendTxArgs.PrivateFor[0] || generatedOptions.PrivateFor[1] != sendTxArgs.PrivateFor[1] { t.Errorf("expected PrivateFor to be '%s', but was '%s'", sendTxArgs.PrivateFor, generatedOptions.PrivateFor) return } if generatedOptions.GasLimit != 4712384 { t.Errorf("expected GasLimit to be '%d', but was '%d'", 4712384, generatedOptions.GasLimit) return } if generatedOptions.GasPrice == nil || generatedOptions.GasPrice.Cmp(new(big.Int)) != 0 { t.Errorf("expected GasLimit to be '%d', but was '%d'", new(big.Int), generatedOptions.GasPrice) return } if generatedOptions.From != from { t.Errorf("expected From to be '%d', but was '%d'", from, generatedOptions.From) return } } func TestGenerateTransactionOptionsGivesNonDefaultsWhenSpecified(t *testing.T) { from := common.HexToAddress("0x2222222222222222222222222222222222222222") gasLimit := hexutil.Uint64(5000) gasPrice := hexutil.Big(*big.NewInt(50)) privateTxArgs := ethapi.PrivateTxArgs{PrivateFor: []string{}} sendTxArgs := ethapi.SendTxArgs{ From: from, Gas: &gasLimit, GasPrice: &gasPrice, PrivateTxArgs: privateTxArgs, } mockWallet := &MockWallet{isContained: true} mockBackend := MockBackend{wallets: []accounts.Wallet{mockWallet}} mockAPIBackendHelper := MockEthAPIBackend{} accountManager := accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true}, &mockBackend) config := params.ChainConfig{ ChainID: big.NewInt(1337), } service := &PrivacyService{ accountManager: accountManager, apiBackendHelper: &mockAPIBackendHelper, config: &config, } generatedOptions, err := service.GenerateTransactOptions(sendTxArgs) if err != nil { t.Errorf("expected err to be '%s', but was '%s'", "nil", err.Error()) return } if generatedOptions.GasLimit != 5000 { t.Errorf("expected GasLimit to be '%d', but was '%d'", 5000, generatedOptions.GasLimit) return } if generatedOptions.GasPrice == nil || generatedOptions.GasPrice.Cmp(big.NewInt(50)) != 0 { t.Errorf("expected GasLimit to be '%d', but was '%d'", big.NewInt(50), generatedOptions.GasPrice) return } }