Merge pull request #15014 from rjl493456442/metropolis-eip658

core: add status as a consensus field in receipt
This commit is contained in:
Péter Szilágyi 2017-08-23 14:39:37 +03:00 committed by GitHub
commit 3c48a25762
18 changed files with 87 additions and 50 deletions

View File

@ -253,7 +253,8 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{}) vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{})
gaspool := new(core.GasPool).AddGas(math.MaxBig256) 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 return ret, gasUsed, err
} }

View File

@ -47,6 +47,9 @@ func FromHex(s string) []byte {
// //
// Returns an exact copy of the provided bytes // Returns an exact copy of the provided bytes
func CopyBytes(b []byte) (copiedBytes []byte) { func CopyBytes(b []byte) (copiedBytes []byte) {
if b == nil {
return nil
}
copiedBytes = make([]byte, len(b)) copiedBytes = make([]byte, len(b))
copy(copiedBytes, b) copy(copiedBytes, b)

View File

@ -461,12 +461,12 @@ func TestMipmapChain(t *testing.T) {
var receipts types.Receipts var receipts types.Receipts
switch i { switch i {
case 1: 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}}} receipt.Logs = []*types.Log{{Address: addr, Topics: []common.Hash{hash1}}}
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
receipts = types.Receipts{receipt} receipts = types.Receipts{receipt}
case 1000: case 1000:
receipt := types.NewReceipt(nil, new(big.Int)) receipt := types.NewReceipt(nil, false, new(big.Int))
receipt.Logs = []*types.Log{{Address: addr2}} receipt.Logs = []*types.Log{{Address: addr2}}
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
receipts = types.Receipts{receipt} receipts = types.Receipts{receipt}

View File

@ -98,7 +98,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
vmenv := vm.NewEVM(context, statedb, config, cfg) vmenv := vm.NewEVM(context, statedb, config, cfg)
// Apply the transaction to the current state (included in the env) // 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 { if err != nil {
return nil, nil, err 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 // 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. // 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.TxHash = tx.Hash()
receipt.GasUsed = new(big.Int).Set(gas) receipt.GasUsed = new(big.Int).Set(gas)
// if the transaction created a contract, store the creation address in the receipt. // if the transaction created a contract, store the creation address in the receipt.

View File

@ -59,7 +59,6 @@ type StateTransition struct {
value *big.Int value *big.Int
data []byte data []byte
state vm.StateDB state vm.StateDB
evm *vm.EVM 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 // 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 // indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block. // 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) st := NewStateTransition(evm, msg, gp)
ret, _, gasUsed, err := st.TransitionDb() ret, _, gasUsed, failed, err := st.TransitionDb()
return ret, gasUsed, err return ret, gasUsed, failed, err
} }
func (st *StateTransition) from() vm.AccountRef { 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 // 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 // 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. // 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 { if err = st.preCheck(); err != nil {
return return
} }
@ -222,10 +221,10 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
// TODO convert to uint64 // TODO convert to uint64
intrinsicGas := IntrinsicGas(st.data, contractCreation, homestead) intrinsicGas := IntrinsicGas(st.data, contractCreation, homestead)
if intrinsicGas.BitLen() > 64 { 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 { if err = st.useGas(intrinsicGas.Uint64()); err != nil {
return nil, nil, nil, err return nil, nil, nil, false, err
} }
var ( var (
@ -248,7 +247,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
// sufficient balance to make the transfer happen. The first // sufficient balance to make the transfer happen. The first
// balance transfer may never fail. // balance transfer may never fail.
if vmerr == vm.ErrInsufficientBalance { if vmerr == vm.ErrInsufficientBalance {
return nil, nil, nil, vmerr return nil, nil, nil, false, vmerr
} }
} }
requiredGas = new(big.Int).Set(st.gasUsed()) requiredGas = new(big.Int).Set(st.gasUsed())
@ -256,7 +255,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
st.refundGas() st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(st.gasUsed(), st.gasPrice)) 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() { func (st *StateTransition) refundGas() {

View File

@ -14,6 +14,7 @@ import (
func (r Receipt) MarshalJSON() ([]byte, error) { func (r Receipt) MarshalJSON() ([]byte, error) {
type Receipt struct { type Receipt struct {
PostState hexutil.Bytes `json:"root"` PostState hexutil.Bytes `json:"root"`
Failed bool `json:"failed"`
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"` CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"`
@ -23,6 +24,7 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
} }
var enc Receipt var enc Receipt
enc.PostState = r.PostState enc.PostState = r.PostState
enc.Failed = r.Failed
enc.CumulativeGasUsed = (*hexutil.Big)(r.CumulativeGasUsed) enc.CumulativeGasUsed = (*hexutil.Big)(r.CumulativeGasUsed)
enc.Bloom = r.Bloom enc.Bloom = r.Bloom
enc.Logs = r.Logs enc.Logs = r.Logs
@ -35,6 +37,7 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
func (r *Receipt) UnmarshalJSON(input []byte) error { func (r *Receipt) UnmarshalJSON(input []byte) error {
type Receipt struct { type Receipt struct {
PostState hexutil.Bytes `json:"root"` PostState hexutil.Bytes `json:"root"`
Failed *bool `json:"failed"`
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"` CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"` Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"`
@ -49,6 +52,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
if dec.PostState != nil { if dec.PostState != nil {
r.PostState = dec.PostState r.PostState = dec.PostState
} }
if dec.Failed != nil {
r.Failed = *dec.Failed
}
if dec.CumulativeGasUsed == nil { if dec.CumulativeGasUsed == nil {
return errors.New("missing required field 'cumulativeGasUsed' for Receipt") return errors.New("missing required field 'cumulativeGasUsed' for Receipt")
} }

View File

@ -28,10 +28,16 @@ import (
//go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go //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. // Receipt represents the results of a transaction.
type Receipt struct { type Receipt struct {
// Consensus fields // Consensus fields
PostState []byte `json:"root"` PostState []byte `json:"root"`
Failed bool `json:"failed"`
CumulativeGasUsed *big.Int `json:"cumulativeGasUsed" gencodec:"required"` CumulativeGasUsed *big.Int `json:"cumulativeGasUsed" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"`
@ -60,21 +66,26 @@ type homesteadReceiptRLP struct {
// metropolisReceiptRLP contains the receipt's Metropolis consensus fields, used // metropolisReceiptRLP contains the receipt's Metropolis consensus fields, used
// during RLP serialization. // during RLP serialization.
type metropolisReceiptRLP struct { type metropolisReceiptRLP struct {
Status byte
CumulativeGasUsed *big.Int CumulativeGasUsed *big.Int
Bloom Bloom Bloom Bloom
Logs []*Log Logs []*Log
} }
// NewReceipt creates a barebone transaction receipt, copying the init fields. // NewReceipt creates a barebone transaction receipt, copying the init fields.
func NewReceipt(root []byte, cumulativeGasUsed *big.Int) *Receipt { func NewReceipt(root []byte, failed bool, cumulativeGasUsed *big.Int) *Receipt {
return &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumulativeGasUsed)} 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 // 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. // into an RLP stream. If no post state is present, metropolis fork is assumed.
func (r *Receipt) EncodeRLP(w io.Writer) error { func (r *Receipt) EncodeRLP(w io.Writer) error {
if r.PostState == nil { 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}) return rlp.Encode(w, &homesteadReceiptRLP{r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs})
} }
@ -87,29 +98,38 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
if err != nil { if err != nil {
return err return err
} }
list, _, err := rlp.SplitList(raw) content, _, err := rlp.SplitList(raw)
if err != nil { if err != nil {
return err return err
} }
items, err := rlp.CountValues(list) kind, cnt, _, err := rlp.Split(content)
if err != nil { if err != nil {
return err return err
} }
// Deserialize based on the number of content items // Deserialize based on the first component type.
switch items { switch {
case 3: case kind == rlp.Byte || (kind == rlp.String && len(cnt) == 0):
// Metropolis receipts have 3 components // The first component of metropolis receipts is Byte (0x01), or the empty
// string (0x80, decoded as a byte with 0x00 value).
var metro metropolisReceiptRLP var metro metropolisReceiptRLP
if err := rlp.DecodeBytes(raw, &metro); err != nil { if err := rlp.DecodeBytes(raw, &metro); err != nil {
return err return err
} }
switch metro.Status {
case receiptStatusSuccessful:
r.Failed = false
case receiptStatusFailed:
r.Failed = true
default:
return fmt.Errorf("invalid status byte: 0x%x", metro.Status)
}
r.CumulativeGasUsed = metro.CumulativeGasUsed r.CumulativeGasUsed = metro.CumulativeGasUsed
r.Bloom = metro.Bloom r.Bloom = metro.Bloom
r.Logs = metro.Logs r.Logs = metro.Logs
return nil return nil
case 4: case kind == rlp.String:
// Homestead receipts have 4 components // The first component of homestead receipts is non-empty String.
var home homesteadReceiptRLP var home homesteadReceiptRLP
if err := rlp.DecodeBytes(raw, &home); err != nil { if err := rlp.DecodeBytes(raw, &home); err != nil {
return err return err
@ -121,14 +141,14 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
return nil return nil
default: default:
return fmt.Errorf("invalid receipt components: %v", items) return fmt.Errorf("invalid first receipt component: %v", kind)
} }
} }
// String implements the Stringer interface. // String implements the Stringer interface.
func (r *Receipt) String() string { func (r *Receipt) String() string {
if r.PostState == nil { 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) return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs)
} }
@ -144,7 +164,7 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
for i, log := range r.Logs { for i, log := range r.Logs {
logs[i] = (*LogForStorage)(log) 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 // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
@ -152,6 +172,7 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
var receipt struct { var receipt struct {
PostState []byte PostState []byte
Failed bool
CumulativeGasUsed *big.Int CumulativeGasUsed *big.Int
Bloom Bloom Bloom Bloom
TxHash common.Hash TxHash common.Hash
@ -163,7 +184,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
return err return err
} }
// Assign the consensus fields // 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)) r.Logs = make([]*Log, len(receipt.Logs))
for i, log := range receipt.Logs { for i, log := range receipt.Logs {
r.Logs[i] = (*Log)(log) r.Logs[i] = (*Log)(log)

View File

@ -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) evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
// initialise a new contract and set the code that is to be used by the // 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. // only.
contract := NewContract(caller, to, value, gas) contract := NewContract(caller, to, value, gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 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) 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 return ret, contractAddr, contract.Gas, err
} }

View File

@ -33,6 +33,7 @@ var (
errWriteProtection = errors.New("evm: write protection") errWriteProtection = errors.New("evm: write protection")
errReturnDataOutOfBounds = errors.New("evm: return data out of bounds") errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
errExecutionReverted = errors.New("evm: execution reverted") 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) { 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 { if value.Sign() != 0 {
gas += params.CallStipend gas += params.CallStipend
} }
ret, returnGas, err := evm.Call(contract, address, args, gas, value) ret, returnGas, err := evm.Call(contract, address, args, gas, value)
if err != nil { if err != nil {
stack.push(new(big.Int)) stack.push(new(big.Int))

View File

@ -523,7 +523,8 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
// Run the transaction with tracing enabled. // Run the transaction with tracing enabled.
vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{Debug: true, Tracer: tracer}) 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 { if err != nil {
return nil, fmt.Errorf("tracing failed: %v", err) 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{}) vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{})
gp := new(core.GasPool).AddGas(tx.Gas()) gp := new(core.GasPool).AddGas(tx.Gas())
_, _, err := core.ApplyMessage(vmenv, msg, gp) _, _, _, err := core.ApplyMessage(vmenv, msg, gp)
if err != nil { if err != nil {
return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err) return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
} }

View File

@ -35,11 +35,11 @@ func TestMipmapUpgrade(t *testing.T) {
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *core.BlockGen) { chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *core.BlockGen) {
switch i { switch i {
case 1: case 1:
receipt := types.NewReceipt(nil, new(big.Int)) receipt := types.NewReceipt(nil, false, new(big.Int))
receipt.Logs = []*types.Log{{Address: addr}} receipt.Logs = []*types.Log{{Address: addr}}
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
case 2: case 2:
receipt := types.NewReceipt(nil, new(big.Int)) receipt := types.NewReceipt(nil, false, new(big.Int))
receipt.Logs = []*types.Log{{Address: addr}} receipt.Logs = []*types.Log{{Address: addr}}
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
} }

View File

@ -33,7 +33,7 @@ import (
) )
func makeReceipt(addr common.Address) *types.Receipt { 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{ receipt.Logs = []*types.Log{
{Address: addr}, {Address: addr},
} }
@ -145,7 +145,7 @@ func TestFilters(t *testing.T) {
var receipts types.Receipts var receipts types.Receipts
switch i { switch i {
case 1: case 1:
receipt := types.NewReceipt(nil, new(big.Int)) receipt := types.NewReceipt(nil, false, new(big.Int))
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{ {
Address: addr, Address: addr,
@ -155,7 +155,7 @@ func TestFilters(t *testing.T) {
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
receipts = types.Receipts{receipt} receipts = types.Receipts{receipt}
case 2: case 2:
receipt := types.NewReceipt(nil, new(big.Int)) receipt := types.NewReceipt(nil, false, new(big.Int))
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{ {
Address: addr, Address: addr,
@ -165,7 +165,7 @@ func TestFilters(t *testing.T) {
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
receipts = types.Receipts{receipt} receipts = types.Receipts{receipt}
case 998: case 998:
receipt := types.NewReceipt(nil, new(big.Int)) receipt := types.NewReceipt(nil, false, new(big.Int))
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{ {
Address: addr, Address: addr,
@ -175,7 +175,7 @@ func TestFilters(t *testing.T) {
gen.AddUncheckedReceipt(receipt) gen.AddUncheckedReceipt(receipt)
receipts = types.Receipts{receipt} receipts = types.Receipts{receipt}
case 999: case 999:
receipt := types.NewReceipt(nil, new(big.Int)) receipt := types.NewReceipt(nil, false, new(big.Int))
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{ {
Address: addr, Address: addr,

View File

@ -635,7 +635,8 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Setup the gas pool (also for unmetered requests) // Setup the gas pool (also for unmetered requests)
// and apply the message. // and apply the message.
gp := new(core.GasPool).AddGas(math.MaxBig256) 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 { if err := vmError(); err != nil {
return nil, common.Big0, err return nil, common.Big0, err
} }

View File

@ -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{}) //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxBig256) gp := new(core.GasPool).AddGas(math.MaxBig256)
ret, _, _ := core.ApplyMessage(vmenv, msg, gp) ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...) res = append(res, ret...)
} }
} else { } else {
@ -138,7 +138,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
context := core.NewEVMContext(msg, header, lc, nil) context := core.NewEVMContext(msg, header, lc, nil)
vmenv := vm.NewEVM(context, state, config, vm.Config{}) vmenv := vm.NewEVM(context, state, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxBig256) gp := new(core.GasPool).AddGas(math.MaxBig256)
ret, _, _ := core.ApplyMessage(vmenv, msg, gp) ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
if state.Error() == nil { if state.Error() == nil {
res = append(res, ret...) res = append(res, ret...)
} }

View File

@ -180,7 +180,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
context := core.NewEVMContext(msg, header, chain, nil) context := core.NewEVMContext(msg, header, chain, nil)
vmenv := vm.NewEVM(context, st, config, vm.Config{}) vmenv := vm.NewEVM(context, st, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxBig256) gp := new(core.GasPool).AddGas(math.MaxBig256)
ret, _, _ := core.ApplyMessage(vmenv, msg, gp) ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...) res = append(res, ret...)
if st.Error() != nil { if st.Error() != nil {
return res, st.Error() return res, st.Error()

View File

@ -33,10 +33,11 @@ func TestBlockchain(t *testing.T) {
// Constantinople is not implemented yet. // Constantinople is not implemented yet.
bt.skipLoad(`(?i)(constantinople)`) bt.skipLoad(`(?i)(constantinople)`)
// Expected failures: // Expected failures:
bt.fails("^TransitionTests/bcEIP158ToByzantium", "byzantium not supported")
bt.fails(`^TransitionTests/bcHomesteadToDao/DaoTransactions(|_UncleExtradata|_EmptyTransactionAndForkBlocksAhead)\.json`, "issue in test") bt.fails(`^TransitionTests/bcHomesteadToDao/DaoTransactions(|_UncleExtradata|_EmptyTransactionAndForkBlocksAhead)\.json`, "issue in test")
bt.fails(`^bc(Exploit|Fork|Gas|Multi|Total|State|Random|Uncle|Valid|Wallet).*_Byzantium$`, "byzantium not supported")
bt.fails(`^bcBlockGasLimitTest/(BlockGasLimit2p63m1|TransactionGasHigherThanLimit2p63m1|SuicideTransaction|GasUsedHigherThanBlockGasLimitButNotWithRefundsSuicideFirst|TransactionGasHigherThanLimit2p63m1_2).*_Byzantium$`, "byzantium not supported") // Still failing tests
bt.skipLoad(`^bcWalletTest.*_Byzantium$`)
bt.skipLoad(`^bcStateTests/suicideCoinbase.json.*_Byzantium$`)
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) { bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
if err := bt.checkFailure(t, name, test.Run()); err != nil { if err := bt.checkFailure(t, name, test.Run()); err != nil {

View File

@ -156,7 +156,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) error {
gaspool := new(core.GasPool) gaspool := new(core.GasPool)
gaspool.AddGas(block.GasLimit()) gaspool.AddGas(block.GasLimit())
snapshot := statedb.Snapshot() snapshot := statedb.Snapshot()
if _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil { if _, _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil {
statedb.RevertToSnapshot(snapshot) statedb.RevertToSnapshot(snapshot)
} }
if post.Logs != nil { if post.Logs != nil {

@ -1 +1 @@
Subproject commit 85f6d7cc01b6bd04e071f5ba579fc675cfd2043b Subproject commit 70e5862eb267226ca89fb9f395c97be1fdf6923a