forked from cerc-io/ipld-eth-server
Allow Parity as ingest node (#36)
* Upgrade go-ethereum to v1.8 * Add Node Info for parity nodes * Upgrade start_private_blockchain to use v1.8
This commit is contained in:
+16
-32
@@ -18,6 +18,7 @@ package light
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/big"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -26,6 +27,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"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/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
@@ -98,7 +100,6 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
|
||||
if cp, ok := trustedCheckpoints[bc.genesisBlock.Hash()]; ok {
|
||||
bc.addTrustedCheckpoint(cp)
|
||||
}
|
||||
|
||||
if err := bc.loadLastState(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -126,7 +127,7 @@ func (self *LightChain) addTrustedCheckpoint(cp trustedCheckpoint) {
|
||||
if self.odr.BloomIndexer() != nil {
|
||||
self.odr.BloomIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
|
||||
}
|
||||
log.Info("Added trusted checkpoint", "chain name", cp.name)
|
||||
log.Info("Added trusted checkpoint", "chain", cp.name, "block", (cp.sectionIdx+1)*CHTFrequencyClient-1, "hash", cp.sectionHead)
|
||||
}
|
||||
|
||||
func (self *LightChain) getProcInterrupt() bool {
|
||||
@@ -169,32 +170,10 @@ func (bc *LightChain) SetHead(head uint64) {
|
||||
}
|
||||
|
||||
// GasLimit returns the gas limit of the current HEAD block.
|
||||
func (self *LightChain) GasLimit() *big.Int {
|
||||
self.mu.RLock()
|
||||
defer self.mu.RUnlock()
|
||||
|
||||
func (self *LightChain) GasLimit() uint64 {
|
||||
return self.hc.CurrentHeader().GasLimit
|
||||
}
|
||||
|
||||
// LastBlockHash return the hash of the HEAD block.
|
||||
func (self *LightChain) LastBlockHash() common.Hash {
|
||||
self.mu.RLock()
|
||||
defer self.mu.RUnlock()
|
||||
|
||||
return self.hc.CurrentHeader().Hash()
|
||||
}
|
||||
|
||||
// Status returns status information about the current chain such as the HEAD Td,
|
||||
// the HEAD hash and the hash of the genesis block.
|
||||
func (self *LightChain) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) {
|
||||
self.mu.RLock()
|
||||
defer self.mu.RUnlock()
|
||||
|
||||
header := self.hc.CurrentHeader()
|
||||
hash := header.Hash()
|
||||
return self.GetTd(hash, header.Number.Uint64()), hash, self.genesisBlock.Hash()
|
||||
}
|
||||
|
||||
// Reset purges the entire blockchain, restoring it to its genesis state.
|
||||
func (bc *LightChain) Reset() {
|
||||
bc.ResetWithGenesisBlock(bc.genesisBlock)
|
||||
@@ -231,6 +210,11 @@ func (bc *LightChain) Genesis() *types.Block {
|
||||
return bc.genesisBlock
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
// GetBody retrieves a block body (transactions and uncles) from the database
|
||||
// or ODR service by hash, caching it if found.
|
||||
func (self *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) {
|
||||
@@ -337,7 +321,7 @@ func (self *LightChain) postChainEvents(events []interface{}) {
|
||||
for _, event := range events {
|
||||
switch ev := event.(type) {
|
||||
case core.ChainEvent:
|
||||
if self.LastBlockHash() == ev.Hash {
|
||||
if self.CurrentHeader().Hash() == ev.Hash {
|
||||
self.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block})
|
||||
}
|
||||
self.chainFeed.Send(ev)
|
||||
@@ -393,16 +377,13 @@ func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
|
||||
return err
|
||||
}
|
||||
i, err := self.hc.InsertHeaderChain(chain, whFunc, start)
|
||||
go self.postChainEvents(events)
|
||||
self.postChainEvents(events)
|
||||
return i, err
|
||||
}
|
||||
|
||||
// CurrentHeader retrieves the current head header of the canonical chain. The
|
||||
// header is retrieved from the HeaderChain's internal cache.
|
||||
func (self *LightChain) CurrentHeader() *types.Header {
|
||||
self.mu.RLock()
|
||||
defer self.mu.RUnlock()
|
||||
|
||||
return self.hc.CurrentHeader()
|
||||
}
|
||||
|
||||
@@ -457,14 +438,17 @@ func (self *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64)
|
||||
return GetHeaderByNumber(ctx, self.odr, number)
|
||||
}
|
||||
|
||||
// Config retrieves the header chain's chain configuration.
|
||||
func (self *LightChain) Config() *params.ChainConfig { return self.hc.Config() }
|
||||
|
||||
func (self *LightChain) SyncCht(ctx context.Context) bool {
|
||||
if self.odr.ChtIndexer() == nil {
|
||||
return false
|
||||
}
|
||||
headNum := self.CurrentHeader().Number.Uint64()
|
||||
chtCount, _, _ := self.odr.ChtIndexer().Sections()
|
||||
if headNum+1 < chtCount*ChtFrequency {
|
||||
num := chtCount*ChtFrequency - 1
|
||||
if headNum+1 < chtCount*CHTFrequencyClient {
|
||||
num := chtCount*CHTFrequencyClient - 1
|
||||
header, err := GetHeaderByNumber(ctx, self.odr, num)
|
||||
if header != nil && err == nil {
|
||||
self.mu.Lock()
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ var (
|
||||
|
||||
// makeHeaderChain creates a deterministic chain of headers rooted at parent.
|
||||
func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) []*types.Header {
|
||||
blocks, _ := core.GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(parent), db, n, func(i int, b *core.BlockGen) {
|
||||
blocks, _ := core.GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(parent), ethash.NewFaker(), db, n, func(i int, b *core.BlockGen) {
|
||||
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
|
||||
})
|
||||
headers := make([]*types.Header, len(blocks))
|
||||
|
||||
+22
-15
@@ -1,4 +1,4 @@
|
||||
// Copyright 2014 The go-ethereum Authors
|
||||
// Copyright 2017 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
|
||||
@@ -22,14 +22,16 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
// NodeSet stores a set of trie nodes. It implements trie.Database and can also
|
||||
// act as a cache for another trie.Database.
|
||||
type NodeSet struct {
|
||||
db map[string][]byte
|
||||
nodes map[string][]byte
|
||||
order []string
|
||||
|
||||
dataSize int
|
||||
lock sync.RWMutex
|
||||
}
|
||||
@@ -37,7 +39,7 @@ type NodeSet struct {
|
||||
// NewNodeSet creates an empty node set
|
||||
func NewNodeSet() *NodeSet {
|
||||
return &NodeSet{
|
||||
db: make(map[string][]byte),
|
||||
nodes: make(map[string][]byte),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +48,15 @@ func (db *NodeSet) Put(key []byte, value []byte) error {
|
||||
db.lock.Lock()
|
||||
defer db.lock.Unlock()
|
||||
|
||||
if _, ok := db.db[string(key)]; !ok {
|
||||
db.db[string(key)] = common.CopyBytes(value)
|
||||
db.dataSize += len(value)
|
||||
if _, ok := db.nodes[string(key)]; ok {
|
||||
return nil
|
||||
}
|
||||
keystr := string(key)
|
||||
|
||||
db.nodes[keystr] = common.CopyBytes(value)
|
||||
db.order = append(db.order, keystr)
|
||||
db.dataSize += len(value)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -58,7 +65,7 @@ func (db *NodeSet) Get(key []byte) ([]byte, error) {
|
||||
db.lock.RLock()
|
||||
defer db.lock.RUnlock()
|
||||
|
||||
if entry, ok := db.db[string(key)]; ok {
|
||||
if entry, ok := db.nodes[string(key)]; ok {
|
||||
return entry, nil
|
||||
}
|
||||
return nil, errors.New("not found")
|
||||
@@ -75,7 +82,7 @@ func (db *NodeSet) KeyCount() int {
|
||||
db.lock.RLock()
|
||||
defer db.lock.RUnlock()
|
||||
|
||||
return len(db.db)
|
||||
return len(db.nodes)
|
||||
}
|
||||
|
||||
// DataSize returns the aggregated data size of nodes in the set
|
||||
@@ -92,27 +99,27 @@ func (db *NodeSet) NodeList() NodeList {
|
||||
defer db.lock.RUnlock()
|
||||
|
||||
var values NodeList
|
||||
for _, value := range db.db {
|
||||
values = append(values, value)
|
||||
for _, key := range db.order {
|
||||
values = append(values, db.nodes[key])
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// Store writes the contents of the set to the given database
|
||||
func (db *NodeSet) Store(target trie.Database) {
|
||||
func (db *NodeSet) Store(target ethdb.Putter) {
|
||||
db.lock.RLock()
|
||||
defer db.lock.RUnlock()
|
||||
|
||||
for key, value := range db.db {
|
||||
for key, value := range db.nodes {
|
||||
target.Put([]byte(key), value)
|
||||
}
|
||||
}
|
||||
|
||||
// NodeList stores an ordered list of trie nodes. It implements trie.DatabaseWriter.
|
||||
// NodeList stores an ordered list of trie nodes. It implements ethdb.Putter.
|
||||
type NodeList []rlp.RawValue
|
||||
|
||||
// Store writes the contents of the list to the given database
|
||||
func (n NodeList) Store(db trie.Database) {
|
||||
func (n NodeList) Store(db ethdb.Putter) {
|
||||
for _, node := range n {
|
||||
db.Put(crypto.Keccak256(node), node)
|
||||
}
|
||||
|
||||
+11
-13
@@ -50,8 +50,6 @@ var (
|
||||
|
||||
testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056")
|
||||
testContractAddr common.Address
|
||||
|
||||
bigTxGas = new(big.Int).SetUint64(params.TxGas)
|
||||
)
|
||||
|
||||
type testOdr struct {
|
||||
@@ -76,7 +74,7 @@ func (odr *testOdr) Retrieve(ctx context.Context, req OdrRequest) error {
|
||||
case *ReceiptsRequest:
|
||||
req.Receipts = core.GetBlockReceipts(odr.sdb, req.Hash, core.GetBlockNumber(odr.sdb, req.Hash))
|
||||
case *TrieRequest:
|
||||
t, _ := trie.New(req.Id.Root, odr.sdb)
|
||||
t, _ := trie.New(req.Id.Root, trie.NewDatabase(odr.sdb))
|
||||
nodes := NewNodeSet()
|
||||
t.Prove(req.Key, 0, nodes)
|
||||
req.Proof = nodes
|
||||
@@ -178,10 +176,10 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
|
||||
|
||||
// Perform read-only call.
|
||||
st.SetBalance(testBankAddress, math.MaxBig256)
|
||||
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)}
|
||||
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false)}
|
||||
context := core.NewEVMContext(msg, header, chain, nil)
|
||||
vmenv := vm.NewEVM(context, st, config, vm.Config{})
|
||||
gp := new(core.GasPool).AddGas(math.MaxBig256)
|
||||
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
||||
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
|
||||
res = append(res, ret...)
|
||||
if st.Error() != nil {
|
||||
@@ -196,17 +194,17 @@ func testChainGen(i int, block *core.BlockGen) {
|
||||
switch i {
|
||||
case 0:
|
||||
// In block 1, the test bank sends account #1 some ether.
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
|
||||
block.AddTx(tx)
|
||||
case 1:
|
||||
// In block 2, the test bank sends some more ether to account #1.
|
||||
// acc1Addr passes it on to account #2.
|
||||
// acc1Addr creates a test contract.
|
||||
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
|
||||
nonce := block.TxNonce(acc1Addr)
|
||||
tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key)
|
||||
tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
|
||||
nonce++
|
||||
tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(1000000), big.NewInt(0), testContractCode), signer, acc1Key)
|
||||
tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 1000000, big.NewInt(0), testContractCode), signer, acc1Key)
|
||||
testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
|
||||
block.AddTx(tx1)
|
||||
block.AddTx(tx2)
|
||||
@@ -216,7 +214,7 @@ func testChainGen(i int, block *core.BlockGen) {
|
||||
block.SetCoinbase(acc2Addr)
|
||||
block.SetExtra([]byte("yeehaw"))
|
||||
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey)
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
|
||||
block.AddTx(tx)
|
||||
case 3:
|
||||
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
|
||||
@@ -227,7 +225,7 @@ func testChainGen(i int, block *core.BlockGen) {
|
||||
b3.Extra = []byte("foo")
|
||||
block.AddUncle(b3)
|
||||
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey)
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
|
||||
block.AddTx(tx)
|
||||
}
|
||||
}
|
||||
@@ -241,8 +239,8 @@ func testChainOdr(t *testing.T, protocol int, fn odrTestFn) {
|
||||
)
|
||||
gspec.MustCommit(ldb)
|
||||
// Assemble the test environment
|
||||
blockchain, _ := core.NewBlockChain(sdb, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
|
||||
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, sdb, 4, testChainGen)
|
||||
blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
|
||||
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), sdb, 4, testChainGen)
|
||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
+42
-12
@@ -52,23 +52,20 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ
|
||||
for chtCount > 0 && canonicalHash != sectionHead && canonicalHash != (common.Hash{}) {
|
||||
chtCount--
|
||||
if chtCount > 0 {
|
||||
sectionHeadNum = chtCount*ChtFrequency - 1
|
||||
sectionHeadNum = chtCount*CHTFrequencyClient - 1
|
||||
sectionHead = odr.ChtIndexer().SectionHead(chtCount - 1)
|
||||
canonicalHash = core.GetCanonicalHash(db, sectionHeadNum)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if number >= chtCount*ChtFrequency {
|
||||
if number >= chtCount*CHTFrequencyClient {
|
||||
return nil, ErrNoTrustedCht
|
||||
}
|
||||
|
||||
r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, BlockNum: number}
|
||||
if err := odr.Retrieve(ctx, r); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return r.Header, nil
|
||||
}
|
||||
return r.Header, nil
|
||||
}
|
||||
|
||||
func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) {
|
||||
@@ -129,15 +126,48 @@ func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint
|
||||
// GetBlockReceipts retrieves the receipts generated by the transactions included
|
||||
// in a block given by its hash.
|
||||
func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) (types.Receipts, error) {
|
||||
// Retrieve the potentially incomplete receipts from disk or network
|
||||
receipts := core.GetBlockReceipts(odr.Database(), hash, number)
|
||||
if receipts != nil {
|
||||
return receipts, nil
|
||||
if receipts == nil {
|
||||
r := &ReceiptsRequest{Hash: hash, Number: number}
|
||||
if err := odr.Retrieve(ctx, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
receipts = r.Receipts
|
||||
}
|
||||
r := &ReceiptsRequest{Hash: hash, Number: number}
|
||||
if err := odr.Retrieve(ctx, r); err != nil {
|
||||
return nil, err
|
||||
// If the receipts are incomplete, fill the derived fields
|
||||
if len(receipts) > 0 && receipts[0].TxHash == (common.Hash{}) {
|
||||
block, err := GetBlock(ctx, odr, hash, number)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
genesis := core.GetCanonicalHash(odr.Database(), 0)
|
||||
config, _ := core.GetChainConfig(odr.Database(), genesis)
|
||||
|
||||
core.SetReceiptsData(config, block, receipts)
|
||||
core.WriteBlockReceipts(odr.Database(), hash, number, receipts)
|
||||
}
|
||||
return r.Receipts, nil
|
||||
return receipts, nil
|
||||
}
|
||||
|
||||
// GetBlockLogs retrieves the logs generated by the transactions included in a
|
||||
// block given by its hash.
|
||||
func GetBlockLogs(ctx context.Context, odr OdrBackend, hash common.Hash, number uint64) ([][]*types.Log, error) {
|
||||
// Retrieve the potentially incomplete receipts from disk or network
|
||||
receipts := core.GetBlockReceipts(odr.Database(), hash, number)
|
||||
if receipts == nil {
|
||||
r := &ReceiptsRequest{Hash: hash, Number: number}
|
||||
if err := odr.Retrieve(ctx, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
receipts = r.Receipts
|
||||
}
|
||||
// Return the logs without deriving any computed fields on the receipts
|
||||
logs := make([][]*types.Log, len(receipts))
|
||||
for i, receipt := range receipts {
|
||||
logs[i] = receipt.Logs
|
||||
}
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
// GetBloomBits retrieves a batch of compressed bloomBits vectors belonging to the given bit index and section indexes
|
||||
|
||||
+57
-46
@@ -1,4 +1,4 @@
|
||||
// Copyright 2016 The go-ethereum Authors
|
||||
// Copyright 2017 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
|
||||
@@ -19,7 +19,6 @@ package light
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
@@ -35,8 +34,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ChtFrequency = 32768
|
||||
ChtV1Frequency = 4096 // as long as we want to retain LES/1 compatibility, servers generate CHTs with the old, higher frequency
|
||||
// CHTFrequencyClient is the block frequency for creating CHTs on the client side.
|
||||
CHTFrequencyClient = 32768
|
||||
|
||||
// CHTFrequencyServer is the block frequency for creating CHTs on the server side.
|
||||
// Eventually this can be merged back with the client version, but that requires a
|
||||
// full database upgrade, so that should be left for a suitable moment.
|
||||
CHTFrequencyServer = 4096
|
||||
|
||||
HelperTrieConfirmations = 2048 // number of confirmations before a server is expected to have the given HelperTrie available
|
||||
HelperTrieProcessConfirmations = 256 // number of confirmations before a HelperTrie is generated
|
||||
)
|
||||
@@ -52,19 +57,19 @@ type trustedCheckpoint struct {
|
||||
|
||||
var (
|
||||
mainnetCheckpoint = trustedCheckpoint{
|
||||
name: "ETH mainnet",
|
||||
sectionIdx: 129,
|
||||
sectionHead: common.HexToHash("64100587c8ec9a76870056d07cb0f58622552d16de6253a59cac4b580c899501"),
|
||||
chtRoot: common.HexToHash("bb4fb4076cbe6923c8a8ce8f158452bbe19564959313466989fda095a60884ca"),
|
||||
bloomTrieRoot: common.HexToHash("0db524b2c4a2a9520a42fd842b02d2e8fb58ff37c75cf57bd0eb82daeace6716"),
|
||||
name: "mainnet",
|
||||
sectionIdx: 157,
|
||||
sectionHead: common.HexToHash("1963c080887ca7f406c2bb114293eea83e54f783f94df24b447f7e3b6317c747"),
|
||||
chtRoot: common.HexToHash("42abc436567dfb678a38fa6a9f881aa4c8a4cc8eaa2def08359292c3d0bd48ec"),
|
||||
bloomTrieRoot: common.HexToHash("281c9f8fb3cb8b37ae45e9907ef8f3b19cd22c54e297c2d6c09c1db1593dce42"),
|
||||
}
|
||||
|
||||
ropstenCheckpoint = trustedCheckpoint{
|
||||
name: "Ropsten testnet",
|
||||
sectionIdx: 50,
|
||||
sectionHead: common.HexToHash("00bd65923a1aa67f85e6b4ae67835784dd54be165c37f056691723c55bf016bd"),
|
||||
chtRoot: common.HexToHash("6f56dc61936752cc1f8c84b4addabdbe6a1c19693de3f21cb818362df2117f03"),
|
||||
bloomTrieRoot: common.HexToHash("aca7d7c504d22737242effc3fdc604a762a0af9ced898036b5986c3a15220208"),
|
||||
name: "ropsten",
|
||||
sectionIdx: 83,
|
||||
sectionHead: common.HexToHash("3ca623586bc0da35f1fc8d9b6b55950f3b1f69be9c6501846a2df672adb61236"),
|
||||
chtRoot: common.HexToHash("8f08ec7783969768c6ef06e5fe3398223cbf4ae2907b676da7b6fe6c7f55b059"),
|
||||
bloomTrieRoot: common.HexToHash("02d86d3c6a87f8f8a92c2a59bbba2132ff6f9f61b0915a5dc28a9d8279219fd0"),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -100,7 +105,7 @@ func GetChtRoot(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) c
|
||||
// GetChtV2Root reads the CHT root assoctiated to the given section from the database
|
||||
// Note that sectionIdx is specified according to LES/2 CHT section size
|
||||
func GetChtV2Root(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) common.Hash {
|
||||
return GetChtRoot(db, (sectionIdx+1)*(ChtFrequency/ChtV1Frequency)-1, sectionHead)
|
||||
return GetChtRoot(db, (sectionIdx+1)*(CHTFrequencyClient/CHTFrequencyServer)-1, sectionHead)
|
||||
}
|
||||
|
||||
// StoreChtRoot writes the CHT root assoctiated to the given section into the database
|
||||
@@ -113,7 +118,8 @@ func StoreChtRoot(db ethdb.Database, sectionIdx uint64, sectionHead, root common
|
||||
|
||||
// ChtIndexerBackend implements core.ChainIndexerBackend
|
||||
type ChtIndexerBackend struct {
|
||||
db, cdb ethdb.Database
|
||||
diskdb ethdb.Database
|
||||
triedb *trie.Database
|
||||
section, sectionSize uint64
|
||||
lastHash common.Hash
|
||||
trie *trie.Trie
|
||||
@@ -121,27 +127,31 @@ type ChtIndexerBackend struct {
|
||||
|
||||
// NewBloomTrieIndexer creates a BloomTrie chain indexer
|
||||
func NewChtIndexer(db ethdb.Database, clientMode bool) *core.ChainIndexer {
|
||||
cdb := ethdb.NewTable(db, ChtTablePrefix)
|
||||
idb := ethdb.NewTable(db, "chtIndex-")
|
||||
var sectionSize, confirmReq uint64
|
||||
if clientMode {
|
||||
sectionSize = ChtFrequency
|
||||
sectionSize = CHTFrequencyClient
|
||||
confirmReq = HelperTrieConfirmations
|
||||
} else {
|
||||
sectionSize = ChtV1Frequency
|
||||
sectionSize = CHTFrequencyServer
|
||||
confirmReq = HelperTrieProcessConfirmations
|
||||
}
|
||||
return core.NewChainIndexer(db, idb, &ChtIndexerBackend{db: db, cdb: cdb, sectionSize: sectionSize}, sectionSize, confirmReq, time.Millisecond*100, "cht")
|
||||
idb := ethdb.NewTable(db, "chtIndex-")
|
||||
backend := &ChtIndexerBackend{
|
||||
diskdb: db,
|
||||
triedb: trie.NewDatabase(ethdb.NewTable(db, ChtTablePrefix)),
|
||||
sectionSize: sectionSize,
|
||||
}
|
||||
return core.NewChainIndexer(db, idb, backend, sectionSize, confirmReq, time.Millisecond*100, "cht")
|
||||
}
|
||||
|
||||
// Reset implements core.ChainIndexerBackend
|
||||
func (c *ChtIndexerBackend) Reset(section uint64, lastSectionHead common.Hash) error {
|
||||
var root common.Hash
|
||||
if section > 0 {
|
||||
root = GetChtRoot(c.db, section-1, lastSectionHead)
|
||||
root = GetChtRoot(c.diskdb, section-1, lastSectionHead)
|
||||
}
|
||||
var err error
|
||||
c.trie, err = trie.New(root, c.cdb)
|
||||
c.trie, err = trie.New(root, c.triedb)
|
||||
c.section = section
|
||||
return err
|
||||
}
|
||||
@@ -151,7 +161,7 @@ func (c *ChtIndexerBackend) Process(header *types.Header) {
|
||||
hash, num := header.Hash(), header.Number.Uint64()
|
||||
c.lastHash = hash
|
||||
|
||||
td := core.GetTd(c.db, hash, num)
|
||||
td := core.GetTd(c.diskdb, hash, num)
|
||||
if td == nil {
|
||||
panic(nil)
|
||||
}
|
||||
@@ -163,17 +173,16 @@ func (c *ChtIndexerBackend) Process(header *types.Header) {
|
||||
|
||||
// Commit implements core.ChainIndexerBackend
|
||||
func (c *ChtIndexerBackend) Commit() error {
|
||||
batch := c.cdb.NewBatch()
|
||||
root, err := c.trie.CommitTo(batch)
|
||||
root, err := c.trie.Commit(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
batch.Write()
|
||||
if ((c.section+1)*c.sectionSize)%ChtFrequency == 0 {
|
||||
log.Info("Storing CHT", "idx", c.section*c.sectionSize/ChtFrequency, "sectionHead", fmt.Sprintf("%064x", c.lastHash), "root", fmt.Sprintf("%064x", root))
|
||||
}
|
||||
StoreChtRoot(c.db, c.section, c.lastHash, root)
|
||||
}
|
||||
c.triedb.Commit(root, false)
|
||||
|
||||
if ((c.section+1)*c.sectionSize)%CHTFrequencyClient == 0 {
|
||||
log.Info("Storing CHT", "section", c.section*c.sectionSize/CHTFrequencyClient, "head", c.lastHash, "root", root)
|
||||
}
|
||||
StoreChtRoot(c.diskdb, c.section, c.lastHash, root)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -205,7 +214,8 @@ func StoreBloomTrieRoot(db ethdb.Database, sectionIdx uint64, sectionHead, root
|
||||
|
||||
// BloomTrieIndexerBackend implements core.ChainIndexerBackend
|
||||
type BloomTrieIndexerBackend struct {
|
||||
db, cdb ethdb.Database
|
||||
diskdb ethdb.Database
|
||||
triedb *trie.Database
|
||||
section, parentSectionSize, bloomTrieRatio uint64
|
||||
trie *trie.Trie
|
||||
sectionHeads []common.Hash
|
||||
@@ -213,9 +223,12 @@ type BloomTrieIndexerBackend struct {
|
||||
|
||||
// NewBloomTrieIndexer creates a BloomTrie chain indexer
|
||||
func NewBloomTrieIndexer(db ethdb.Database, clientMode bool) *core.ChainIndexer {
|
||||
cdb := ethdb.NewTable(db, BloomTrieTablePrefix)
|
||||
backend := &BloomTrieIndexerBackend{
|
||||
diskdb: db,
|
||||
triedb: trie.NewDatabase(ethdb.NewTable(db, BloomTrieTablePrefix)),
|
||||
}
|
||||
idb := ethdb.NewTable(db, "bltIndex-")
|
||||
backend := &BloomTrieIndexerBackend{db: db, cdb: cdb}
|
||||
|
||||
var confirmReq uint64
|
||||
if clientMode {
|
||||
backend.parentSectionSize = BloomTrieFrequency
|
||||
@@ -233,10 +246,10 @@ func NewBloomTrieIndexer(db ethdb.Database, clientMode bool) *core.ChainIndexer
|
||||
func (b *BloomTrieIndexerBackend) Reset(section uint64, lastSectionHead common.Hash) error {
|
||||
var root common.Hash
|
||||
if section > 0 {
|
||||
root = GetBloomTrieRoot(b.db, section-1, lastSectionHead)
|
||||
root = GetBloomTrieRoot(b.diskdb, section-1, lastSectionHead)
|
||||
}
|
||||
var err error
|
||||
b.trie, err = trie.New(root, b.cdb)
|
||||
b.trie, err = trie.New(root, b.triedb)
|
||||
b.section = section
|
||||
return err
|
||||
}
|
||||
@@ -259,7 +272,7 @@ func (b *BloomTrieIndexerBackend) Commit() error {
|
||||
binary.BigEndian.PutUint64(encKey[2:10], b.section)
|
||||
var decomp []byte
|
||||
for j := uint64(0); j < b.bloomTrieRatio; j++ {
|
||||
data, err := core.GetBloomBits(b.db, i, b.section*b.bloomTrieRatio+j, b.sectionHeads[j])
|
||||
data, err := core.GetBloomBits(b.diskdb, i, b.section*b.bloomTrieRatio+j, b.sectionHeads[j])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -279,17 +292,15 @@ func (b *BloomTrieIndexerBackend) Commit() error {
|
||||
b.trie.Delete(encKey[:])
|
||||
}
|
||||
}
|
||||
|
||||
batch := b.cdb.NewBatch()
|
||||
root, err := b.trie.CommitTo(batch)
|
||||
root, err := b.trie.Commit(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
batch.Write()
|
||||
sectionHead := b.sectionHeads[b.bloomTrieRatio-1]
|
||||
log.Info("Storing BloomTrie", "section", b.section, "sectionHead", fmt.Sprintf("%064x", sectionHead), "root", fmt.Sprintf("%064x", root), "compression ratio", float64(compSize)/float64(decompSize))
|
||||
StoreBloomTrieRoot(b.db, b.section, sectionHead, root)
|
||||
}
|
||||
b.triedb.Commit(root, false)
|
||||
|
||||
sectionHead := b.sectionHeads[b.bloomTrieRatio-1]
|
||||
log.Info("Storing bloom trie", "section", b.section, "head", sectionHead, "root", root, "compression", float64(compSize)/float64(decompSize))
|
||||
StoreBloomTrieRoot(b.diskdb, b.section, sectionHead, root)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+15
-5
@@ -18,12 +18,14 @@ package light
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
@@ -83,6 +85,10 @@ func (db *odrDatabase) ContractCodeSize(addrHash, codeHash common.Hash) (int, er
|
||||
return len(code), err
|
||||
}
|
||||
|
||||
func (db *odrDatabase) TrieDB() *trie.Database {
|
||||
return nil
|
||||
}
|
||||
|
||||
type odrTrie struct {
|
||||
db *odrDatabase
|
||||
id *TrieID
|
||||
@@ -113,11 +119,11 @@ func (t *odrTrie) TryDelete(key []byte) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (t *odrTrie) CommitTo(db trie.DatabaseWriter) (common.Hash, error) {
|
||||
func (t *odrTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) {
|
||||
if t.trie == nil {
|
||||
return t.id.Root, nil
|
||||
}
|
||||
return t.trie.CommitTo(db)
|
||||
return t.trie.Commit(onleaf)
|
||||
}
|
||||
|
||||
func (t *odrTrie) Hash() common.Hash {
|
||||
@@ -135,13 +141,17 @@ func (t *odrTrie) GetKey(sha []byte) []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *odrTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
|
||||
return errors.New("not implemented, needs client/server interface split")
|
||||
}
|
||||
|
||||
// do tries and retries to execute a function until it returns with no error or
|
||||
// an error type other than MissingNodeError
|
||||
func (t *odrTrie) do(key []byte, fn func() error) error {
|
||||
for {
|
||||
var err error
|
||||
if t.trie == nil {
|
||||
t.trie, err = trie.New(t.id.Root, t.db.backend.Database())
|
||||
t.trie, err = trie.New(t.id.Root, trie.NewDatabase(t.db.backend.Database()))
|
||||
}
|
||||
if err == nil {
|
||||
err = fn()
|
||||
@@ -151,7 +161,7 @@ func (t *odrTrie) do(key []byte, fn func() error) error {
|
||||
}
|
||||
r := &TrieRequest{Id: t.id, Key: key}
|
||||
if err := t.db.backend.Retrieve(t.db.ctx, r); err != nil {
|
||||
return fmt.Errorf("can't fetch trie key %x: %v", key, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +177,7 @@ func newNodeIterator(t *odrTrie, startkey []byte) trie.NodeIterator {
|
||||
// Open the actual non-ODR trie if that hasn't happened yet.
|
||||
if t.trie == nil {
|
||||
it.do(func() error {
|
||||
t, err := trie.New(t.id.Root, t.db.backend.Database())
|
||||
t, err := trie.New(t.id.Root, trie.NewDatabase(t.db.backend.Database()))
|
||||
if err == nil {
|
||||
it.t.trie = t
|
||||
}
|
||||
|
||||
+2
-2
@@ -40,8 +40,8 @@ func TestNodeIterator(t *testing.T) {
|
||||
genesis = gspec.MustCommit(fulldb)
|
||||
)
|
||||
gspec.MustCommit(lightdb)
|
||||
blockchain, _ := core.NewBlockChain(fulldb, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
|
||||
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, fulldb, 4, testChainGen)
|
||||
blockchain, _ := core.NewBlockChain(fulldb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
|
||||
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), fulldb, 4, testChainGen)
|
||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
+6
-3
@@ -358,7 +358,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
|
||||
// Check the transaction doesn't exceed the current
|
||||
// block limit gas.
|
||||
header := pool.chain.GetHeaderByHash(pool.head)
|
||||
if header.GasLimit.Cmp(tx.Gas()) < 0 {
|
||||
if header.GasLimit < tx.Gas() {
|
||||
return core.ErrGasLimit
|
||||
}
|
||||
|
||||
@@ -376,10 +376,13 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
|
||||
}
|
||||
|
||||
// Should supply enough intrinsic gas
|
||||
if tx.Gas().Cmp(core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)) < 0 {
|
||||
gas, err := core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tx.Gas() < gas {
|
||||
return core.ErrIntrinsicGas
|
||||
}
|
||||
|
||||
return currentState.Error()
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -77,7 +77,7 @@ func txPoolTestChainGen(i int, block *core.BlockGen) {
|
||||
|
||||
func TestTxPool(t *testing.T) {
|
||||
for i := range testTx {
|
||||
testTx[i], _ = types.SignTx(types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), types.HomesteadSigner{}, testBankKey)
|
||||
testTx[i], _ = types.SignTx(types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -88,8 +88,8 @@ func TestTxPool(t *testing.T) {
|
||||
)
|
||||
gspec.MustCommit(ldb)
|
||||
// Assemble the test environment
|
||||
blockchain, _ := core.NewBlockChain(sdb, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
|
||||
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, sdb, poolTestBlocks, txPoolTestChainGen)
|
||||
blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
|
||||
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), sdb, poolTestBlocks, txPoolTestChainGen)
|
||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user