mirror of https://github.com/poanetwork/quorum.git
Merge remote-tracking branch 'remotes/geth/release/1.8' into merge-193
changes related to merge conflicts
This commit is contained in:
parent
c3c479d2aa
commit
7c548e0f74
|
@ -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 (
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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()) }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
42
eth/api.go
42
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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package p2p
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue