diff --git a/client/client.go b/client/client.go index cd6371a0b8291817d06ce914cde121bde7635a08..b79d85bca9c33ea650ee64d6f51a3ca393e36b44 100644 --- a/client/client.go +++ b/client/client.go @@ -21,21 +21,20 @@ import ( "github.com/tendermint/go-rpc/client" - "github.com/eris-ltd/eris-db/account" + acc "github.com/eris-ltd/eris-db/account" tendermint_client "github.com/eris-ltd/eris-db/rpc/tendermint/client" - rpc_types "github.com/eris-ltd/eris-db/rpc/tendermint/core/types" "github.com/eris-ltd/eris-db/txs" ) type NodeClient interface { Broadcast(transaction txs.Tx) (*txs.Receipt, error) - GetAccount(address []byte) (*account.Account, error) - - Status() (*rpc_types.ResultStatus, error) + Status() (ChainId []byte, ValidatorPublicKey []byte, LatestBlockHash []byte, + BlockHeight int, LatestBlockTime int64, err error) + GetAccount(address []byte) (*acc.Account, error) } -// NOTE [ben] Compiler check to ensure ErisClient successfully implements +// NOTE [ben] Compiler check to ensure ErisNodeClient successfully implements // eris-db/client.NodeClient var _ NodeClient = (*ErisNodeClient)(nil) @@ -58,8 +57,8 @@ func NewErisNodeClient(rpcString string) *ErisNodeClient { // NOTE: [ben] Eris Client first continues from tendermint rpc, but will have handshake to negotiate // protocol version for moving towards rpc/v1 -func (erisClient *ErisNodeClient) Broadcast(tx txs.Tx) (*txs.Receipt, error) { - client := rpcclient.NewClientURI(erisClient.broadcastRPC) +func (erisNodeClient *ErisNodeClient) Broadcast(tx txs.Tx) (*txs.Receipt, error) { + client := rpcclient.NewClientURI(erisNodeClient.broadcastRPC) receipt, err := tendermint_client.BroadcastTx(client, tx) if err != nil { return nil, err @@ -67,30 +66,36 @@ func (erisClient *ErisNodeClient) Broadcast(tx txs.Tx) (*txs.Receipt, error) { return &receipt, nil } -func (erisClient *ErisNodeClient) GetAccount(address []byte) (*account.Account, error) { - // fetch nonce from node - client := rpcclient.NewClientURI(erisClient.broadcastRPC) +//------------------------------------------------------------------------------------ +// RPC requests other than transaction related + +// GetAccount returns a copy of the account +func (erisNodeClient *ErisNodeClient) GetAccount(address []byte) (*acc.Account, error) { + client := rpcclient.NewClientURI(erisNodeClient.broadcastRPC) account, err := tendermint_client.GetAccount(client, address) if err != nil { err = fmt.Errorf("Error connecting to node (%s) to fetch account (%X): %s", - erisClient.broadcastRPC, address, err.Error()) + erisNodeClient.broadcastRPC, address, err.Error()) return nil, err } if account == nil { - err = fmt.Errorf("Unknown account %X at node (%s)", address, erisClient.broadcastRPC) + err = fmt.Errorf("Unknown account %X at node (%s)", address, erisNodeClient.broadcastRPC) return nil, err } return account.Copy(), nil } -func (erisClient *ErisNodeClient) Status() (*rpc_types.ResultStatus, error) { +// Status returns the ChainId (GenesisHash), validator's PublicKey, latest block hash +// the block height and the latest block time. +func (erisClient *ErisNodeClient) Status() (ChainId []byte, ValidatorPublicKey []byte, LatestBlockHash []byte, + BlockHeight int, LatestBlockTime int64, err error) { client := rpcclient.NewClientURI(erisClient.broadcastRPC) res, err := tendermint_client.Status(client) if err != nil { err = fmt.Errorf("Error connecting to node (%s) to get status: %s", erisClient.broadcastRPC, err.Error()) - return nil, err + return nil, nil, nil, 0, 0, err } - return res, nil + return res.GenesisHash, res.PubKey.Bytes(), res.LatestBlockHash, res.LatestBlockHeight, res.LatestBlockTime, nil } diff --git a/client/mock/client_mock.go b/client/mock/client_mock.go index c8a31bc9e77fd0adeb047e34e1ca015f83701882..7cfd54101e9e4431a4b0a9c93d58339e068b1426 100644 --- a/client/mock/client_mock.go +++ b/client/mock/client_mock.go @@ -18,9 +18,6 @@ package mock import ( "github.com/tendermint/go-crypto" - "github.com/tendermint/go-p2p" - - rpc_types "github.com/eris-ltd/eris-db/rpc/tendermint/core/types" acc "github.com/eris-ltd/eris-db/account" . "github.com/eris-ltd/eris-db/client" @@ -72,29 +69,19 @@ func (mock *MockNodeClient) MockAddAccount(account *acc.Account) { mock.accounts[addressString] = account.Copy() } -func (mock *MockNodeClient) Status() (*rpc_types.ResultStatus, error) { +func (mock *MockNodeClient) Status() (ChainId []byte, + ValidatorPublicKey []byte, LatestBlockHash []byte, + BlockHeight int, LatestBlockTime int64, err error) { // make zero account var zero [32]byte ed25519 := crypto.PubKeyEd25519(zero) pub := crypto.PubKey(ed25519) - // create a status - nodeInfo := &p2p.NodeInfo{ - PubKey: ed25519, - Moniker: "Mock", - Network: "MockNet", - RemoteAddr: "127.0.0.1", - ListenAddr: "127.0.0.1", - Version: "0.12.0", - Other: []string{}, - } - - return &rpc_types.ResultStatus{ - NodeInfo: nodeInfo, - GenesisHash: nil, - PubKey: pub, - LatestBlockHash: nil, - LatestBlockHeight: 1, - LatestBlockTime: 1, - }, nil + // fill return values + ChainId = make([]byte, 64) + LatestBlockHash = make([]byte, 64) + ValidatorPublicKey = pub.Bytes() + BlockHeight = 0 + LatestBlockTime = 0 + return } diff --git a/manager/eris-mint/pipe.go b/manager/eris-mint/pipe.go index 2c6b5c3bec037ebf5545354cf093814f6be2d723..6339abc2daab3c055b5c1a226223d61036797957 100644 --- a/manager/eris-mint/pipe.go +++ b/manager/eris-mint/pipe.go @@ -395,7 +395,10 @@ func (pipe *erisMintPipe) DumpStorage(address []byte) (*rpc_tm_types.ResultDumpS return &rpc_tm_types.ResultDumpStorage{storageRoot, storageItems}, nil } -// Call +// Call +// NOTE: this function is used from 46657 and has sibling on 1337 +// in transactor.go +// TODO: [ben] resolve incompatibilities in byte representation for 0.12.0 release func (pipe *erisMintPipe) Call(fromAddress, toAddress, data []byte) (*rpc_tm_types.ResultCall, error) { st := pipe.erisMint.GetState() @@ -404,23 +407,30 @@ func (pipe *erisMintPipe) Call(fromAddress, toAddress, data []byte) (*rpc_tm_typ if outAcc == nil { return nil, fmt.Errorf("Account %x does not exist", toAddress) } + if fromAddress == nil { + fromAddress = []byte{} + } callee := toVMAccount(outAcc) caller := &vm.Account{Address: tm_common.LeftPadWord256(fromAddress)} txCache := state.NewTxCache(cache) + gasLimit := st.GetGasLimit() params := vm.Params{ BlockHeight: int64(st.LastBlockHeight), BlockHash: tm_common.LeftPadWord256(st.LastBlockHash), BlockTime: st.LastBlockTime.Unix(), - GasLimit: st.GetGasLimit(), + GasLimit: gasLimit, } vmach := vm.NewVM(txCache, params, caller.Address, nil) - gas := st.GetGasLimit() + gas := gasLimit ret, err := vmach.Call(caller, callee, callee.Code, data, 0, &gas) if err != nil { return nil, err } - return &rpc_tm_types.ResultCall{Return: ret}, nil + gasUsed := gasLimit - gas + // here return bytes are not hex encoded; on the sibling function + // they are + return &rpc_tm_types.ResultCall{Return: ret, GasUsed: gasUsed}, nil } func (pipe *erisMintPipe) CallCode(fromAddress, code, data []byte) (*rpc_tm_types.ResultCall, @@ -430,20 +440,22 @@ func (pipe *erisMintPipe) CallCode(fromAddress, code, data []byte) (*rpc_tm_type callee := &vm.Account{Address: tm_common.LeftPadWord256(fromAddress)} caller := &vm.Account{Address: tm_common.LeftPadWord256(fromAddress)} txCache := state.NewTxCache(cache) + gasLimit := st.GetGasLimit() params := vm.Params{ BlockHeight: int64(st.LastBlockHeight), BlockHash: tm_common.LeftPadWord256(st.LastBlockHash), BlockTime: st.LastBlockTime.Unix(), - GasLimit: st.GetGasLimit(), + GasLimit: gasLimit, } vmach := vm.NewVM(txCache, params, caller.Address, nil) - gas := st.GetGasLimit() + gas := gasLimit ret, err := vmach.Call(caller, callee, code, data, 0, &gas) if err != nil { return nil, err } - return &rpc_tm_types.ResultCall{Return: ret}, nil + gasUsed := gasLimit - gas + return &rpc_tm_types.ResultCall{Return: ret, GasUsed: gasUsed}, nil } // TODO: [ben] deprecate as we should not allow unsafe behaviour diff --git a/manager/eris-mint/transactor.go b/manager/eris-mint/transactor.go index 23012e4a5cc7e0c1e208f75588860171070759f6..71c342a85f47a4e6216f3a44b9d898755648b270 100644 --- a/manager/eris-mint/transactor.go +++ b/manager/eris-mint/transactor.go @@ -59,10 +59,14 @@ func newTransactor(chainID string, eventSwitch tEvents.Fireable, // Run a contract's code on an isolated and unpersisted state // Cannot be used to create new contracts +// NOTE: this function is used from 1337 and has sibling on 46657 +// in pipe.go +// TODO: [ben] resolve incompatibilities in byte representation for 0.12.0 release func (this *transactor) Call(fromAddress, toAddress, data []byte) ( *core_types.Call, error) { - cache := this.erisMint.GetCheckCache() // XXX: DON'T MUTATE THIS CACHE (used internally for CheckTx) + st := this.erisMint.GetState() + cache := state.NewBlockCache(st) // XXX: DON'T MUTATE THIS CACHE (used internally for CheckTx) outAcc := cache.GetAccount(toAddress) if outAcc == nil { return nil, fmt.Errorf("Account %X does not exist", toAddress) @@ -73,22 +77,25 @@ func (this *transactor) Call(fromAddress, toAddress, data []byte) ( callee := toVMAccount(outAcc) caller := &vm.Account{Address: cmn.LeftPadWord256(fromAddress)} txCache := state.NewTxCache(cache) - st := this.erisMint.GetState() // for block height, time + gasLimit := st.GetGasLimit() params := vm.Params{ BlockHeight: int64(st.LastBlockHeight), BlockHash: cmn.LeftPadWord256(st.LastBlockHash), BlockTime: st.LastBlockTime.Unix(), - GasLimit: 10000000, + GasLimit: gasLimit, } vmach := vm.NewVM(txCache, params, caller.Address, nil) vmach.SetFireable(this.eventSwitch) - gas := int64(1000000000) + gas := gasLimit ret, err := vmach.Call(caller, callee, callee.Code, data, 0, &gas) if err != nil { return nil, err } - return &core_types.Call{Return: hex.EncodeToString(ret)}, nil + gasUsed := gasLimit - gas + // here return bytes are hex encoded; on the sibling function + // they are not + return &core_types.Call{Return: hex.EncodeToString(ret), GasUsed: gasUsed}, nil } // Run the given code on an isolated and unpersisted state @@ -103,20 +110,24 @@ func (this *transactor) CallCode(fromAddress, code, data []byte) ( caller := &vm.Account{Address: cmn.LeftPadWord256(fromAddress)} txCache := state.NewTxCache(cache) st := this.erisMint.GetState() // for block height, time + gasLimit := st.GetGasLimit() params := vm.Params{ BlockHeight: int64(st.LastBlockHeight), BlockHash: cmn.LeftPadWord256(st.LastBlockHash), BlockTime: st.LastBlockTime.Unix(), - GasLimit: 10000000, + GasLimit: gasLimit, } vmach := vm.NewVM(txCache, params, caller.Address, nil) - gas := int64(1000000000) + gas := gasLimit ret, err := vmach.Call(caller, callee, code, data, 0, &gas) if err != nil { return nil, err } - return &core_types.Call{Return: hex.EncodeToString(ret)}, nil + gasUsed := gasLimit - gas + // here return bytes are hex encoded; on the sibling function + // they are not + return &core_types.Call{Return: hex.EncodeToString(ret), GasUsed: gasUsed}, nil } // Broadcast a transaction.