core: implement Metropolis EIP 658, receipt status byte
This commit is contained in:
		
				
					committed by
					
						 Péter Szilágyi
						Péter Szilágyi
					
				
			
			
				
	
			
			
			
						parent
						
							2fd5ba6bd4
						
					
				
				
					commit
					28aea46ac0
				
			| @@ -253,7 +253,8 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM | ||||
| 	// about the transaction and calling mechanisms. | ||||
| 	vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{}) | ||||
| 	gaspool := new(core.GasPool).AddGas(math.MaxBig256) | ||||
| 	ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() | ||||
| 	// TODO utilize returned failed flag to help gas estimation. | ||||
| 	ret, gasUsed, _, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() | ||||
| 	return ret, gasUsed, err | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -47,6 +47,9 @@ func FromHex(s string) []byte { | ||||
| // | ||||
| // Returns an exact copy of the provided bytes | ||||
| func CopyBytes(b []byte) (copiedBytes []byte) { | ||||
| 	if b == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	copiedBytes = make([]byte, len(b)) | ||||
| 	copy(copiedBytes, b) | ||||
|  | ||||
|   | ||||
| @@ -461,12 +461,12 @@ func TestMipmapChain(t *testing.T) { | ||||
| 		var receipts types.Receipts | ||||
| 		switch i { | ||||
| 		case 1: | ||||
| 			receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 			receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 			receipt.Logs = []*types.Log{{Address: addr, Topics: []common.Hash{hash1}}} | ||||
| 			gen.AddUncheckedReceipt(receipt) | ||||
| 			receipts = types.Receipts{receipt} | ||||
| 		case 1000: | ||||
| 			receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 			receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 			receipt.Logs = []*types.Log{{Address: addr2}} | ||||
| 			gen.AddUncheckedReceipt(receipt) | ||||
| 			receipts = types.Receipts{receipt} | ||||
|   | ||||
| @@ -98,7 +98,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common | ||||
| 	// about the transaction and calling mechanisms. | ||||
| 	vmenv := vm.NewEVM(context, statedb, config, cfg) | ||||
| 	// Apply the transaction to the current state (included in the env) | ||||
| 	_, gas, err := ApplyMessage(vmenv, msg, gp) | ||||
| 	_, gas, failed, err := ApplyMessage(vmenv, msg, gp) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| @@ -114,7 +114,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common | ||||
|  | ||||
| 	// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx | ||||
| 	// based on the eip phase, we're passing wether the root touch-delete accounts. | ||||
| 	receipt := types.NewReceipt(root, usedGas) | ||||
| 	receipt := types.NewReceipt(root, failed, usedGas) | ||||
| 	receipt.TxHash = tx.Hash() | ||||
| 	receipt.GasUsed = new(big.Int).Set(gas) | ||||
| 	// if the transaction created a contract, store the creation address in the receipt. | ||||
|   | ||||
| @@ -59,7 +59,6 @@ type StateTransition struct { | ||||
| 	value      *big.Int | ||||
| 	data       []byte | ||||
| 	state      vm.StateDB | ||||
|  | ||||
| 	evm        *vm.EVM | ||||
| } | ||||
|  | ||||
| @@ -127,11 +126,11 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition | ||||
| // the gas used (which includes gas refunds) and an error if it failed. An error always | ||||
| // indicates a core error meaning that the message would always fail for that particular | ||||
| // state and would never be accepted within a block. | ||||
| func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, error) { | ||||
| func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, bool, error) { | ||||
| 	st := NewStateTransition(evm, msg, gp) | ||||
|  | ||||
| 	ret, _, gasUsed, err := st.TransitionDb() | ||||
| 	return ret, gasUsed, err | ||||
| 	ret, _, gasUsed, failed, err := st.TransitionDb() | ||||
| 	return ret, gasUsed, failed, err | ||||
| } | ||||
|  | ||||
| func (st *StateTransition) from() vm.AccountRef { | ||||
| @@ -208,7 +207,7 @@ func (st *StateTransition) preCheck() error { | ||||
| // TransitionDb will transition the state by applying the current message and returning the result | ||||
| // including the required gas for the operation as well as the used gas. It returns an error if it | ||||
| // failed. An error indicates a consensus issue. | ||||
| func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, err error) { | ||||
| func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, failed bool, err error) { | ||||
| 	if err = st.preCheck(); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| @@ -222,10 +221,10 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big | ||||
| 	// TODO convert to uint64 | ||||
| 	intrinsicGas := IntrinsicGas(st.data, contractCreation, homestead) | ||||
| 	if intrinsicGas.BitLen() > 64 { | ||||
| 		return nil, nil, nil, vm.ErrOutOfGas | ||||
| 		return nil, nil, nil, false, vm.ErrOutOfGas | ||||
| 	} | ||||
| 	if err = st.useGas(intrinsicGas.Uint64()); err != nil { | ||||
| 		return nil, nil, nil, err | ||||
| 		return nil, nil, nil, false, err | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| @@ -248,7 +247,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big | ||||
| 		// sufficient balance to make the transfer happen. The first | ||||
| 		// balance transfer may never fail. | ||||
| 		if vmerr == vm.ErrInsufficientBalance { | ||||
| 			return nil, nil, nil, vmerr | ||||
| 			return nil, nil, nil, false, vmerr | ||||
| 		} | ||||
| 	} | ||||
| 	requiredGas = new(big.Int).Set(st.gasUsed()) | ||||
| @@ -256,7 +255,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big | ||||
| 	st.refundGas() | ||||
| 	st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(st.gasUsed(), st.gasPrice)) | ||||
|  | ||||
| 	return ret, requiredGas, st.gasUsed(), err | ||||
| 	return ret, requiredGas, st.gasUsed(), vmerr != nil, err | ||||
| } | ||||
|  | ||||
| func (st *StateTransition) refundGas() { | ||||
|   | ||||
| @@ -14,6 +14,7 @@ import ( | ||||
| func (r Receipt) MarshalJSON() ([]byte, error) { | ||||
| 	type Receipt struct { | ||||
| 		PostState         hexutil.Bytes  `json:"root"` | ||||
| 		Failed            bool           `json:"failed"` | ||||
| 		CumulativeGasUsed *hexutil.Big   `json:"cumulativeGasUsed" gencodec:"required"` | ||||
| 		Bloom             Bloom          `json:"logsBloom"         gencodec:"required"` | ||||
| 		Logs              []*Log         `json:"logs"              gencodec:"required"` | ||||
| @@ -23,6 +24,7 @@ func (r Receipt) MarshalJSON() ([]byte, error) { | ||||
| 	} | ||||
| 	var enc Receipt | ||||
| 	enc.PostState = r.PostState | ||||
| 	enc.Failed = r.Failed | ||||
| 	enc.CumulativeGasUsed = (*hexutil.Big)(r.CumulativeGasUsed) | ||||
| 	enc.Bloom = r.Bloom | ||||
| 	enc.Logs = r.Logs | ||||
| @@ -35,6 +37,7 @@ func (r Receipt) MarshalJSON() ([]byte, error) { | ||||
| func (r *Receipt) UnmarshalJSON(input []byte) error { | ||||
| 	type Receipt struct { | ||||
| 		PostState         hexutil.Bytes   `json:"root"` | ||||
| 		Failed            *bool           `json:"failed"` | ||||
| 		CumulativeGasUsed *hexutil.Big    `json:"cumulativeGasUsed" gencodec:"required"` | ||||
| 		Bloom             *Bloom          `json:"logsBloom"         gencodec:"required"` | ||||
| 		Logs              []*Log          `json:"logs"              gencodec:"required"` | ||||
| @@ -49,6 +52,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { | ||||
| 	if dec.PostState != nil { | ||||
| 		r.PostState = dec.PostState | ||||
| 	} | ||||
| 	if dec.Failed != nil { | ||||
| 		r.Failed = *dec.Failed | ||||
| 	} | ||||
| 	if dec.CumulativeGasUsed == nil { | ||||
| 		return errors.New("missing required field 'cumulativeGasUsed' for Receipt") | ||||
| 	} | ||||
|   | ||||
| @@ -28,10 +28,16 @@ import ( | ||||
|  | ||||
| //go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go | ||||
|  | ||||
| const ( | ||||
| 	receiptStatusSuccessful = byte(0x01) | ||||
| 	receiptStatusFailed     = byte(0x00) | ||||
| ) | ||||
|  | ||||
| // Receipt represents the results of a transaction. | ||||
| type Receipt struct { | ||||
| 	// Consensus fields | ||||
| 	PostState         []byte   `json:"root"` | ||||
| 	Failed            bool     `json:"failed"` | ||||
| 	CumulativeGasUsed *big.Int `json:"cumulativeGasUsed" gencodec:"required"` | ||||
| 	Bloom             Bloom    `json:"logsBloom"         gencodec:"required"` | ||||
| 	Logs              []*Log   `json:"logs"              gencodec:"required"` | ||||
| @@ -60,21 +66,26 @@ type homesteadReceiptRLP struct { | ||||
| // metropolisReceiptRLP contains the receipt's Metropolis consensus fields, used | ||||
| // during RLP serialization. | ||||
| type metropolisReceiptRLP struct { | ||||
| 	Status            byte | ||||
| 	CumulativeGasUsed *big.Int | ||||
| 	Bloom             Bloom | ||||
| 	Logs              []*Log | ||||
| } | ||||
|  | ||||
| // NewReceipt creates a barebone transaction receipt, copying the init fields. | ||||
| func NewReceipt(root []byte, cumulativeGasUsed *big.Int) *Receipt { | ||||
| 	return &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumulativeGasUsed)} | ||||
| func NewReceipt(root []byte, failed bool, cumulativeGasUsed *big.Int) *Receipt { | ||||
| 	return &Receipt{PostState: common.CopyBytes(root), Failed: failed, CumulativeGasUsed: new(big.Int).Set(cumulativeGasUsed)} | ||||
| } | ||||
|  | ||||
| // EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt | ||||
| // into an RLP stream. If no post state is present, metropolis fork is assumed. | ||||
| func (r *Receipt) EncodeRLP(w io.Writer) error { | ||||
| 	if r.PostState == nil { | ||||
| 		return rlp.Encode(w, &metropolisReceiptRLP{r.CumulativeGasUsed, r.Bloom, r.Logs}) | ||||
| 		status := receiptStatusSuccessful | ||||
| 		if r.Failed { | ||||
| 			status = receiptStatusFailed | ||||
| 		} | ||||
| 		return rlp.Encode(w, &metropolisReceiptRLP{status, r.CumulativeGasUsed, r.Bloom, r.Logs}) | ||||
| 	} | ||||
| 	return rlp.Encode(w, &homesteadReceiptRLP{r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs}) | ||||
| } | ||||
| @@ -87,29 +98,31 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	list, _, err := rlp.SplitList(raw) | ||||
| 	content, _, err := rlp.SplitList(raw) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	items, err := rlp.CountValues(list) | ||||
| 	kind, cnt, _, err := rlp.Split(content) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// Deserialize based on the number of content items | ||||
| 	switch items { | ||||
| 	case 3: | ||||
| 		// Metropolis receipts have 3 components | ||||
| 	// Deserialize based on the first component type. | ||||
| 	switch { | ||||
| 	case kind == rlp.Byte || kind == rlp.String && len(cnt) == 0: | ||||
| 		// The first component of metropolis receipts is Byte | ||||
| 		// or empty String(byte with 0x00 value). | ||||
| 		var metro metropolisReceiptRLP | ||||
| 		if err := rlp.DecodeBytes(raw, &metro); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		r.Failed = metro.Status == receiptStatusFailed | ||||
| 		r.CumulativeGasUsed = metro.CumulativeGasUsed | ||||
| 		r.Bloom = metro.Bloom | ||||
| 		r.Logs = metro.Logs | ||||
| 		return nil | ||||
|  | ||||
| 	case 4: | ||||
| 		// Homestead receipts have 4 components | ||||
| 	case kind == rlp.String: | ||||
| 		// The first component of homestead receipts is non-empty String. | ||||
| 		var home homesteadReceiptRLP | ||||
| 		if err := rlp.DecodeBytes(raw, &home); err != nil { | ||||
| 			return err | ||||
| @@ -121,14 +134,14 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error { | ||||
| 		return nil | ||||
|  | ||||
| 	default: | ||||
| 		return fmt.Errorf("invalid receipt components: %v", items) | ||||
| 		return fmt.Errorf("invalid first receipt component: %v", kind) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // String implements the Stringer interface. | ||||
| func (r *Receipt) String() string { | ||||
| 	if r.PostState == nil { | ||||
| 		return fmt.Sprintf("receipt{cgas=%v bloom=%x logs=%v}", r.CumulativeGasUsed, r.Bloom, r.Logs) | ||||
| 		return fmt.Sprintf("receipt{failed=%t cgas=%v bloom=%x logs=%v}", r.Failed, r.CumulativeGasUsed, r.Bloom, r.Logs) | ||||
| 	} | ||||
| 	return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs) | ||||
| } | ||||
| @@ -144,7 +157,7 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { | ||||
| 	for i, log := range r.Logs { | ||||
| 		logs[i] = (*LogForStorage)(log) | ||||
| 	} | ||||
| 	return rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, logs, r.GasUsed}) | ||||
| 	return rlp.Encode(w, []interface{}{r.PostState, r.Failed, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, logs, r.GasUsed}) | ||||
| } | ||||
|  | ||||
| // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation | ||||
| @@ -152,6 +165,7 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { | ||||
| func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { | ||||
| 	var receipt struct { | ||||
| 		PostState         []byte | ||||
| 		Failed            bool | ||||
| 		CumulativeGasUsed *big.Int | ||||
| 		Bloom             Bloom | ||||
| 		TxHash            common.Hash | ||||
| @@ -163,7 +177,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { | ||||
| 		return err | ||||
| 	} | ||||
| 	// Assign the consensus fields | ||||
| 	r.PostState, r.CumulativeGasUsed, r.Bloom = receipt.PostState, receipt.CumulativeGasUsed, receipt.Bloom | ||||
| 	r.PostState, r.Failed, r.CumulativeGasUsed, r.Bloom = receipt.PostState, receipt.Failed, receipt.CumulativeGasUsed, receipt.Bloom | ||||
| 	r.Logs = make([]*Log, len(receipt.Logs)) | ||||
| 	for i, log := range receipt.Logs { | ||||
| 		r.Logs[i] = (*Log)(log) | ||||
|   | ||||
| @@ -158,7 +158,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas | ||||
| 	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value) | ||||
|  | ||||
| 	// initialise a new contract and set the code that is to be used by the | ||||
| 	// E The contract is a scoped evmironment for this execution context | ||||
| 	// E The contract is a scoped environment for this execution context | ||||
| 	// only. | ||||
| 	contract := NewContract(caller, to, value, gas) | ||||
| 	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) | ||||
| @@ -351,6 +351,10 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I | ||||
| 			contract.UseGas(contract.Gas) | ||||
| 		} | ||||
| 	} | ||||
| 	// Assign err if contract code size exceeds the max while the err is still empty. | ||||
| 	if maxCodeSizeExceeded && err == nil { | ||||
| 		err = errMaxCodeSizeExceeded | ||||
| 	} | ||||
| 	return ret, contractAddr, contract.Gas, err | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -33,6 +33,7 @@ var ( | ||||
| 	errWriteProtection       = errors.New("evm: write protection") | ||||
| 	errReturnDataOutOfBounds = errors.New("evm: return data out of bounds") | ||||
| 	errExecutionReverted     = errors.New("evm: execution reverted") | ||||
| 	errMaxCodeSizeExceeded   = errors.New("evm: max code size exceeded") | ||||
| ) | ||||
|  | ||||
| func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { | ||||
| @@ -619,7 +620,6 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta | ||||
| 	if value.Sign() != 0 { | ||||
| 		gas += params.CallStipend | ||||
| 	} | ||||
|  | ||||
| 	ret, returnGas, err := evm.Call(contract, address, args, gas, value) | ||||
| 	if err != nil { | ||||
| 		stack.push(new(big.Int)) | ||||
|   | ||||
| @@ -523,7 +523,8 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common. | ||||
|  | ||||
| 	// Run the transaction with tracing enabled. | ||||
| 	vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{Debug: true, Tracer: tracer}) | ||||
| 	ret, gas, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())) | ||||
| 	// TODO utilize failed flag | ||||
| 	ret, gas, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("tracing failed: %v", err) | ||||
| 	} | ||||
| @@ -570,7 +571,7 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int) (co | ||||
|  | ||||
| 		vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{}) | ||||
| 		gp := new(core.GasPool).AddGas(tx.Gas()) | ||||
| 		_, _, err := core.ApplyMessage(vmenv, msg, gp) | ||||
| 		_, _, _, err := core.ApplyMessage(vmenv, msg, gp) | ||||
| 		if err != nil { | ||||
| 			return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err) | ||||
| 		} | ||||
|   | ||||
| @@ -35,11 +35,11 @@ func TestMipmapUpgrade(t *testing.T) { | ||||
| 	chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *core.BlockGen) { | ||||
| 		switch i { | ||||
| 		case 1: | ||||
| 			receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 			receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 			receipt.Logs = []*types.Log{{Address: addr}} | ||||
| 			gen.AddUncheckedReceipt(receipt) | ||||
| 		case 2: | ||||
| 			receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 			receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 			receipt.Logs = []*types.Log{{Address: addr}} | ||||
| 			gen.AddUncheckedReceipt(receipt) | ||||
| 		} | ||||
|   | ||||
| @@ -33,7 +33,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| func makeReceipt(addr common.Address) *types.Receipt { | ||||
| 	receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 	receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 	receipt.Logs = []*types.Log{ | ||||
| 		{Address: addr}, | ||||
| 	} | ||||
| @@ -145,7 +145,7 @@ func TestFilters(t *testing.T) { | ||||
| 		var receipts types.Receipts | ||||
| 		switch i { | ||||
| 		case 1: | ||||
| 			receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 			receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 			receipt.Logs = []*types.Log{ | ||||
| 				{ | ||||
| 					Address: addr, | ||||
| @@ -155,7 +155,7 @@ func TestFilters(t *testing.T) { | ||||
| 			gen.AddUncheckedReceipt(receipt) | ||||
| 			receipts = types.Receipts{receipt} | ||||
| 		case 2: | ||||
| 			receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 			receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 			receipt.Logs = []*types.Log{ | ||||
| 				{ | ||||
| 					Address: addr, | ||||
| @@ -165,7 +165,7 @@ func TestFilters(t *testing.T) { | ||||
| 			gen.AddUncheckedReceipt(receipt) | ||||
| 			receipts = types.Receipts{receipt} | ||||
| 		case 998: | ||||
| 			receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 			receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 			receipt.Logs = []*types.Log{ | ||||
| 				{ | ||||
| 					Address: addr, | ||||
| @@ -175,7 +175,7 @@ func TestFilters(t *testing.T) { | ||||
| 			gen.AddUncheckedReceipt(receipt) | ||||
| 			receipts = types.Receipts{receipt} | ||||
| 		case 999: | ||||
| 			receipt := types.NewReceipt(nil, new(big.Int)) | ||||
| 			receipt := types.NewReceipt(nil, false, new(big.Int)) | ||||
| 			receipt.Logs = []*types.Log{ | ||||
| 				{ | ||||
| 					Address: addr, | ||||
|   | ||||
| @@ -635,7 +635,8 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr | ||||
| 	// Setup the gas pool (also for unmetered requests) | ||||
| 	// and apply the message. | ||||
| 	gp := new(core.GasPool).AddGas(math.MaxBig256) | ||||
| 	res, gas, err := core.ApplyMessage(evm, msg, gp) | ||||
| 	// TODO utilize failed flag to help gas estimation | ||||
| 	res, gas, _, err := core.ApplyMessage(evm, msg, gp) | ||||
| 	if err := vmError(); err != nil { | ||||
| 		return nil, common.Big0, err | ||||
| 	} | ||||
|   | ||||
| @@ -127,7 +127,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai | ||||
|  | ||||
| 				//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) | ||||
| 				gp := new(core.GasPool).AddGas(math.MaxBig256) | ||||
| 				ret, _, _ := core.ApplyMessage(vmenv, msg, gp) | ||||
| 				ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) | ||||
| 				res = append(res, ret...) | ||||
| 			} | ||||
| 		} else { | ||||
| @@ -138,7 +138,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai | ||||
| 			context := core.NewEVMContext(msg, header, lc, nil) | ||||
| 			vmenv := vm.NewEVM(context, state, config, vm.Config{}) | ||||
| 			gp := new(core.GasPool).AddGas(math.MaxBig256) | ||||
| 			ret, _, _ := core.ApplyMessage(vmenv, msg, gp) | ||||
| 			ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) | ||||
| 			if state.Error() == nil { | ||||
| 				res = append(res, ret...) | ||||
| 			} | ||||
|   | ||||
| @@ -180,7 +180,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain | ||||
| 		context := core.NewEVMContext(msg, header, chain, nil) | ||||
| 		vmenv := vm.NewEVM(context, st, config, vm.Config{}) | ||||
| 		gp := new(core.GasPool).AddGas(math.MaxBig256) | ||||
| 		ret, _, _ := core.ApplyMessage(vmenv, msg, gp) | ||||
| 		ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) | ||||
| 		res = append(res, ret...) | ||||
| 		if st.Error() != nil { | ||||
| 			return res, st.Error() | ||||
|   | ||||
| @@ -156,7 +156,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) error { | ||||
| 	gaspool := new(core.GasPool) | ||||
| 	gaspool.AddGas(block.GasLimit()) | ||||
| 	snapshot := statedb.Snapshot() | ||||
| 	if _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil { | ||||
| 	if _, _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil { | ||||
| 		statedb.RevertToSnapshot(snapshot) | ||||
| 	} | ||||
| 	if post.Logs != nil { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user