diff options
-rw-r--r-- | core/block_processor.go | 5 | ||||
-rw-r--r-- | core/error.go | 22 | ||||
-rw-r--r-- | core/execution.go | 2 | ||||
-rw-r--r-- | core/state_transition.go | 2 | ||||
-rw-r--r-- | core/types/transaction.go | 18 | ||||
-rw-r--r-- | core/types/transaction_test.go | 6 | ||||
-rw-r--r-- | core/vm/errors.go | 24 | ||||
-rw-r--r-- | core/vm/vm.go | 4 | ||||
-rw-r--r-- | rpc/api/eth.go | 26 | ||||
-rw-r--r-- | rpc/api/parsing.go | 33 | ||||
-rw-r--r-- | rpc/api/utils.go | 1 | ||||
-rw-r--r-- | tests/init.go | 5 | ||||
-rw-r--r-- | xeth/xeth.go | 3 |
13 files changed, 87 insertions, 64 deletions
diff --git a/core/block_processor.go b/core/block_processor.go index e7ad059c3..660c917e4 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" @@ -72,7 +73,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated cb := statedb.GetStateObject(coinbase.Address()) _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, cb) - if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { + if err != nil && err != vm.OutOfGasError { return nil, nil, err } @@ -118,7 +119,7 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state statedb.StartRecord(tx.Hash(), block.Hash(), i) receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, header, tx, totalUsedGas, transientProcess) - if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { + if err != nil && err != vm.OutOfGasError { return nil, err } diff --git a/core/error.go b/core/error.go index 3f3c350df..fb64d09b2 100644 --- a/core/error.go +++ b/core/error.go @@ -30,7 +30,6 @@ func ParentError(hash common.Hash) error { func IsParentErr(err error) bool { _, ok := err.(*ParentErr) - return ok } @@ -48,7 +47,6 @@ func UncleError(format string, v ...interface{}) error { func IsUncleErr(err error) bool { _, ok := err.(*UncleErr) - return ok } @@ -67,7 +65,6 @@ func ValidationError(format string, v ...interface{}) *ValidationErr { func IsValidationErr(err error) bool { _, ok := err.(*ValidationErr) - return ok } @@ -86,7 +83,6 @@ func NonceError(is, exp uint64) *NonceErr { func IsNonceErr(err error) bool { _, ok := err.(*NonceErr) - return ok } @@ -121,24 +117,6 @@ func InvalidTxError(err error) *InvalidTxErr { func IsInvalidTxErr(err error) bool { _, ok := err.(*InvalidTxErr) - - return ok -} - -type OutOfGasErr struct { - Message string -} - -func OutOfGasError() *OutOfGasErr { - return &OutOfGasErr{Message: "Out of gas"} -} -func (self *OutOfGasErr) Error() string { - return self.Message -} - -func IsOutOfGasErr(err error) bool { - _, ok := err.(*OutOfGasErr) - return ok } diff --git a/core/execution.go b/core/execution.go index 9fb0210de..a8c4ffb6d 100644 --- a/core/execution.go +++ b/core/execution.go @@ -53,7 +53,7 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm. if env.Depth() > int(params.CallCreateDepth.Int64()) { caller.ReturnGas(self.Gas, self.price) - return nil, vm.DepthError{} + return nil, vm.DepthError } vsnapshot := env.State().Copy() diff --git a/core/state_transition.go b/core/state_transition.go index 5611ffd0f..465000e87 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -122,7 +122,7 @@ func (self *StateTransition) To() *state.StateObject { func (self *StateTransition) UseGas(amount *big.Int) error { if self.gas.Cmp(amount) < 0 { - return OutOfGasError() + return vm.OutOfGasError } self.gas.Sub(self.gas, amount) diff --git a/core/types/transaction.go b/core/types/transaction.go index 95deac36e..c381fc5f3 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -116,11 +116,21 @@ func (tx *Transaction) To() *common.Address { } } +// Hash hashes the RLP encoding of tx. +// It uniquely identifies the transaction. func (tx *Transaction) Hash() common.Hash { if hash := tx.hash.Load(); hash != nil { return hash.(common.Hash) } - v := rlpHash([]interface{}{ + v := rlpHash(tx) + tx.hash.Store(v) + return v +} + +// SigHash returns the hash to be signed by the sender. +// It does not uniquely identify the transaction. +func (tx *Transaction) SigHash() common.Hash { + return rlpHash([]interface{}{ tx.data.AccountNonce, tx.data.Price, tx.data.GasLimit, @@ -128,8 +138,6 @@ func (tx *Transaction) Hash() common.Hash { tx.data.Amount, tx.data.Payload, }) - tx.hash.Store(v) - return v } func (tx *Transaction) Size() common.StorageSize { @@ -180,7 +188,7 @@ func (tx *Transaction) publicKey() ([]byte, error) { sig[64] = tx.data.V - 27 // recover the public key from the signature - hash := tx.Hash() + hash := tx.SigHash() pub, err := crypto.Ecrecover(hash[:], sig) if err != nil { glog.V(logger.Error).Infof("Could not get pubkey from signature: ", err) @@ -204,7 +212,7 @@ func (tx *Transaction) WithSignature(sig []byte) (*Transaction, error) { } func (tx *Transaction) SignECDSA(prv *ecdsa.PrivateKey) (*Transaction, error) { - h := tx.Hash() + h := tx.SigHash() sig, err := crypto.Sign(h[:], prv) if err != nil { return nil, err diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index dd9c5e87b..c9da4b73b 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -34,11 +34,11 @@ var ( ) ) -func TestTransactionHash(t *testing.T) { - if emptyTx.Hash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") { +func TestTransactionSigHash(t *testing.T) { + if emptyTx.SigHash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") { t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash()) } - if rightvrsTx.Hash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") { + if rightvrsTx.SigHash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") { t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.Hash()) } } diff --git a/core/vm/errors.go b/core/vm/errors.go index 799eb6797..75b9c0f10 100644 --- a/core/vm/errors.go +++ b/core/vm/errors.go @@ -1,21 +1,14 @@ package vm import ( + "errors" "fmt" "github.com/ethereum/go-ethereum/params" ) -type OutOfGasError struct{} - -func (self OutOfGasError) Error() string { - return "Out Of Gas" -} - -func IsOOGErr(err error) bool { - _, ok := err.(OutOfGasError) - return ok -} +var OutOfGasError = errors.New("Out of gas") +var DepthError = fmt.Errorf("Max call depth exceeded (%d)", params.CallCreateDepth) type StackError struct { req, has int @@ -33,14 +26,3 @@ func IsStack(err error) bool { _, ok := err.(StackError) return ok } - -type DepthError struct{} - -func (self DepthError) Error() string { - return fmt.Sprintf("Max call depth exceeded (%d)", params.CallCreateDepth) -} - -func IsDepthErr(err error) bool { - _, ok := err.(DepthError) - return ok -} diff --git a/core/vm/vm.go b/core/vm/vm.go index ba803683b..e390fb89c 100644 --- a/core/vm/vm.go +++ b/core/vm/vm.go @@ -116,7 +116,7 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) { context.UseGas(context.Gas) - return context.Return(nil), OutOfGasError{} + return context.Return(nil), OutOfGasError } // Resize the memory calculated previously mem.Resize(newMemSize.Uint64()) @@ -789,7 +789,7 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, context *Con return context.Return(ret), nil } else { - return nil, OutOfGasError{} + return nil, OutOfGasError } } diff --git a/rpc/api/eth.go b/rpc/api/eth.go index db0b4b024..6d759a087 100644 --- a/rpc/api/eth.go +++ b/rpc/api/eth.go @@ -77,6 +77,7 @@ var ( "eth_submitWork": (*ethApi).SubmitWork, "eth_resend": (*ethApi).Resend, "eth_pendingTransactions": (*ethApi).PendingTransactions, + "eth_getTransactionReceipt": (*ethApi).GetTransactionReceipt, } ) @@ -596,3 +597,28 @@ func (self *ethApi) PendingTransactions(req *shared.Request) (interface{}, error return ltxs, nil } + +func (self *ethApi) GetTransactionReceipt(req *shared.Request) (interface{}, error) { + args := new(HashArgs) + if err := self.codec.Decode(req.Params, &args); err != nil { + return nil, shared.NewDecodeParamError(err.Error()) + } + + txhash := common.BytesToHash(common.FromHex(args.Hash)) + tx, bhash, bnum, txi := self.xeth.EthTransactionByHash(args.Hash) + rec := self.xeth.GetTxReceipt(txhash) + // We could have an error of "not found". Should disambiguate + // if err != nil { + // return err, nil + // } + if rec != nil && tx != nil { + v := NewReceiptRes(rec) + v.BlockHash = newHexData(bhash) + v.BlockNumber = newHexNum(bnum) + v.GasUsed = newHexNum(tx.Gas().Bytes()) + v.TransactionIndex = newHexNum(txi) + return v, nil + } + + return nil, nil +} diff --git a/rpc/api/parsing.go b/rpc/api/parsing.go index 632462c31..4209ea7e3 100644 --- a/rpc/api/parsing.go +++ b/rpc/api/parsing.go @@ -1,6 +1,7 @@ package api import ( + "bytes" "encoding/binary" "encoding/hex" "encoding/json" @@ -402,6 +403,38 @@ func NewUncleRes(h *types.Header) *UncleRes { // WorkProved string `json:"workProved"` // } +type ReceiptRes struct { + TransactionHash *hexdata `json:transactionHash` + TransactionIndex *hexnum `json:transactionIndex` + BlockNumber *hexnum `json:blockNumber` + BlockHash *hexdata `json:blockHash` + CumulativeGasUsed *hexnum `json:cumulativeGasUsed` + GasUsed *hexnum `json:gasUsed` + ContractAddress *hexdata `json:contractAddress` + Logs *[]interface{} `json:logs` +} + +func NewReceiptRes(rec *types.Receipt) *ReceiptRes { + if rec == nil { + return nil + } + + var v = new(ReceiptRes) + v.TransactionHash = newHexData(rec.TxHash) + // v.TransactionIndex = newHexNum(input) + // v.BlockNumber = newHexNum(input) + // v.BlockHash = newHexData(input) + v.CumulativeGasUsed = newHexNum(rec.CumulativeGasUsed) + // v.GasUsed = newHexNum(input) + // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation + if bytes.Compare(rec.ContractAddress.Bytes(), bytes.Repeat([]byte{0}, 20)) != 0 { + v.ContractAddress = newHexData(rec.ContractAddress) + } + // v.Logs = rec.Logs() + + return v +} + func numString(raw interface{}) (*big.Int, error) { var number *big.Int // Parse as integer diff --git a/rpc/api/utils.go b/rpc/api/utils.go index e6a01d3d6..54ca28774 100644 --- a/rpc/api/utils.go +++ b/rpc/api/utils.go @@ -86,6 +86,7 @@ var ( "submitWork", "pendingTransactions", "resend", + "getTransactionReceipt", }, "miner": []string{ "hashrate", diff --git a/tests/init.go b/tests/init.go index a78a2f54b..832759f7e 100644 --- a/tests/init.go +++ b/tests/init.go @@ -22,11 +22,6 @@ var ( BlockSkipTests = []string{ "SimpleTx3", - // these panic in block_processor.go:84 , see https://github.com/ethereum/go-ethereum/issues/1384 - "TRANSCT_rvalue_TooShort", - "TRANSCT_rvalue_TooLarge", - "TRANSCT_svalue_TooLarge", - // TODO: check why these fail "BLOCK__RandomByteAtTheEnd", "TRANSCT__RandomByteAtTheEnd", diff --git a/xeth/xeth.go b/xeth/xeth.go index 1cec82e5e..4bd18a2f6 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -969,7 +969,6 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS if contractCreation { addr := crypto.CreateAddress(from, nonce) glog.V(logger.Info).Infof("Tx(%x) created: %x\n", tx.Hash(), addr) - return addr.Hex(), nil } else { glog.V(logger.Info).Infof("Tx(%x) to: %x\n", tx.Hash(), tx.To()) } @@ -978,7 +977,7 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS } func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock bool) (*types.Transaction, error) { - hash := tx.Hash() + hash := tx.SigHash() sig, err := self.doSign(from, hash, didUnlock) if err != nil { return tx, err |