From 7c548e0f74ab477ae83b87be6201d6629888959e Mon Sep 17 00:00:00 2001 From: "amalraj.manigmail.com" Date: Tue, 24 Jul 2018 16:15:38 +0800 Subject: [PATCH] Merge remote-tracking branch 'remotes/geth/release/1.8' into merge-193 changes related to merge conflicts --- accounts/abi/argument.go | 241 --------- accounts/abi/bind/backends/simulated.go | 26 +- cmd/faucet/faucet.go | 2 +- cmd/utils/flags.go | 5 +- common/types.go | 9 + consensus/ethash/consensus.go | 4 +- core/blockchain.go | 11 +- core/blockchain_test.go | 6 +- core/chain_makers.go | 2 +- core/database_util.go | 664 ++++++++++++++++++++++++ core/tx_pool.go | 8 +- core/tx_pool_test.go | 20 +- core/types.go | 2 +- core/types/transaction.go | 1 + core/vm/instructions_test.go | 10 +- core/vm/interface.go | 18 +- core/vm/logger_test.go | 2 +- core/vm/opcodes.go | 10 + eth/api.go | 42 +- eth/api_backend.go | 4 +- eth/backend.go | 6 +- eth/handler.go | 4 +- internal/debug/api.go | 11 - internal/ethapi/api.go | 12 +- internal/ethapi/backend.go | 2 - les/api_backend.go | 4 - les/handler.go | 8 +- les/helper_test.go | 2 +- les/server.go | 2 +- light/lightchain.go | 4 +- p2p/peer.go | 1 + p2p/server.go | 1 - params/config.go | 2 +- params/protocol_params.go | 9 + raft/minter.go | 6 +- tests/block_test_util.go | 2 +- 36 files changed, 813 insertions(+), 350 deletions(-) diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go index 871131d69..93b513c34 100644 --- a/accounts/abi/argument.go +++ b/accounts/abi/argument.go @@ -100,247 +100,6 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error { return arguments.unpackAtomic(v, marshalledValues) } -func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error { - - var ( - value = reflect.ValueOf(v).Elem() - typ = value.Type() - kind = value.Kind() - ) - - if err := requireUnpackKind(value, typ, kind, arguments); err != nil { - return err - } - // If the output interface is a struct, make sure names don't collide - if kind == reflect.Struct { - if err := requireUniqueStructFieldNames(arguments); err != nil { - return err - } - } - for i, arg := range arguments.NonIndexed() { - - reflectValue := reflect.ValueOf(marshalledValues[i]) - - switch kind { - case reflect.Struct: - err := unpackStruct(value, reflectValue, arg) - if err != nil { - return err - } - case reflect.Slice, reflect.Array: - if value.Len() < i { - return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) - } - v := value.Index(i) - if err := requireAssignable(v, reflectValue); err != nil { - return err - } - - if err := set(v.Elem(), reflectValue, arg); err != nil { - return err - } - default: - return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ) - } - } - return nil -} - -// unpackAtomic unpacks ( hexdata -> go ) a single value -func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interface{}) error { - if len(marshalledValues) != 1 { - return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues)) - } - elem := reflect.ValueOf(v).Elem() - kind := elem.Kind() - reflectValue := reflect.ValueOf(marshalledValues[0]) - - if kind == reflect.Struct { - //make sure names don't collide - if err := requireUniqueStructFieldNames(arguments); err != nil { - return err - } - - return unpackStruct(elem, reflectValue, arguments[0]) - } - - return set(elem, reflectValue, arguments.NonIndexed()[0]) - -} - -// Computes the full size of an array; -// i.e. counting nested arrays, which count towards size for unpacking. -func getArraySize(arr *Type) int { - size := arr.Size - // Arrays can be nested, with each element being the same size - arr = arr.Elem - for arr.T == ArrayTy { - // Keep multiplying by elem.Size while the elem is an array. - size *= arr.Size - arr = arr.Elem - } - // Now we have the full array size, including its children. - return size -} - -// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification, -// without supplying a struct to unpack into. Instead, this method returns a list containing the -// values. An atomic argument will be a list with one element. -func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { - retval := make([]interface{}, 0, arguments.LengthNonIndexed()) - virtualArgs := 0 - for index, arg := range arguments.NonIndexed() { - marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data) - if arg.Type.T == ArrayTy { - // If we have a static array, like [3]uint256, these are coded as - // just like uint256,uint256,uint256. - // This means that we need to add two 'virtual' arguments when - // we count the index from now on. - // - // Array values nested multiple levels deep are also encoded inline: - // [2][3]uint256: uint256,uint256,uint256,uint256,uint256,uint256 - // - // Calculate the full array size to get the correct offset for the next argument. - // Decrement it by 1, as the normal index increment is still applied. - virtualArgs += getArraySize(&arg.Type) - 1 - } - if err != nil { - return nil, err - } - retval = append(retval, marshalledValue) - } - return retval, nil -} - -// PackValues performs the operation Go format -> Hexdata -// It is the semantic opposite of UnpackValues -func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) { - return arguments.Pack(args...) -} - -// Pack performs the operation Go format -> Hexdata -func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) { - // Make sure arguments match up and pack them - abiArgs := arguments - if len(args) != len(abiArgs) { - return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs)) - } - // variable input is the output appended at the end of packed - // output. This is used for strings and bytes types input. - var variableInput []byte - - // input offset is the bytes offset for packed output - inputOffset := 0 - for _, abiArg := range abiArgs { - if abiArg.Type.T == ArrayTy { - inputOffset += 32 * abiArg.Type.Size - } else { - inputOffset += 32 - } - } - var ret []byte - for i, a := range args { - input := abiArgs[i] - // pack the input - packed, err := input.Type.pack(reflect.ValueOf(a)) - if err != nil { - return nil, err - } - // check for a slice type (string, bytes, slice) - if input.Type.requiresLengthPrefix() { - // calculate the offset - offset := inputOffset + len(variableInput) - // set the offset - ret = append(ret, packNum(reflect.ValueOf(offset))...) - // Append the packed output to the variable input. The variable input - // will be appended at the end of the input. - variableInput = append(variableInput, packed...) - } else { - // append the packed value to the input - ret = append(ret, packed...) - } - } - // append the variable input at the end of the packed input - ret = append(ret, variableInput...) - - return ret, nil -} - -// capitalise makes the first character of a string upper case, also removing any -// prefixing underscores from the variable names. -func capitalise(input string) string { - for len(input) > 0 && input[0] == '_' { - input = input[1:] - } - if len(input) == 0 { - return "" - } - return strings.ToUpper(input[:1]) + input[1:] -} - -//unpackStruct extracts each argument into its corresponding struct field -func unpackStruct(value, reflectValue reflect.Value, arg Argument) error { - name := capitalise(arg.Name) - typ := value.Type() - for j := 0; j < typ.NumField(); j++ { - // TODO read tags: `abi:"fieldName"` - if typ.Field(j).Name == name { - if err := set(value.Field(j), reflectValue, arg); err != nil { - return err - } - } - } - argument.Name = extarg.Name - argument.Indexed = extarg.Indexed - - return nil -} - -// LengthNonIndexed returns the number of arguments when not counting 'indexed' ones. Only events -// can ever have 'indexed' arguments, it should always be false on arguments for method input/output -func (arguments Arguments) LengthNonIndexed() int { - out := 0 - for _, arg := range arguments { - if !arg.Indexed { - out++ - } - } - return out -} - -// NonIndexed returns the arguments with indexed arguments filtered out -func (arguments Arguments) NonIndexed() Arguments { - var ret []Argument - for _, arg := range arguments { - if !arg.Indexed { - ret = append(ret, arg) - } - } - return ret -} - -// isTuple returns true for non-atomic constructs, like (uint,uint) or uint[] -func (arguments Arguments) isTuple() bool { - return len(arguments) > 1 -} - -// Unpack performs the operation hexdata -> Go format -func (arguments Arguments) Unpack(v interface{}, data []byte) error { - - // make sure the passed value is arguments pointer - if reflect.Ptr != reflect.ValueOf(v).Kind() { - return fmt.Errorf("abi: Unpack(non-pointer %T)", v) - } - marshalledValues, err := arguments.UnpackValues(data) - if err != nil { - return err - } - if arguments.isTuple() { - return arguments.unpackTuple(v, marshalledValues) - } - return arguments.unpackAtomic(v, marshalledValues) -} - func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error { var ( diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index fd69538d5..d08de5153 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -103,7 +103,7 @@ func (b *SimulatedBackend) Rollback() { func (b *SimulatedBackend) rollback() { blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {}) - statedb, _ := b.blockchain.State() + statedb, _, _ := b.blockchain.State() b.pendingBlock = blocks[0] b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database()) @@ -117,7 +117,7 @@ func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address, if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { return nil, errBlockNumberUnsupported } - statedb, _ := b.blockchain.State() + statedb, _, _ := b.blockchain.State() return statedb.GetCode(contract), nil } @@ -129,7 +129,7 @@ func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Addres if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { return nil, errBlockNumberUnsupported } - statedb, _ := b.blockchain.State() + statedb, _, _ := b.blockchain.State() return statedb.GetBalance(contract), nil } @@ -141,7 +141,7 @@ func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address, if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { return 0, errBlockNumberUnsupported } - statedb, _ := b.blockchain.State() + statedb, _, _ := b.blockchain.State() return statedb.GetNonce(contract), nil } @@ -153,7 +153,7 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { return nil, errBlockNumberUnsupported } - statedb, _ := b.blockchain.State() + statedb, _, _ := b.blockchain.State() val := statedb.GetState(contract, key) return val[:], nil } @@ -180,11 +180,11 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { return nil, errBlockNumberUnsupported } - state, err := b.blockchain.State() + state, _, err := b.blockchain.State() if err != nil { return nil, err } - rval, _, _, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), state) + rval, _, _, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), state, state) return rval, err } @@ -194,7 +194,7 @@ func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereu defer b.mu.Unlock() defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot()) - rval, _, _, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) + rval, _, _, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState, b.pendingState) return rval, err } @@ -237,7 +237,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs call.Gas = gas snapshot := b.pendingState.Snapshot() - _, _, failed, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) + _, _, failed, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState, b.pendingState) b.pendingState.RevertToSnapshot(snapshot) if err != nil || failed { @@ -265,7 +265,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs // callContract implements common code between normal and pending contract calls. // state is modified during execution, make sure to copy it if necessary. -func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, uint64, bool, error) { +func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB, privateState *state.StateDB) ([]byte, uint64, bool, error) { // Ensure message is initialized properly. if call.GasPrice == nil { call.GasPrice = big.NewInt(1) @@ -285,7 +285,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{}) + vmenv := vm.NewEVM(evmContext, statedb, privateState, b.config, vm.Config{}) gaspool := new(core.GasPool).AddGas(math.MaxUint64) return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() @@ -312,7 +312,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa } block.AddTxWithChain(b.blockchain, tx) }) - statedb, _ := b.blockchain.State() + statedb, _, _ := b.blockchain.State() b.pendingBlock = blocks[0] b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database()) @@ -391,7 +391,7 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { } block.OffsetTime(int64(adjustment.Seconds())) }) - statedb, _ := b.blockchain.State() + statedb, _, _ := b.blockchain.State() b.pendingBlock = blocks[0] b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database()) diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go index 70fd6d1ab..b4ec620ca 100644 --- a/cmd/faucet/faucet.go +++ b/cmd/faucet/faucet.go @@ -471,7 +471,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) { amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil)) tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil) - signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainID) + signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainID, false) if err != nil { f.lock.Unlock() if err = sendError(conn, err); err != nil { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index e5ec5f3fb..56fd9763c 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -58,6 +58,7 @@ import ( "github.com/ethereum/go-ethereum/params" whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" "gopkg.in/urfave/cli.v1" + "time" ) var ( @@ -1228,7 +1229,8 @@ func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) { } // RegisterEthService adds an Ethereum client to the stack. -func RegisterEthService(stack *node.Node, cfg *eth.Config) { +func RegisterEthService(stack *node.Node, cfg *eth.Config) <-chan *eth.Ethereum { + nodeChan := make(chan *eth.Ethereum, 1) var err error if cfg.SyncMode == downloader.LightSync { err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { @@ -1241,6 +1243,7 @@ func RegisterEthService(stack *node.Node, cfg *eth.Config) { ls, _ := les.NewLesServer(fullNode, cfg) fullNode.AddLesServer(ls) } + nodeChan <- fullNode return fullNode, err }) } diff --git a/common/types.go b/common/types.go index 4d374ad24..7098dd47a 100644 --- a/common/types.go +++ b/common/types.go @@ -51,6 +51,8 @@ func BytesToHash(b []byte) Hash { return h } +func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } // dep: Istanbul + // BigToHash sets byte representation of b to hash. // If b is larger than len(h), b will be cropped from the left. func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } @@ -111,6 +113,10 @@ func (h *Hash) SetBytes(b []byte) { copy(h[HashLength-len(b):], b) } +func EmptyHash(h Hash) bool { + return h == Hash{} +} + // Generate implements testing/quick.Generator. func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { m := rand.Intn(len(h)) @@ -146,6 +152,9 @@ func BytesToAddress(b []byte) Address { return a } +func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) } // dep: Istanbul + + // BigToAddress returns Address with byte values of b. // If b is larger than len(h), b will be cropped from the left. func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 3a4ff5d9c..28950e749 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -545,7 +545,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header) // setting the final state and assembling the block. func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { // Accumulate any block and uncle rewards and commit the final state root - accumulateRewards(chain.Config(), state, header, uncles) + AccumulateRewards(chain.Config(), state, header, uncles) header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) // Header seems complete, assemble into a block and return @@ -561,7 +561,7 @@ var ( // AccumulateRewards credits the coinbase of the given block with the mining // reward. The total reward consists of the static block reward and rewards for // included uncles. The coinbase of each uncle block is also rewarded. -func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { +func AccumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { // Select the correct block reward based on chain progression blockReward := FrontierBlockReward if config.IsByzantium(header.Number) { diff --git a/core/blockchain.go b/core/blockchain.go index 074d957f4..e18ef7e29 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -701,9 +701,9 @@ func (bc *BlockChain) Stop() { } } for !bc.triegc.Empty() { - triedb.Dereference(bc.triegc.PopItem().(common.Hash), common.Hash{}) + triedb.Dereference(bc.triegc.PopItem().(common.Hash)) } - if size := triedb.Size(); size != 0 { + if size, _ := triedb.Size(); size != 0 { log.Error("Dangling trie nodes after full cleanup") } } @@ -976,7 +976,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types. bc.triegc.Push(root, number) break } - triedb.Dereference(root.(common.Hash), common.Hash{}) + triedb.Dereference(root.(common.Hash)) } } } @@ -1486,6 +1486,11 @@ func (bc *BlockChain) BadBlocks() []*types.Block { return blocks } +// HasBadBlock returns whether the block with the hash is a bad block. dep: Istanbul +func (bc *BlockChain) HasBadBlock(hash common.Hash) bool { + return bc.badBlocks.Contains(hash) +} + // addBadBlock adds a bad block to the bad-block LRU cache func (bc *BlockChain) addBadBlock(block *types.Block) { bc.badBlocks.Add(block.Hash(), block) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 26056c44a..899c77956 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -1208,7 +1208,7 @@ func TestEIP161AccountRemoval(t *testing.T) { if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { t.Fatal(err) } - if st, _ := blockchain.State(); !st.Exist(theAddr) { + if st, _, _ := blockchain.State(); !st.Exist(theAddr) { t.Error("expected account to exist") } @@ -1216,7 +1216,7 @@ func TestEIP161AccountRemoval(t *testing.T) { if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { t.Fatal(err) } - if st, _ := blockchain.State(); st.Exist(theAddr) { + if st, _, _ := blockchain.State(); st.Exist(theAddr) { t.Error("account should not exist") } @@ -1224,7 +1224,7 @@ func TestEIP161AccountRemoval(t *testing.T) { if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { t.Fatal(err) } - if st, _ := blockchain.State(); st.Exist(theAddr) { + if st, _, _ := blockchain.State(); st.Exist(theAddr) { t.Error("account should not exist") } } diff --git a/core/chain_makers.go b/core/chain_makers.go index c1e4b4264..c5bf238e6 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -92,7 +92,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { b.SetCoinbase(common.Address{}) } b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) - receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{}) + receipt, _, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{}) if err != nil { panic(err) } diff --git a/core/database_util.go b/core/database_util.go index 9a8bc9592..458be93ac 100644 --- a/core/database_util.go +++ b/core/database_util.go @@ -1 +1,665 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package core + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" +) + +// DatabaseReader wraps the Get method of a backing data store. +type DatabaseReader interface { + Get(key []byte) (value []byte, err error) +} + +// DatabaseDeleter wraps the Delete method of a backing data store. +type DatabaseDeleter interface { + Delete(key []byte) error +} + +var ( + headHeaderKey = []byte("LastHeader") + headBlockKey = []byte("LastBlock") + headFastKey = []byte("LastFast") + + // Data item prefixes (use single byte to avoid mixing data types, avoid `i`). + headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header + tdSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td + numSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + numSuffix -> hash + blockHashPrefix = []byte("H") // blockHashPrefix + hash -> num (uint64 big endian) + bodyPrefix = []byte("b") // bodyPrefix + num (uint64 big endian) + hash -> block body + blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts + lookupPrefix = []byte("l") // lookupPrefix + hash -> transaction/receipt lookup metadata + bloomBitsPrefix = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits + + preimagePrefix = "secure-key-" // preimagePrefix + hash -> preimage + configPrefix = []byte("ethereum-config-") // config prefix for the db + + // Chain index prefixes (use `i` + single byte to avoid mixing data types). + BloomBitsIndexPrefix = []byte("iB") // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress + + // used by old db, now only used for conversion + oldReceiptsPrefix = []byte("receipts-") + oldTxMetaSuffix = []byte{0x01} + + ErrChainConfigNotFound = errors.New("ChainConfig not found") // general config not found error + + preimageCounter = metrics.NewCounter() + preimageHitCounter = metrics.NewCounter() + + privateRootPrefix = []byte("P") + privateblockReceiptsPrefix = []byte("Pr") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts + privateReceiptPrefix = []byte("Prs") + privateBloomPrefix = []byte("Pb") +) + +// txLookupEntry is a positional metadata to help looking up the data content of +// a transaction or receipt given only its hash. +type txLookupEntry struct { + BlockHash common.Hash + BlockIndex uint64 + Index uint64 +} + +// encodeBlockNumber encodes a block number as big endian uint64 +func encodeBlockNumber(number uint64) []byte { + enc := make([]byte, 8) + binary.BigEndian.PutUint64(enc, number) + return enc +} + +// GetCanonicalHash retrieves a hash assigned to a canonical block number. +func GetCanonicalHash(db DatabaseReader, number uint64) common.Hash { + data, _ := db.Get(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)) + if len(data) == 0 { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// missingNumber is returned by GetBlockNumber if no header with the +// given block hash has been stored in the database +const missingNumber = uint64(0xffffffffffffffff) + +// GetBlockNumber returns the block number assigned to a block hash +// if the corresponding header is present in the database +func GetBlockNumber(db DatabaseReader, hash common.Hash) uint64 { + data, _ := db.Get(append(blockHashPrefix, hash.Bytes()...)) + if len(data) != 8 { + return missingNumber + } + return binary.BigEndian.Uint64(data) +} + +// GetHeadHeaderHash retrieves the hash of the current canonical head block's +// header. The difference between this and GetHeadBlockHash is that whereas the +// last block hash is only updated upon a full block import, the last header +// hash is updated already at header import, allowing head tracking for the +// light synchronization mechanism. +func GetHeadHeaderHash(db DatabaseReader) common.Hash { + data, _ := db.Get(headHeaderKey) + if len(data) == 0 { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// GetHeadBlockHash retrieves the hash of the current canonical head block. +func GetHeadBlockHash(db DatabaseReader) common.Hash { + data, _ := db.Get(headBlockKey) + if len(data) == 0 { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// GetHeadFastBlockHash retrieves the hash of the current canonical head block during +// fast synchronization. The difference between this and GetHeadBlockHash is that +// whereas the last block hash is only updated upon a full block import, the last +// fast hash is updated when importing pre-processed blocks. +func GetHeadFastBlockHash(db DatabaseReader) common.Hash { + data, _ := db.Get(headFastKey) + if len(data) == 0 { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// GetHeaderRLP retrieves a block header in its raw RLP database encoding, or nil +// if the header's not found. +func GetHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Get(headerKey(hash, number)) + return data +} + +// GetHeader retrieves the block header corresponding to the hash, nil if none +// found. +func GetHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header { + data := GetHeaderRLP(db, hash, number) + if len(data) == 0 { + return nil + } + header := new(types.Header) + if err := rlp.Decode(bytes.NewReader(data), header); err != nil { + log.Error("Invalid block header RLP", "hash", hash, "err", err) + return nil + } + return header +} + +// GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. +func GetBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { + data, _ := db.Get(blockBodyKey(hash, number)) + return data +} + +func headerKey(hash common.Hash, number uint64) []byte { + return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) +} + +func blockBodyKey(hash common.Hash, number uint64) []byte { + return append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) +} + +// GetBody retrieves the block body (transactons, uncles) corresponding to the +// hash, nil if none found. +func GetBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body { + data := GetBodyRLP(db, hash, number) + if len(data) == 0 { + return nil + } + body := new(types.Body) + if err := rlp.Decode(bytes.NewReader(data), body); err != nil { + log.Error("Invalid block body RLP", "hash", hash, "err", err) + return nil + } + return body +} + +// GetTd retrieves a block's total difficulty corresponding to the hash, nil if +// none found. +func GetTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int { + data, _ := db.Get(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash[:]...), tdSuffix...)) + if len(data) == 0 { + return nil + } + td := new(big.Int) + if err := rlp.Decode(bytes.NewReader(data), td); err != nil { + log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) + return nil + } + return td +} + +// GetBlock retrieves an entire block corresponding to the hash, assembling it +// back from the stored header and body. If either the header or body could not +// be retrieved nil is returned. +// +// Note, due to concurrent download of header and block body the header and thus +// canonical hash can be stored in the database but the body data not (yet). +func GetBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block { + // Retrieve the block header and body contents + header := GetHeader(db, hash, number) + if header == nil { + return nil + } + body := GetBody(db, hash, number) + if body == nil { + return nil + } + // Reassemble the block and return + return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) +} + +// GetBlockReceipts retrieves the receipts generated by the transactions included +// in a block given by its hash. +func GetBlockReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts { + data, _ := db.Get(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash[:]...)) + if len(data) == 0 { + return nil + } + storageReceipts := []*types.ReceiptForStorage{} + if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { + log.Error("Invalid receipt array RLP", "hash", hash, "err", err) + return nil + } + receipts := make(types.Receipts, len(storageReceipts)) + for i, receipt := range storageReceipts { + receipts[i] = (*types.Receipt)(receipt) + } + return receipts +} + +// GetTxLookupEntry retrieves the positional metadata associated with a transaction +// hash to allow retrieving the transaction or receipt by hash. +func GetTxLookupEntry(db DatabaseReader, hash common.Hash) (common.Hash, uint64, uint64) { + // Load the positional metadata from disk and bail if it fails + data, _ := db.Get(append(lookupPrefix, hash.Bytes()...)) + if len(data) == 0 { + return common.Hash{}, 0, 0 + } + // Parse and return the contents of the lookup entry + var entry txLookupEntry + if err := rlp.DecodeBytes(data, &entry); err != nil { + log.Error("Invalid lookup entry RLP", "hash", hash, "err", err) + return common.Hash{}, 0, 0 + } + return entry.BlockHash, entry.BlockIndex, entry.Index +} + +// GetTransaction retrieves a specific transaction from the database, along with +// its added positional metadata. +func GetTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { + // Retrieve the lookup metadata and resolve the transaction from the body + blockHash, blockNumber, txIndex := GetTxLookupEntry(db, hash) + + if blockHash != (common.Hash{}) { + body := GetBody(db, blockHash, blockNumber) + if body == nil || len(body.Transactions) <= int(txIndex) { + log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash, "index", txIndex) + return nil, common.Hash{}, 0, 0 + } + return body.Transactions[txIndex], blockHash, blockNumber, txIndex + } + // Old transaction representation, load the transaction and it's metadata separately + data, _ := db.Get(hash.Bytes()) + if len(data) == 0 { + return nil, common.Hash{}, 0, 0 + } + var tx types.Transaction + if err := rlp.DecodeBytes(data, &tx); err != nil { + return nil, common.Hash{}, 0, 0 + } + // Retrieve the blockchain positional metadata + data, _ = db.Get(append(hash.Bytes(), oldTxMetaSuffix...)) + if len(data) == 0 { + return nil, common.Hash{}, 0, 0 + } + var entry txLookupEntry + if err := rlp.DecodeBytes(data, &entry); err != nil { + return nil, common.Hash{}, 0, 0 + } + return &tx, entry.BlockHash, entry.BlockIndex, entry.Index +} + +// GetReceipt retrieves a specific transaction receipt from the database, along with +// its added positional metadata. +func GetReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) { + // Retrieve the lookup metadata and resolve the receipt from the receipts + blockHash, blockNumber, receiptIndex := GetTxLookupEntry(db, hash) + + if blockHash != (common.Hash{}) { + receipts := GetBlockReceipts(db, blockHash, blockNumber) + if len(receipts) <= int(receiptIndex) { + log.Error("Receipt refereced missing", "number", blockNumber, "hash", blockHash, "index", receiptIndex) + return nil, common.Hash{}, 0, 0 + } + return receipts[receiptIndex], blockHash, blockNumber, receiptIndex + } + // Old receipt representation, load the receipt and set an unknown metadata + data, _ := db.Get(append(oldReceiptsPrefix, hash[:]...)) + if len(data) == 0 { + return nil, common.Hash{}, 0, 0 + } + var receipt types.ReceiptForStorage + err := rlp.DecodeBytes(data, &receipt) + if err != nil { + log.Error("Invalid receipt RLP", "hash", hash, "err", err) + } + return (*types.Receipt)(&receipt), common.Hash{}, 0, 0 +} + +// GetBloomBits retrieves the compressed bloom bit vector belonging to the given +// section and bit index from the. +func GetBloomBits(db DatabaseReader, bit uint, section uint64, head common.Hash) []byte { + key := append(append(bloomBitsPrefix, make([]byte, 10)...), head.Bytes()...) + + binary.BigEndian.PutUint16(key[1:], uint16(bit)) + binary.BigEndian.PutUint64(key[3:], section) + + bits, _ := db.Get(key) + return bits +} + +// WriteCanonicalHash stores the canonical hash for the given block number. +func WriteCanonicalHash(db ethdb.Putter, hash common.Hash, number uint64) error { + key := append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...) + if err := db.Put(key, hash.Bytes()); err != nil { + log.Crit("Failed to store number to hash mapping", "err", err) + } + return nil +} + +// WriteHeadHeaderHash stores the head header's hash. +func WriteHeadHeaderHash(db ethdb.Putter, hash common.Hash) error { + if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { + log.Crit("Failed to store last header's hash", "err", err) + } + return nil +} + +// WriteHeadBlockHash stores the head block's hash. +func WriteHeadBlockHash(db ethdb.Putter, hash common.Hash) error { + if err := db.Put(headBlockKey, hash.Bytes()); err != nil { + log.Crit("Failed to store last block's hash", "err", err) + } + return nil +} + +// WriteHeadFastBlockHash stores the fast head block's hash. +func WriteHeadFastBlockHash(db ethdb.Putter, hash common.Hash) error { + if err := db.Put(headFastKey, hash.Bytes()); err != nil { + log.Crit("Failed to store last fast block's hash", "err", err) + } + return nil +} + +// WriteHeader serializes a block header into the database. +func WriteHeader(db ethdb.Putter, header *types.Header) error { + data, err := rlp.EncodeToBytes(header) + if err != nil { + return err + } + hash := header.Hash().Bytes() + num := header.Number.Uint64() + encNum := encodeBlockNumber(num) + key := append(blockHashPrefix, hash...) + if err := db.Put(key, encNum); err != nil { + log.Crit("Failed to store hash to number mapping", "err", err) + } + key = append(append(headerPrefix, encNum...), hash...) + if err := db.Put(key, data); err != nil { + log.Crit("Failed to store header", "err", err) + } + return nil +} + +// WriteBody serializes the body of a block into the database. +func WriteBody(db ethdb.Putter, hash common.Hash, number uint64, body *types.Body) error { + data, err := rlp.EncodeToBytes(body) + if err != nil { + return err + } + return WriteBodyRLP(db, hash, number, data) +} + +// WriteBodyRLP writes a serialized body of a block into the database. +func WriteBodyRLP(db ethdb.Putter, hash common.Hash, number uint64, rlp rlp.RawValue) error { + key := append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) + if err := db.Put(key, rlp); err != nil { + log.Crit("Failed to store block body", "err", err) + } + return nil +} + +// WriteTd serializes the total difficulty of a block into the database. +func WriteTd(db ethdb.Putter, hash common.Hash, number uint64, td *big.Int) error { + data, err := rlp.EncodeToBytes(td) + if err != nil { + return err + } + key := append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...) + if err := db.Put(key, data); err != nil { + log.Crit("Failed to store block total difficulty", "err", err) + } + return nil +} + +// WriteBlock serializes a block into the database, header and body separately. +func WriteBlock(db ethdb.Putter, block *types.Block) error { + // Store the body first to retain database consistency + if err := WriteBody(db, block.Hash(), block.NumberU64(), block.Body()); err != nil { + return err + } + // Store the header too, signaling full block ownership + if err := WriteHeader(db, block.Header()); err != nil { + return err + } + return nil +} + +// WriteBlockReceipts stores all the transaction receipts belonging to a block +// as a single receipt slice. This is used during chain reorganisations for +// rescheduling dropped transactions. +func WriteBlockReceipts(db ethdb.Putter, hash common.Hash, number uint64, receipts types.Receipts) error { + // Convert the receipts into their storage form and serialize them + storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) + for i, receipt := range receipts { + storageReceipts[i] = (*types.ReceiptForStorage)(receipt) + } + bytes, err := rlp.EncodeToBytes(storageReceipts) + if err != nil { + return err + } + // Store the flattened receipt slice + key := append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) + if err := db.Put(key, bytes); err != nil { + log.Crit("Failed to store block receipts", "err", err) + } + return nil +} + +// WriteTxLookupEntries stores a positional metadata for every transaction from +// a block, enabling hash based transaction and receipt lookups. +func WriteTxLookupEntries(db ethdb.Putter, block *types.Block) error { + // Iterate over each transaction and encode its metadata + for i, tx := range block.Transactions() { + entry := txLookupEntry{ + BlockHash: block.Hash(), + BlockIndex: block.NumberU64(), + Index: uint64(i), + } + data, err := rlp.EncodeToBytes(entry) + if err != nil { + return err + } + if err := db.Put(append(lookupPrefix, tx.Hash().Bytes()...), data); err != nil { + return err + } + } + return nil +} + +// WriteBloomBits writes the compressed bloom bits vector belonging to the given +// section and bit index. +func WriteBloomBits(db ethdb.Putter, bit uint, section uint64, head common.Hash, bits []byte) { + key := append(append(bloomBitsPrefix, make([]byte, 10)...), head.Bytes()...) + + binary.BigEndian.PutUint16(key[1:], uint16(bit)) + binary.BigEndian.PutUint64(key[3:], section) + + if err := db.Put(key, bits); err != nil { + log.Crit("Failed to store bloom bits", "err", err) + } +} + +// DeleteCanonicalHash removes the number to hash canonical mapping. +func DeleteCanonicalHash(db DatabaseDeleter, number uint64) { + db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)) +} + +// DeleteHeader removes all block header data associated with a hash. +func DeleteHeader(db DatabaseDeleter, hash common.Hash, number uint64) { + db.Delete(append(blockHashPrefix, hash.Bytes()...)) + db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) +} + +// DeleteBody removes all block body data associated with a hash. +func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) { + db.Delete(append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) +} + +// DeleteTd removes all block total difficulty data associated with a hash. +func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) { + db.Delete(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...)) +} + +// DeleteBlock removes all block data associated with a hash. +func DeleteBlock(db DatabaseDeleter, hash common.Hash, number uint64) { + DeleteBlockReceipts(db, hash, number) + DeleteHeader(db, hash, number) + DeleteBody(db, hash, number) + DeleteTd(db, hash, number) +} + +// DeleteBlockReceipts removes all receipt data associated with a block hash. +func DeleteBlockReceipts(db DatabaseDeleter, hash common.Hash, number uint64) { + db.Delete(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) +} + +// DeleteTxLookupEntry removes all transaction data associated with a hash. +func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) { + db.Delete(append(lookupPrefix, hash.Bytes()...)) +} + +// PreimageTable returns a Database instance with the key prefix for preimage entries. +func PreimageTable(db ethdb.Database) ethdb.Database { + return ethdb.NewTable(db, preimagePrefix) +} + +// WritePreimages writes the provided set of preimages to the database. `number` is the +// current block number, and is used for debug messages only. +func WritePreimages(db ethdb.Database, number uint64, preimages map[common.Hash][]byte) error { + table := PreimageTable(db) + batch := table.NewBatch() + hitCount := 0 + for hash, preimage := range preimages { + if _, err := table.Get(hash.Bytes()); err != nil { + batch.Put(hash.Bytes(), preimage) + hitCount++ + } + } + preimageCounter.Inc(int64(len(preimages))) + preimageHitCounter.Inc(int64(hitCount)) + if hitCount > 0 { + if err := batch.Write(); err != nil { + return fmt.Errorf("preimage write fail for block %d: %v", number, err) + } + } + return nil +} + +// GetBlockChainVersion reads the version number from db. +func GetBlockChainVersion(db DatabaseReader) int { + var vsn uint + enc, _ := db.Get([]byte("BlockchainVersion")) + rlp.DecodeBytes(enc, &vsn) + return int(vsn) +} + +// WriteBlockChainVersion writes vsn as the version number to db. +func WriteBlockChainVersion(db ethdb.Putter, vsn int) { + enc, _ := rlp.EncodeToBytes(uint(vsn)) + db.Put([]byte("BlockchainVersion"), enc) +} + +// WriteChainConfig writes the chain config settings to the database. +func WriteChainConfig(db ethdb.Putter, hash common.Hash, cfg *params.ChainConfig) error { + // short circuit and ignore if nil config. GetChainConfig + // will return a default. + if cfg == nil { + return nil + } + + jsonChainConfig, err := json.Marshal(cfg) + if err != nil { + return err + } + + return db.Put(append(configPrefix, hash[:]...), jsonChainConfig) +} + +// GetChainConfig will fetch the network settings based on the given hash. +func GetChainConfig(db DatabaseReader, hash common.Hash) (*params.ChainConfig, error) { + jsonChainConfig, _ := db.Get(append(configPrefix, hash[:]...)) + if len(jsonChainConfig) == 0 { + return nil, ErrChainConfigNotFound + } + + var config params.ChainConfig + if err := json.Unmarshal(jsonChainConfig, &config); err != nil { + return nil, err + } + + return &config, nil +} + +// FindCommonAncestor returns the last common ancestor of two block headers +func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header { + for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { + a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1) + if a == nil { + return nil + } + } + for an := a.Number.Uint64(); an < b.Number.Uint64(); { + b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1) + if b == nil { + return nil + } + } + for a.Hash() != b.Hash() { + a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1) + if a == nil { + return nil + } + b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1) + if b == nil { + return nil + } + } + return a +} + +func GetPrivateStateRoot(db ethdb.Database, blockRoot common.Hash) common.Hash { + root, _ := db.Get(append(privateRootPrefix, blockRoot[:]...)) + return common.BytesToHash(root) +} + +func WritePrivateStateRoot(db ethdb.Database, blockRoot, root common.Hash) error { + return db.Put(append(privateRootPrefix, blockRoot[:]...), root[:]) +} + +// WritePrivateBlockBloom creates a bloom filter for the given receipts and saves it to the database +// with the number given as identifier (i.e. block number). +func WritePrivateBlockBloom(db ethdb.Database, number uint64, receipts types.Receipts) error { + rbloom := types.CreateBloom(receipts) + return db.Put(append(privateBloomPrefix, encodeBlockNumber(number)...), rbloom[:]) +} + +// GetPrivateBlockBloom retrieves the private bloom associated with the given number. +func GetPrivateBlockBloom(db ethdb.Database, number uint64) (bloom types.Bloom) { + data, _ := db.Get(append(privateBloomPrefix, encodeBlockNumber(number)...)) + if len(data) > 0 { + bloom = types.BytesToBloom(data) + } + return bloom +} + + diff --git a/core/tx_pool.go b/core/tx_pool.go index 71a975b21..49d176c88 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -118,7 +118,7 @@ const ( type blockChain interface { CurrentBlock() *types.Block GetBlock(hash common.Hash, number uint64) *types.Block - StateAt(root common.Hash) (*state.StateDB, error) + StateAt(root common.Hash) (*state.StateDB, *state.StateDB, error) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription } @@ -240,7 +240,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block if !config.NoLocals && config.Journal != "" { pool.journal = newTxJournal(config.Journal) - if err := pool.journal.load(pool.AddLocal); err != nil { + if err := pool.journal.load(pool.AddLocals); err != nil { log.Warn("Failed to load transaction journal", "err", err) } if err := pool.journal.rotate(pool.local()); err != nil { @@ -402,7 +402,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { if newHead == nil { newHead = pool.chain.CurrentBlock().Header() // Special case during testing } - statedb, err := pool.chain.StateAt(newHead.Root) + statedb, _, err := pool.chain.StateAt(newHead.Root) if err != nil { log.Error("Failed to reset txpool state", "err", err) return @@ -624,7 +624,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { return false, err } // If the transaction pool is full, discard underpriced transactions - if uint64(len(pool.all)) >= pool.config.GlobalSlots+pool.config.GlobalQueue { + if uint64(pool.all.Count()) >= pool.config.GlobalSlots+pool.config.GlobalQueue { // If the new transaction is underpriced, don't accept it if !pool.chainconfig.IsQuorum && !local && pool.priced.Underpriced(tx, pool.locals) { log.Trace("Discarding underpriced transaction", "hash", hash, "price", tx.GasPrice()) diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index e9dee097f..6f7717110 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -95,7 +95,7 @@ func validateTxPoolInternals(pool *TxPool) error { // Ensure the total transaction set is consistent with pending + queued pending, queued := pool.stats() - if total := len(pool.all); total != pending+queued { + if total := pool.all.Count(); total != pending+queued { return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued) } if priced := pool.priced.items.Len() - pool.priced.stales; priced != pending+queued { @@ -119,7 +119,7 @@ func validateTxPoolInternals(pool *TxPool) error { // validateEvents checks that the correct number of transaction addition events // were fired on the pool's event feed. -func validateEvents(events chan TxPreEvent, count int) error { +func validateEvents(events chan NewTxsEvent, count int) error { for i := 0; i < count; i++ { select { case <-events: @@ -129,7 +129,7 @@ func validateEvents(events chan TxPreEvent, count int) error { } select { case tx := <-events: - return fmt.Errorf("more than %d events fired: %v", count, tx.Tx) + return fmt.Errorf("more than %d events fired: %v", count, tx.Txs) case <-time.After(50 * time.Millisecond): // This branch should be "default", but it's a data race between goroutines, @@ -484,7 +484,7 @@ func TestTransactionDropping(t *testing.T) { t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) } if pool.all.Count() != 6 { - t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6) + t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 6) } pool.lockedReset(nil, nil) if pool.pending[account].Len() != 3 { @@ -494,7 +494,7 @@ func TestTransactionDropping(t *testing.T) { t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) } if pool.all.Count() != 6 { - t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6) + t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 6) } // Reduce the balance of the account, and check that invalidated transactions are dropped pool.currentState.AddBalance(account, big.NewInt(-650)) @@ -611,7 +611,7 @@ func TestTransactionPostponing(t *testing.T) { t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) } if pool.all.Count() != len(txs) { - t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)) + t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)) } pool.lockedReset(nil, nil) if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { @@ -621,7 +621,7 @@ func TestTransactionPostponing(t *testing.T) { t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) } if pool.all.Count() != len(txs) { - t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)) + t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)) } // Reduce the balance of the account, and check that transactions are reorganised for _, addr := range accs { @@ -671,7 +671,7 @@ func TestTransactionPostponing(t *testing.T) { } } if pool.all.Count() != len(txs)/2 { - t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)/2) + t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)/2) } } @@ -763,7 +763,7 @@ func TestTransactionQueueAccountLimiting(t *testing.T) { } } if pool.all.Count() != int(testTxPoolConfig.AccountQueue) { - t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue) + t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), testTxPoolConfig.AccountQueue) } } @@ -957,7 +957,7 @@ func TestTransactionPendingLimiting(t *testing.T) { } } if pool.all.Count() != int(testTxPoolConfig.AccountQueue+5) { - t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue+5) + t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), testTxPoolConfig.AccountQueue+5) } if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil { t.Fatalf("event firing failed: %v", err) diff --git a/core/types.go b/core/types.go index d0bbaf0aa..0214fd01d 100644 --- a/core/types.go +++ b/core/types.go @@ -42,5 +42,5 @@ type Validator interface { // of gas used in the process and return an error if any of the internal rules // failed. type Processor interface { - Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) + Process(block *types.Block, statedb, privateState *state.StateDB, cfg vm.Config) (types.Receipts, types.Receipts, []*types.Log, uint64, error) } diff --git a/core/types/transaction.go b/core/types/transaction.go index 6b09b7fd1..0b340faf7 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" + fmt "fmt" ) //go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 1643da967..92a69f71c 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -32,7 +32,7 @@ type twoOperandTest struct { func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) ) @@ -70,7 +70,7 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64 func TestByteOp(t *testing.T) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) stack = newstack() ) env.interpreter.intPool = poolOfIntPools.get() @@ -202,7 +202,7 @@ func TestSLT(t *testing.T) { func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) stack = newstack() ) // convert args @@ -432,7 +432,7 @@ func BenchmarkOpIsZero(b *testing.B) { func TestOpMstore(t *testing.T) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() ) @@ -455,7 +455,7 @@ func TestOpMstore(t *testing.T) { func BenchmarkOpMstore(bench *testing.B) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() ) diff --git a/core/vm/interface.go b/core/vm/interface.go index 1ef91cf1d..64db740e7 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -23,26 +23,36 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +// Quorum uses a cut-down StateDB, MinimalApiState. We leave the methods in StateDB commented out so they'll produce a +// conflict when upstream changes. +type MinimalApiState interface { + GetBalance(addr common.Address) *big.Int + GetCode(addr common.Address) []byte + GetState(a common.Address, b common.Hash) common.Hash + GetNonce(addr common.Address) uint64 +} + // StateDB is an EVM database for full state querying. type StateDB interface { + MinimalApiState CreateAccount(common.Address) SubBalance(common.Address, *big.Int) AddBalance(common.Address, *big.Int) - GetBalance(common.Address) *big.Int + //GetBalance(common.Address) *big.Int - GetNonce(common.Address) uint64 + //GetNonce(common.Address) uint64 SetNonce(common.Address, uint64) GetCodeHash(common.Address) common.Hash - GetCode(common.Address) []byte + //GetCode(common.Address) []byte SetCode(common.Address, []byte) GetCodeSize(common.Address) int AddRefund(uint64) GetRefund() uint64 - GetState(common.Address, common.Hash) common.Hash + //GetState(common.Address, common.Hash) common.Hash SetState(common.Address, common.Hash, common.Hash) Suicide(common.Address) bool diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go index 28830c445..6eac422b8 100644 --- a/core/vm/logger_test.go +++ b/core/vm/logger_test.go @@ -48,7 +48,7 @@ type dummyStateDB struct { func TestStoreCapture(t *testing.T) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) logger = NewStructLogger(nil) mem = NewMemory() stack = newstack() diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index 6c12c50e5..c9202e035 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -532,3 +532,13 @@ var stringToOp = map[string]OpCode{ func StringToOp(str string) OpCode { return stringToOp[str] } + +func (op OpCode) isMutating() bool { + switch op { + // TODO(joel): REVERT? + case SELFDESTRUCT, CREATE, SSTORE, LOG0, LOG1, LOG2, LOG3, LOG4: + return true + default: + return false + } +} diff --git a/eth/api.go b/eth/api.go index 0b6da456f..14c42c0a2 100644 --- a/eth/api.go +++ b/eth/api.go @@ -307,28 +307,38 @@ func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI { } // DumpBlock retrieves the entire state of the database at a given block. -func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) { +func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber, typ string) (state.Dump, error) { + var publicState, privateState *state.StateDB + var err error if blockNr == rpc.PendingBlockNumber { // If we're dumping the pending state, we need to request // both the pending block as well as the pending state from // the miner and operate on those - _, stateDb := api.eth.miner.Pending() - return stateDb.RawDump(), nil - } - var block *types.Block - if blockNr == rpc.LatestBlockNumber { - block = api.eth.blockchain.CurrentBlock() + _, publicState, privateState = api.eth.miner.Pending() } else { - block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) + var block *types.Block + if blockNr == rpc.LatestBlockNumber { + block = api.eth.blockchain.CurrentBlock() + } else { + block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) + } + if block == nil { + return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) + } + publicState, privateState, err = api.eth.BlockChain().StateAt(block.Root()) + if err != nil { + return state.Dump{}, err + } } - if block == nil { - return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) + + switch typ { + case "public": + return publicState.RawDump(), nil + case "private": + return privateState.RawDump(), nil + default: + return state.Dump{}, fmt.Errorf("unknown type: '%s'", typ) } - stateDb, err := api.eth.BlockChain().StateAt(block.Root()) - if err != nil { - return state.Dump{}, err - } - return stateDb.RawDump(), nil } // PrivateDebugAPI is the collection of Ethereum full node APIs exposed over @@ -397,7 +407,7 @@ type storageEntry struct { // StorageRangeAt returns the storage at the given block height and transaction index. func (api *PrivateDebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) { - _, _, statedb, err := api.computeTxEnv(blockHash, txIndex, 0) + _, _, _, statedb, err := api.computeTxEnv(blockHash, txIndex, 0) if err != nil { return StorageRangeResult{}, err } diff --git a/eth/api_backend.go b/eth/api_backend.go index 7c5878360..2a601d4b6 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -204,8 +204,8 @@ func (b *EthAPIBackend) TxPoolContent() (map[common.Address]types.Transactions, return b.eth.TxPool().Content() } -func (b *EthAPIBackend) SubscribeTxPreEvent(ch chan<- core.TxPreEvent) event.Subscription { - return b.eth.TxPool().SubscribeTxPreEvent(ch) +func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { + return b.eth.TxPool().SubscribeNewTxsEvent(ch) } func (b *EthAPIBackend) Downloader() *downloader.Downloader { diff --git a/eth/backend.go b/eth/backend.go index 31b821c47..3dfc2dd5d 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -238,13 +238,13 @@ func CreateConsensusEngine(ctx *node.ServiceContext, config *Config, chainConfig // Otherwise assume proof-of-work switch config.PowMode { - case ethash.ModeFake: + case ModeFake: log.Warn("Ethash used in fake mode") return ethash.NewFaker() - case ethash.ModeTest: + case ModeTest: log.Warn("Ethash used in test mode") return ethash.NewTester() - case ethash.ModeShared: + case ModeShared: log.Warn("Ethash used in shared mode") return ethash.NewShared() default: diff --git a/eth/handler.go b/eth/handler.go index 9cd4071b0..e22b9cb3a 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -102,7 +102,7 @@ type ProtocolManager struct { // NewProtocolManager returns a new Ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // with the Ethereum network. -func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkID uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) { +func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkID uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database, raftMode bool) (*ProtocolManager, error) { // Create the protocol manager with the base fields manager := &ProtocolManager{ networkID: networkID, @@ -239,7 +239,7 @@ func (pm *ProtocolManager) Start(maxPeers int) { func (pm *ProtocolManager) Stop() { log.Info("Stopping Ethereum protocol") - pm.txSub.Unsubscribe() // quits txBroadcastLoop + pm.txsSub.Unsubscribe() // quits txBroadcastLoop if !pm.raftMode { pm.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop } diff --git a/internal/debug/api.go b/internal/debug/api.go index 37d233648..86a4218f6 100644 --- a/internal/debug/api.go +++ b/internal/debug/api.go @@ -207,17 +207,6 @@ func (*HandlerT) SetGCPercent(v int) int { return debug.SetGCPercent(v) } -// FreeOSMemory returns unused memory to the OS. -func (*HandlerT) FreeOSMemory() { - debug.FreeOSMemory() -} - -// SetGCPercent sets the garbage collection target percentage. It returns the previous -// setting. A negative value disables GC. -func (*HandlerT) SetGCPercent(v int) int { - return debug.SetGCPercent(v) -} - func writeProfile(name, file string) error { p := pprof.Lookup(name) log.Info("Writing profile records", "count", p.Count(), "type", name, "dump", file) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 2811d46b4..d833098ee 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -361,7 +361,7 @@ func (s *PrivateAccountAPI) signTransaction(ctx context.Context, args SendTxArgs var chainID *big.Int if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { - chainID = config.ChainId + chainID = config.ChainID } return wallet.SignTxWithPassphrase(account, passwd, tx, chainID) } @@ -521,7 +521,7 @@ func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Add if state == nil || err != nil { return nil, err } - return (*hexutil.Big)(state.GetBalance(address)), state.Error() + return (*hexutil.Big)(state.GetBalance(address)), nil } // GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all @@ -608,7 +608,7 @@ func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Addres return nil, err } code := state.GetCode(address) - return code, state.Error() + return code, nil } // GetStorageAt returns the storage from the state at the given address, key and @@ -620,7 +620,7 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A return nil, err } res := state.GetState(address, common.HexToHash(key)) - return res[:], state.Error() + return res[:], nil } // CallArgs represents the arguments for a call. @@ -1030,7 +1030,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr return nil, err } nonce := state.GetNonce(address) - return (*hexutil.Uint64)(&nonce), state.Error() + return (*hexutil.Uint64)(&nonce), nil } // GetTransactionByHash returns the transaction for the given hash @@ -1273,7 +1273,7 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen var chainID *big.Int isQuorum := false if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { - chainID = config.ChainId + chainID = config.ChainID isQuorum = true } signed, err := wallet.SignTx(account, tx, chainID, isQuorum) diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 1c168f013..fd0615bc7 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -24,7 +24,6 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "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/eth/downloader" @@ -65,7 +64,6 @@ type Backend interface { GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) Stats() (pending int, queued int) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) - SubscribeTxPreEvent(chan<- core.TxPreEvent) event.Subscription SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription ChainConfig() *params.ChainConfig diff --git a/les/api_backend.go b/les/api_backend.go index e3752ebad..2c81904f3 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -137,10 +137,6 @@ func (b *LesApiBackend) TxPoolContent() (map[common.Address]types.Transactions, return b.eth.txPool.Content() } -func (b *LesApiBackend) SubscribeTxPreEvent(ch chan<- core.TxPreEvent) event.Subscription { - return b.eth.txPool.SubscribeTxPreEvent(ch) -} - func (b *LesApiBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { return b.eth.txPool.SubscribeNewTxsEvent(ch) } diff --git a/les/handler.go b/les/handler.go index a1c16cb87..916802a0f 100644 --- a/les/handler.go +++ b/les/handler.go @@ -79,7 +79,7 @@ type BlockChain interface { GetHeaderByHash(hash common.Hash) *types.Header CurrentHeader() *types.Header GetTd(hash common.Hash, number uint64) *big.Int - State() (*state.StateDB, error) + State() (*state.StateDB, *state.StateDB, error) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) Rollback(chain []common.Hash) GetHeaderByNumber(number uint64) *types.Header @@ -605,7 +605,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { // Retrieve the requested state entry, stopping if enough was found if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { - statedb, err := pm.blockchain.State() + statedb, _, err := pm.blockchain.State() if err != nil { continue } @@ -736,7 +736,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { // Retrieve the requested state entry, stopping if enough was found if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { - statedb, err := pm.blockchain.State() + statedb, _, err := pm.blockchain.State() if err != nil { continue } @@ -796,7 +796,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil { if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil { - statedb, _ = pm.blockchain.State() + statedb, _, _ = pm.blockchain.State() root = header.Root } } diff --git a/les/helper_test.go b/les/helper_test.go index 6d997a1a3..cc2a7696b 100644 --- a/les/helper_test.go +++ b/les/helper_test.go @@ -178,7 +178,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor } else { protocolVersions = ServerProtocolVersions } - pm, err := NewProtocolManager(gspec.Config, lightSync, protocolVersions, NetworkId, evmux, engine, peers, chain, nil, db, odr, nil, make(chan struct{}), new(sync.WaitGroup)) + pm, err := NewProtocolManager(gspec.Config, lightSync, protocolVersions, NetworkId, evmux, engine, peers, chain, nil, db, odr, nil,nil, make(chan struct{}), new(sync.WaitGroup)) if err != nil { return nil, err } diff --git a/les/server.go b/les/server.go index 9eb8ee7f9..fca6124c9 100644 --- a/les/server.go +++ b/les/server.go @@ -52,7 +52,7 @@ type LesServer struct { func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) { quitSync := make(chan struct{}) - pm, err := NewProtocolManager(eth.BlockChain().Config(), false, ServerProtocolVersions, config.NetworkId, eth.EventMux(), eth.Engine(), newPeerSet(), eth.BlockChain(), eth.TxPool(), eth.ChainDb(), nil, nil, quitSync, new(sync.WaitGroup)) + pm, err := NewProtocolManager(eth.BlockChain().Config(), false, ServerProtocolVersions, config.NetworkId, eth.EventMux(), eth.Engine(), newPeerSet(), eth.BlockChain(), eth.TxPool(), eth.ChainDb(), nil, nil, nil, quitSync, new(sync.WaitGroup)) if err != nil { return nil, err } diff --git a/light/lightchain.go b/light/lightchain.go index 30b9bd89a..b2b82c553 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -209,8 +209,8 @@ func (bc *LightChain) Genesis() *types.Block { } // State returns a new mutable state based on the current HEAD block. -func (bc *LightChain) State() (*state.StateDB, error) { - return nil, errors.New("not implemented, needs client/server interface split") +func (bc *LightChain) State() (*state.StateDB, *state.StateDB, error) { + return nil, nil, errors.New("not implemented, needs client/server interface split") } // GetBody retrieves a block body (transactions and uncles) from the database diff --git a/p2p/peer.go b/p2p/peer.go index b48708d41..eb2d34441 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -17,6 +17,7 @@ package p2p import ( + "errors" "fmt" "io" "net" diff --git a/p2p/server.go b/p2p/server.go index f2e2ec765..005b69cbd 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -857,7 +857,6 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *discover.Node) e //END - QUORUM Permissioning - clog := srv.log.New("id", c.id, "addr", c.fd.RemoteAddr(), "conn", c.flags) // For dialed connections, check that the remote public key matches. if dialDest != nil && c.id != dialDest.ID { clog.Trace("Dialed identity mismatch", "want", c, dialDest.ID) diff --git a/params/config.go b/params/config.go index 1d207fb09..e95010bad 100644 --- a/params/config.go +++ b/params/config.go @@ -81,7 +81,7 @@ var ( // OttomanChainConfig contains the chain parameters to run a node on the Ottoman test network. OttomanChainConfig = &ChainConfig{ - ChainId: big.NewInt(5), + ChainID: big.NewInt(5), HomesteadBlock: big.NewInt(1), DAOForkBlock: nil, DAOForkSupport: true, diff --git a/params/protocol_params.go b/params/protocol_params.go index 1ea9c5813..1390c860d 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -77,6 +77,7 @@ const ( Bn256ScalarMulGas uint64 = 40000 // Gas needed for an elliptic curve scalar multiplication Bn256PairingBaseGas uint64 = 100000 // Base price for an elliptic curve pairing check Bn256PairingPerPointGas uint64 = 80000 // Per-point price for an elliptic curve pairing check + QuorumMaximumExtraDataSize uint64 = 65 // Maximum size extra data may be after Genesis. ) var ( @@ -85,3 +86,11 @@ var ( MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. ) + +func GetMaximumExtraDataSize(isQuorum bool) uint64 { + if isQuorum { + return QuorumMaximumExtraDataSize + } else { + return MaximumExtraDataSize + } +} diff --git a/raft/minter.go b/raft/minter.go index 97df46f90..7d7a30a7f 100644 --- a/raft/minter.go +++ b/raft/minter.go @@ -62,7 +62,7 @@ type minter struct { invalidRaftOrderingChan chan InvalidRaftOrdering chainHeadChan chan core.ChainHeadEvent chainHeadSub event.Subscription - txPreChan chan core.TxPreEvent + txPreChan chan core.NewTxsEvent txPreSub event.Subscription } @@ -79,11 +79,11 @@ func newMinter(config *params.ChainConfig, eth *RaftService, blockTime time.Dura invalidRaftOrderingChan: make(chan InvalidRaftOrdering, 1), chainHeadChan: make(chan core.ChainHeadEvent, 1), - txPreChan: make(chan core.TxPreEvent, 4096), + txPreChan: make(chan core.NewTxsEvent, 4096), } minter.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(minter.chainHeadChan) - minter.txPreSub = eth.TxPool().SubscribeTxPreEvent(minter.txPreChan) + minter.txPreSub = eth.TxPool().SubscribeNewTxsEvent(minter.txPreChan) minter.speculativeChain.clear(minter.chain.CurrentBlock()) diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 2db47da57..dd4b1a089 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -125,7 +125,7 @@ func (t *BlockTest) Run() error { if common.Hash(t.json.BestBlock) != cmlast { return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast) } - newDB, err := chain.State() + newDB, _, err := chain.State() if err != nil { return err }