From cb8bc156c92bce8c55cefe89eacbfe8a93fd15cb Mon Sep 17 00:00:00 2001 From: Silas Davis <silas@monax.io> Date: Wed, 4 Apr 2018 19:46:41 +0100 Subject: [PATCH] Add MemoryState and rename AddressableSigner rename Signed-off-by: Silas Davis <silas@monax.io> --- account/private_account.go | 8 ++-- account/state/memory_state.go | 80 +++++++++++++++++++++++++++++++ account/state/state_cache_test.go | 45 +++-------------- execution/accounts.go | 68 ++++++++++++++++++++++++++ execution/execution_test.go | 14 +++--- execution/state.go | 3 ++ execution/transactor.go | 75 ++++++++++++++++++++++------- execution/transactor_test.go | 42 ++++++++++++++++ txs/bond_tx.go | 2 +- txs/call_tx.go | 4 +- txs/name_tx.go | 4 +- txs/permission_tx.go | 4 +- txs/rebond_tx.go | 4 +- txs/send_tx.go | 2 +- txs/tx.go | 2 +- txs/unbond_tx.go | 4 +- 16 files changed, 281 insertions(+), 80 deletions(-) create mode 100644 account/state/memory_state.go create mode 100644 execution/accounts.go create mode 100644 execution/transactor_test.go diff --git a/account/private_account.go b/account/private_account.go index 0ef0bed6..3ca56cd7 100644 --- a/account/private_account.go +++ b/account/private_account.go @@ -20,13 +20,13 @@ import ( "github.com/tendermint/go-wire" ) -type SigningAccount interface { +type AddressableSigner interface { Addressable Signer } type PrivateAccount interface { - SigningAccount + AddressableSigner PrivateKey() PrivateKey } @@ -99,8 +99,8 @@ func (pa *ConcretePrivateAccount) String() string { } // Convert slice of ConcretePrivateAccounts to slice of SigningAccounts -func SigningAccounts(concretePrivateAccounts []*ConcretePrivateAccount) []SigningAccount { - signingAccounts := make([]SigningAccount, len(concretePrivateAccounts)) +func SigningAccounts(concretePrivateAccounts []*ConcretePrivateAccount) []AddressableSigner { + signingAccounts := make([]AddressableSigner, len(concretePrivateAccounts)) for i, cpa := range concretePrivateAccounts { signingAccounts[i] = cpa.PrivateAccount() } diff --git a/account/state/memory_state.go b/account/state/memory_state.go new file mode 100644 index 00000000..35f1ad69 --- /dev/null +++ b/account/state/memory_state.go @@ -0,0 +1,80 @@ +package state + +import ( + "fmt" + + acm "github.com/hyperledger/burrow/account" + "github.com/hyperledger/burrow/binary" +) + +type MemoryState struct { + Accounts map[acm.Address]acm.Account + Storage map[acm.Address]map[binary.Word256]binary.Word256 +} + +var _ IterableWriter = &MemoryState{} + +// Get an in-memory state Iterable +func NewMemoryState() *MemoryState { + return &MemoryState{ + Accounts: make(map[acm.Address]acm.Account), + Storage: make(map[acm.Address]map[binary.Word256]binary.Word256), + } +} + +func (ms *MemoryState) GetAccount(address acm.Address) (acm.Account, error) { + return ms.Accounts[address], nil +} + +func (ms *MemoryState) UpdateAccount(updatedAccount acm.Account) error { + if updatedAccount == nil { + return fmt.Errorf("UpdateAccount passed nil account in MemoryState") + } + ms.Accounts[updatedAccount.Address()] = updatedAccount + return nil +} + +func (ms *MemoryState) RemoveAccount(address acm.Address) error { + delete(ms.Accounts, address) + return nil +} + +func (ms *MemoryState) GetStorage(address acm.Address, key binary.Word256) (binary.Word256, error) { + storage, ok := ms.Storage[address] + if !ok { + return binary.Zero256, fmt.Errorf("could not find storage for account %s", address) + } + value, ok := storage[key] + if !ok { + return binary.Zero256, fmt.Errorf("could not find key %x for account %s", key, address) + } + return value, nil +} + +func (ms *MemoryState) SetStorage(address acm.Address, key, value binary.Word256) error { + storage, ok := ms.Storage[address] + if !ok { + storage = make(map[binary.Word256]binary.Word256) + ms.Storage[address] = storage + } + storage[key] = value + return nil +} + +func (ms *MemoryState) IterateAccounts(consumer func(acm.Account) (stop bool)) (stopped bool, err error) { + for _, acc := range ms.Accounts { + if consumer(acc) { + return true, nil + } + } + return false, nil +} + +func (ms *MemoryState) IterateStorage(address acm.Address, consumer func(key, value binary.Word256) (stop bool)) (stopped bool, err error) { + for key, value := range ms.Storage[address] { + if consumer(key, value) { + return true, nil + } + } + return false, nil +} diff --git a/account/state/state_cache_test.go b/account/state/state_cache_test.go index a0c5bc80..2c414708 100644 --- a/account/state/state_cache_test.go +++ b/account/state/state_cache_test.go @@ -1,7 +1,6 @@ package state import ( - "fmt" "testing" acm "github.com/hyperledger/burrow/account" @@ -15,7 +14,7 @@ import ( func TestStateCache_GetAccount(t *testing.T) { // Build backend states for read and write readBackend := testAccounts() - writeBackend := NewCache(newTestState()) + writeBackend := NewCache(NewMemoryState()) cache := NewCache(readBackend) acc := readBackend.Accounts[addressOf("acc1")] @@ -34,7 +33,7 @@ func TestStateCache_GetAccount(t *testing.T) { func TestStateCache_UpdateAccount(t *testing.T) { // Build backend states for read and write - backend := NewCache(newTestState()) + backend := NewCache(NewMemoryState()) cache := NewCache(backend) // Create acccount accNew := acm.NewConcreteAccountFromSecret("accNew") @@ -102,7 +101,7 @@ func TestStateCache_Sync(t *testing.T) { func TestStateCache_get(t *testing.T) { } -func testAccounts() *testState { +func testAccounts() *MemoryState { acc1 := acm.NewConcreteAccountFromSecret("acc1") acc1.Permissions.Base.Perms = permission.AddRole | permission.Send acc1.Permissions.Base.SetBit = acc1.Permissions.Base.Perms @@ -124,22 +123,8 @@ func addressOf(secret string) acm.Address { return acm.NewConcreteAccountFromSecret(secret).Address } -// testState StateIterable - -type testState struct { - Accounts map[acm.Address]acm.Account - Storage map[acm.Address]map[binary.Word256]binary.Word256 -} - -func newTestState() *testState { - return &testState{ - Accounts: make(map[acm.Address]acm.Account), - Storage: make(map[acm.Address]map[binary.Word256]binary.Word256), - } -} - -func account(acc acm.Account, keyvals ...string) *testState { - ts := newTestState() +func account(acc acm.Account, keyvals ...string) *MemoryState { + ts := NewMemoryState() ts.Accounts[acc.Address()] = acc ts.Storage[acc.Address()] = make(map[binary.Word256]binary.Word256) for i := 0; i < len(keyvals); i += 2 { @@ -148,8 +133,8 @@ func account(acc acm.Account, keyvals ...string) *testState { return ts } -func combine(states ...*testState) *testState { - ts := newTestState() +func combine(states ...*MemoryState) *MemoryState { + ts := NewMemoryState() for _, state := range states { for _, acc := range state.Accounts { ts.Accounts[acc.Address()] = acc @@ -162,19 +147,3 @@ func combine(states ...*testState) *testState { func word(str string) binary.Word256 { return binary.LeftPadWord256([]byte(str)) } - -func (tsr *testState) GetAccount(address acm.Address) (acm.Account, error) { - return tsr.Accounts[address], nil -} - -func (tsr *testState) GetStorage(address acm.Address, key binary.Word256) (binary.Word256, error) { - storage, ok := tsr.Storage[address] - if !ok { - return binary.Zero256, fmt.Errorf("could not find storage for account %s", address) - } - value, ok := storage[key] - if !ok { - return binary.Zero256, fmt.Errorf("could not find key %x for account %s", key, address) - } - return value, nil -} diff --git a/execution/accounts.go b/execution/accounts.go new file mode 100644 index 00000000..7dc11149 --- /dev/null +++ b/execution/accounts.go @@ -0,0 +1,68 @@ +package execution + +import ( + "fmt" + + acm "github.com/hyperledger/burrow/account" + "github.com/hyperledger/burrow/account/state" + "github.com/hyperledger/burrow/keys" +) + +type Accounts struct { + state.Iterable + keyClient keys.KeyClient +} + +type SigningAccount struct { + acm.Account + acm.Signer +} + +func NewAccounts(iterable state.Iterable, keyClient keys.KeyClient) *Accounts { + return &Accounts{ + Iterable: iterable, + keyClient: keyClient, + } +} + +func (accs *Accounts) SigningAccount(address acm.Address) (*SigningAccount, error) { + signer := keys.Signer(accs.keyClient, address) + account, err := accs.GetAccount(address) + if err != nil { + return nil, err + } + // If the account is unknown to us return a zeroed account + if account != nil { + account = acm.ConcreteAccount{ + Address: address, + }.Account() + } + return &SigningAccount{ + Account: account, + Signer: signer, + }, nil +} + +func (accs *Accounts) SigningAccountFromPrivateKey(privateKeyBytes []byte) (*SigningAccount, error) { + if len(privateKeyBytes) != 64 { + return nil, fmt.Errorf("Private key is not of the right length: %d\n", len(privateKeyBytes)) + } + privateAccount, err := acm.GeneratePrivateAccountFromPrivateKeyBytes(privateKeyBytes) + if err != nil { + return nil, err + } + account, err := accs.GetAccount(privateAccount.Address()) + if err != nil { + return nil, err + } + // If the account is unknown to us return a zeroed account + if account != nil { + account = acm.ConcreteAccount{ + Address: privateAccount.Address(), + }.Account() + } + return &SigningAccount{ + Account: account, + Signer: privateAccount, + }, nil +} diff --git a/execution/execution_test.go b/execution/execution_test.go index 6401c8fc..f1cdfb56 100644 --- a/execution/execution_test.go +++ b/execution/execution_test.go @@ -119,8 +119,8 @@ var testGenesisDoc, testPrivAccounts, _ = deterministicGenesis. GenesisDoc(3, true, 1000, 1, true, 1000) var testChainID = testGenesisDoc.ChainID() -func makeUsers(n int) []acm.SigningAccount { - users := make([]acm.SigningAccount, n) +func makeUsers(n int) []acm.AddressableSigner { + users := make([]acm.AddressableSigner, n) for i := 0; i < n; i++ { secret := "mysecret" + strconv.Itoa(i) users[i] = acm.GeneratePrivateAccountFromSecret(secret) @@ -1703,7 +1703,7 @@ func execTxWithStateNewBlock(state *State, blockchain bcm.MutableBlockchain, tx } func makeGenesisState(numAccounts int, randBalance bool, minBalance uint64, numValidators int, randBonded bool, - minBonded int64) (*State, []acm.SigningAccount) { + minBonded int64) (*State, []acm.AddressableSigner) { testGenesisDoc, privAccounts, _ := deterministicGenesis.GenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded) s0, err := MakeGenesisState(dbm.NewMemDB(), testGenesisDoc) @@ -1860,7 +1860,7 @@ func permNameToFuncID(name string) []byte { return id[:] } -func snativePermTestInputCALL(name string, user acm.SigningAccount, perm ptypes.PermFlag, +func snativePermTestInputCALL(name string, user acm.AddressableSigner, perm ptypes.PermFlag, val bool) (addr acm.Address, pF ptypes.PermFlag, data []byte) { addr = permissionsContract.Address() switch name { @@ -1883,7 +1883,7 @@ func snativePermTestInputCALL(name string, user acm.SigningAccount, perm ptypes. return } -func snativePermTestInputTx(name string, user acm.SigningAccount, perm ptypes.PermFlag, +func snativePermTestInputTx(name string, user acm.AddressableSigner, perm ptypes.PermFlag, val bool) (snativeArgs snatives.PermArgs) { switch name { @@ -1899,7 +1899,7 @@ func snativePermTestInputTx(name string, user acm.SigningAccount, perm ptypes.Pe return } -func snativeRoleTestInputCALL(name string, user acm.SigningAccount, +func snativeRoleTestInputCALL(name string, user acm.AddressableSigner, role string) (addr acm.Address, pF ptypes.PermFlag, data []byte) { addr = permissionsContract.Address() data = user.Address().Word256().Bytes() @@ -1913,7 +1913,7 @@ func snativeRoleTestInputCALL(name string, user acm.SigningAccount, return } -func snativeRoleTestInputTx(name string, user acm.SigningAccount, role string) (snativeArgs snatives.PermArgs) { +func snativeRoleTestInputTx(name string, user acm.AddressableSigner, role string) (snativeArgs snatives.PermArgs) { switch name { case "hasRole": snativeArgs = snatives.HasRoleArgs(user.Address(), role) diff --git a/execution/state.go b/execution/state.go index 73fb51df..7b98a32a 100644 --- a/execution/state.go +++ b/execution/state.go @@ -185,6 +185,9 @@ func (s *State) GetAccount(address acm.Address) (acm.Account, error) { func (s *State) UpdateAccount(account acm.Account) error { s.Lock() defer s.Unlock() + if account == nil { + return fmt.Errorf("UpdateAccount passed nil account in execution.State") + } // TODO: find a way to implement something equivalent to this so we can set the account StorageRoot //storageRoot := s.tree.SubTreeHash(prefixedKey(storagePrefix, account.Address().Bytes())) // Alternatively just abandon and diff --git a/execution/transactor.go b/execution/transactor.go index a875fe6b..ddbe8fe7 100644 --- a/execution/transactor.go +++ b/execution/transactor.go @@ -17,11 +17,10 @@ package execution import ( "context" "fmt" + "runtime/debug" "sync" "time" - "runtime/debug" - acm "github.com/hyperledger/burrow/account" "github.com/hyperledger/burrow/account/state" "github.com/hyperledger/burrow/binary" @@ -45,9 +44,14 @@ type Call struct { GasUsed uint64 } +type SequencedAddressableSigner interface { + acm.AddressableSigner + Sequence() uint64 +} + // Transactor is the controller/middleware for the v0 RPC type Transactor struct { - txMtx sync.Mutex + sync.Mutex tip blockchain.Tip state state.Iterable eventEmitter event.Emitter @@ -161,6 +165,44 @@ func (trans *Transactor) BroadcastTx(tx txs.Tx) (*txs.Receipt, error) { } } +// Orders calls to BroadcastTx using lock (waits for response from core before releasing) +func (trans *Transactor) Transact2(inputAccount SequencedAddressableSigner, address *acm.Address, data []byte, gasLimit, + fee uint64) (*txs.Receipt, error) { + trans.Lock() + defer trans.Unlock() + // TODO: [Silas] we should consider revising this method and removing fee, or + // possibly adding an amount parameter. It is non-sensical to just be able to + // set the fee. Our support of fees in general is questionable since at the + // moment all we do is deduct the fee effectively leaking token. It is possible + // someone may be using the sending of native token to payable functions but + // they can be served by broadcasting a token. + + // We hard-code the amount to be equal to the fee which means the CallTx we + // generate transfers 0 value, which is the most sensible default since in + // recent solidity compilers the EVM generated will throw an error if value + // is transferred to a non-payable function. + txInput := &txs.TxInput{ + Address: inputAccount.Address(), + Amount: fee, + Sequence: inputAccount.Sequence() + 1, + PublicKey: inputAccount.PublicKey(), + } + tx := &txs.CallTx{ + Input: txInput, + Address: address, + GasLimit: gasLimit, + Fee: fee, + Data: data, + } + + // Got ourselves a tx. + err := tx.Sign(trans.tip.ChainID(), inputAccount) + if err != nil { + return nil, err + } + return trans.BroadcastTx(tx) +} + // Orders calls to BroadcastTx using lock (waits for response from core before releasing) func (trans *Transactor) Transact(privKey []byte, address *acm.Address, data []byte, gasLimit, fee uint64) (*txs.Receipt, error) { @@ -168,13 +210,12 @@ func (trans *Transactor) Transact(privKey []byte, address *acm.Address, data []b if len(privKey) != 64 { return nil, fmt.Errorf("Private key is not of the right length: %d\n", len(privKey)) } - trans.txMtx.Lock() - defer trans.txMtx.Unlock() + trans.Lock() + defer trans.Unlock() pa, err := acm.GeneratePrivateAccountFromPrivateKeyBytes(privKey) if err != nil { return nil, err } - // [Silas] This is puzzling, if the account doesn't exist the CallTx will fail, so what's the point in this? acc, err := trans.state.GetAccount(pa.Address()) if err != nil { return nil, err @@ -210,7 +251,7 @@ func (trans *Transactor) Transact(privKey []byte, address *acm.Address, data []b } // Got ourselves a tx. - txS, errS := trans.SignTx(tx, []acm.SigningAccount{pa}) + txS, errS := trans.SignTx(tx, []acm.AddressableSigner{pa}) if errS != nil { return nil, errS } @@ -265,14 +306,13 @@ func (trans *Transactor) Send(privKey []byte, toAddress acm.Address, amount uint pk := &[64]byte{} copy(pk[:], privKey) - trans.txMtx.Lock() - defer trans.txMtx.Unlock() + trans.Lock() + defer trans.Unlock() pa, err := acm.GeneratePrivateAccountFromPrivateKeyBytes(privKey) if err != nil { return nil, err } - cache := trans.state - acc, err := cache.GetAccount(pa.Address()) + acc, err := trans.state.GetAccount(pa.Address()) if err != nil { return nil, err } @@ -297,7 +337,7 @@ func (trans *Transactor) Send(privKey []byte, toAddress acm.Address, amount uint tx.Outputs = append(tx.Outputs, txOutput) // Got ourselves a tx. - txS, errS := trans.SignTx(tx, []acm.SigningAccount{pa}) + txS, errS := trans.SignTx(tx, []acm.AddressableSigner{pa}) if errS != nil { return nil, errS } @@ -349,14 +389,13 @@ func (trans *Transactor) TransactNameReg(privKey []byte, name, data string, amou if len(privKey) != 64 { return nil, fmt.Errorf("Private key is not of the right length: %d\n", len(privKey)) } - trans.txMtx.Lock() - defer trans.txMtx.Unlock() + trans.Lock() + defer trans.Unlock() pa, err := acm.GeneratePrivateAccountFromPrivateKeyBytes(privKey) if err != nil { return nil, err } - cache := trans.state // XXX: DON'T MUTATE THIS CACHE (used internally for CheckTx) - acc, err := cache.GetAccount(pa.Address()) + acc, err := trans.state.GetAccount(pa.Address()) if err != nil { return nil, err } @@ -366,7 +405,7 @@ func (trans *Transactor) TransactNameReg(privKey []byte, name, data string, amou } tx := txs.NewNameTxWithSequence(pa.PublicKey(), name, data, amount, fee, sequence) // Got ourselves a tx. - txS, errS := trans.SignTx(tx, []acm.SigningAccount{pa}) + txS, errS := trans.SignTx(tx, []acm.AddressableSigner{pa}) if errS != nil { return nil, errS } @@ -374,7 +413,7 @@ func (trans *Transactor) TransactNameReg(privKey []byte, name, data string, amou } // Sign a transaction -func (trans *Transactor) SignTx(tx txs.Tx, signingAccounts []acm.SigningAccount) (txs.Tx, error) { +func (trans *Transactor) SignTx(tx txs.Tx, signingAccounts []acm.AddressableSigner) (txs.Tx, error) { // more checks? err := tx.Sign(trans.tip.ChainID(), signingAccounts...) if err != nil { diff --git a/execution/transactor_test.go b/execution/transactor_test.go new file mode 100644 index 00000000..83c281a4 --- /dev/null +++ b/execution/transactor_test.go @@ -0,0 +1,42 @@ +package execution + +import ( + "testing" + "time" + + "github.com/hyperledger/burrow/account/state" + "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/event" + "github.com/hyperledger/burrow/txs" + "github.com/tendermint/abci/types" +) + +func TestTransactor_TransactAndHold(t *testing.T) { +} + +type testTransactor struct { + ResponseCh chan<- *types.Response + state.IterableWriter + event.Emitter + *Transactor +} + +func newTestTransactor(txProcessor func(tx txs.Tx) (*types.Response, error)) testTransactor { + st := state.NewMemoryState() + emitter := event.NewEmitter(logger) + trans := NewTransactor(blockchain.NewTip(testChainID, time.Time{}, nil), st, + emitter, func(tx txs.Tx, callback func(res *types.Response)) error { + res, err := txProcessor(tx) + if err != nil { + return err + } + callback(res) + return nil + }, logger) + + return testTransactor{ + IterableWriter: st, + Emitter: emitter, + Transactor: trans, + } +} diff --git a/txs/bond_tx.go b/txs/bond_tx.go index b6537092..aa6aecea 100644 --- a/txs/bond_tx.go +++ b/txs/bond_tx.go @@ -90,7 +90,7 @@ func (tx *BondTx) AddOutput(addr acm.Address, amt uint64) error { return nil } -func (tx *BondTx) Sign(chainID string, signingAccounts ...acm.SigningAccount) error { +func (tx *BondTx) Sign(chainID string, signingAccounts ...acm.AddressableSigner) error { if len(signingAccounts) != len(tx.Inputs)+1 { return fmt.Errorf("BondTx expects %v SigningAccounts but got %v", len(tx.Inputs)+1, len(signingAccounts)) diff --git a/txs/call_tx.go b/txs/call_tx.go index 234972cd..a3d0f1b8 100644 --- a/txs/call_tx.go +++ b/txs/call_tx.go @@ -55,9 +55,9 @@ func NewCallTxWithSequence(from acm.PublicKey, to *acm.Address, data []byte, } } -func (tx *CallTx) Sign(chainID string, signingAccounts ...acm.SigningAccount) error { +func (tx *CallTx) Sign(chainID string, signingAccounts ...acm.AddressableSigner) error { if len(signingAccounts) != 1 { - return fmt.Errorf("CallTx expects a single SigningAccount for its single Input but %v were provieded", + return fmt.Errorf("CallTx expects a single AddressableSigner for its single Input but %v were provieded", len(signingAccounts)) } var err error diff --git a/txs/name_tx.go b/txs/name_tx.go index a9143ab3..76ef57dc 100644 --- a/txs/name_tx.go +++ b/txs/name_tx.go @@ -56,9 +56,9 @@ func NewNameTxWithSequence(from acm.PublicKey, name, data string, amt, fee, sequ } } -func (tx *NameTx) Sign(chainID string, signingAccounts ...acm.SigningAccount) error { +func (tx *NameTx) Sign(chainID string, signingAccounts ...acm.AddressableSigner) error { if len(signingAccounts) != 1 { - return fmt.Errorf("NameTx expects a single SigningAccount for its single Input but %v were provieded", + return fmt.Errorf("NameTx expects a single AddressableSigner for its single Input but %v were provieded", len(signingAccounts)) } var err error diff --git a/txs/permission_tx.go b/txs/permission_tx.go index a1ed4969..c2dad89b 100644 --- a/txs/permission_tx.go +++ b/txs/permission_tx.go @@ -46,9 +46,9 @@ func NewPermissionsTxWithSequence(from acm.PublicKey, args snatives.PermArgs, se } } -func (tx *PermissionsTx) Sign(chainID string, signingAccounts ...acm.SigningAccount) error { +func (tx *PermissionsTx) Sign(chainID string, signingAccounts ...acm.AddressableSigner) error { if len(signingAccounts) != 1 { - return fmt.Errorf("PermissionsTx expects a single SigningAccount for its single Input but %v were provieded", + return fmt.Errorf("PermissionsTx expects a single AddressableSigner for its single Input but %v were provieded", len(signingAccounts)) } var err error diff --git a/txs/rebond_tx.go b/txs/rebond_tx.go index 93b95898..b5b22ff4 100644 --- a/txs/rebond_tx.go +++ b/txs/rebond_tx.go @@ -24,9 +24,9 @@ func NewRebondTx(addr acm.Address, height int) *RebondTx { } } -func (tx *RebondTx) Sign(chainID string, signingAccounts ...acm.SigningAccount) error { +func (tx *RebondTx) Sign(chainID string, signingAccounts ...acm.AddressableSigner) error { if len(signingAccounts) != 1 { - return fmt.Errorf("RebondTx expects a single SigningAccount for its signature but %v were provieded", + return fmt.Errorf("RebondTx expects a single AddressableSigner for its signature but %v were provieded", len(signingAccounts)) } var err error diff --git a/txs/send_tx.go b/txs/send_tx.go index 02c7039c..e9212fd8 100644 --- a/txs/send_tx.go +++ b/txs/send_tx.go @@ -86,7 +86,7 @@ func (tx *SendTx) AddOutput(addr acm.Address, amt uint64) error { return nil } -func (tx *SendTx) Sign(chainID string, signingAccounts ...acm.SigningAccount) error { +func (tx *SendTx) Sign(chainID string, signingAccounts ...acm.AddressableSigner) error { if len(signingAccounts) != len(tx.Inputs) { return fmt.Errorf("SendTx has %v Inputs but was provided with %v SigningAccounts", len(tx.Inputs), len(signingAccounts)) diff --git a/txs/tx.go b/txs/tx.go index 3e7f0419..dec958e2 100644 --- a/txs/tx.go +++ b/txs/tx.go @@ -84,7 +84,7 @@ type Tx interface { String() string GetInputs() []TxInput Hash(chainID string) []byte - Sign(chainID string, signingAccounts ...acm.SigningAccount) error + Sign(chainID string, signingAccounts ...acm.AddressableSigner) error } type Encoder interface { diff --git a/txs/unbond_tx.go b/txs/unbond_tx.go index ab016a0d..8bd84f29 100644 --- a/txs/unbond_tx.go +++ b/txs/unbond_tx.go @@ -24,9 +24,9 @@ func NewUnbondTx(addr acm.Address, height int) *UnbondTx { } } -func (tx *UnbondTx) Sign(chainID string, signingAccounts ...acm.SigningAccount) error { +func (tx *UnbondTx) Sign(chainID string, signingAccounts ...acm.AddressableSigner) error { if len(signingAccounts) != 1 { - return fmt.Errorf("UnbondTx expects a single SigningAccount for its signature but %v were provieded", + return fmt.Errorf("UnbondTx expects a single AddressableSigner for its signature but %v were provieded", len(signingAccounts)) } var err error -- GitLab