mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
use real ProcessWithParent for all chain manager tests. passing
This commit is contained in:
parent
6ef0f67b9f
commit
24523b893d
2 changed files with 175 additions and 97 deletions
|
|
@ -196,7 +196,6 @@ func (self *ChainManager) GetBlock(hash []byte) *types.Block {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,7 +228,8 @@ func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) {
|
||||||
return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.PrevHash)
|
return nil, fmt.Errorf("Unable to calculate total diff without known parent %x", block.PrevHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
parentTd := parent.BlockInfo().TD
|
//parentTd := parent.BlockInfo().TD
|
||||||
|
parentTd := self.BlockInfo(parent).TD
|
||||||
|
|
||||||
uncleDiff := new(big.Int)
|
uncleDiff := new(big.Int)
|
||||||
for _, uncle := range block.Uncles {
|
for _, uncle := range block.Uncles {
|
||||||
|
|
@ -246,8 +246,20 @@ func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) {
|
||||||
func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo {
|
func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo {
|
||||||
bi := types.BlockInfo{}
|
bi := types.BlockInfo{}
|
||||||
data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...))
|
data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...))
|
||||||
|
if len(data) == 0 {
|
||||||
|
if bc.workingChain != nil {
|
||||||
|
// Check the temp chain
|
||||||
|
for e := bc.workingChain.Front(); e != nil; e = e.Next() {
|
||||||
|
l := e.Value.(*link)
|
||||||
|
b := l.Block
|
||||||
|
if bytes.Compare(b.Hash(), block.Hash()) == 0 {
|
||||||
|
bi = types.BlockInfo{Number: b.Number.Uint64(), Hash: b.Hash(), Parent: b.PrevHash, TD: l.Td}
|
||||||
|
return bi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
bi.RlpDecode(data)
|
bi.RlpDecode(data)
|
||||||
|
|
||||||
return bi
|
return bi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,8 +287,10 @@ func (self *ChainManager) InsertChain(chain *BlockChain, call func(*types.Block,
|
||||||
for e := chain.Front(); e != nil; e = e.Next() {
|
for e := chain.Front(); e != nil; e = e.Next() {
|
||||||
link := e.Value.(*link)
|
link := e.Value.(*link)
|
||||||
|
|
||||||
self.add(link.Block)
|
// must set TD before adding as
|
||||||
|
// add calls writeBlockInfo which writes the most recent TD
|
||||||
self.SetTotalDifficulty(link.Td)
|
self.SetTotalDifficulty(link.Td)
|
||||||
|
self.add(link.Block)
|
||||||
|
|
||||||
call(link.Block, link.Messages)
|
call(link.Block, link.Messages)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,22 +16,15 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/wire"
|
"github.com/ethereum/go-ethereum/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// In these tests, TD = block.Number
|
|
||||||
var TD *big.Int
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
initDB()
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDB() {
|
||||||
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
|
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
|
||||||
ethutil.Config.Db, _ = ethdb.NewMemDatabase()
|
ethutil.Config.Db, _ = ethdb.NewMemDatabase()
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeproc struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self fakeproc) ProcessWithParent(a, b *types.Block) (*big.Int, state.Messages, error) {
|
|
||||||
TD = new(big.Int).Add(TD, big.NewInt(1))
|
|
||||||
return TD, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// So we can generate blocks easily
|
// So we can generate blocks easily
|
||||||
type fakePow struct{}
|
type fakePow struct{}
|
||||||
|
|
||||||
|
|
@ -56,61 +49,120 @@ func (e *fakeEth) ClientIdentity() wire.ClientIdentity { return n
|
||||||
func (e *fakeEth) Db() ethutil.Database { return nil }
|
func (e *fakeEth) Db() ethutil.Database { return nil }
|
||||||
func (e *fakeEth) EventMux() *event.TypeMux { return nil }
|
func (e *fakeEth) EventMux() *event.TypeMux { return nil }
|
||||||
|
|
||||||
func makechain(cman *ChainManager, max int) *BlockChain {
|
func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
|
||||||
blocks := make(types.Blocks, max)
|
block := types.CreateBlock(
|
||||||
for i := 0; i < max; i++ {
|
parent.Root(),
|
||||||
addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20)
|
parent.Hash(),
|
||||||
block := cman.NewBlock(addr)
|
addr,
|
||||||
if i != 0 {
|
ethutil.BigPow(2, 32),
|
||||||
cman.CurrentBlock = blocks[i-1]
|
nil,
|
||||||
}
|
"")
|
||||||
blocks[i] = block
|
block.MinGasPrice = big.NewInt(10000000000000)
|
||||||
}
|
block.Difficulty = CalcDifficulty(block, parent)
|
||||||
return NewChain(blocks)
|
block.Number = new(big.Int).Add(parent.Number, ethutil.Big1)
|
||||||
|
block.GasLimit = block.CalcGasLimit(parent)
|
||||||
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
func makechain2(bman *BlockManager, max int) *BlockChain {
|
// Actually make a block by simulating what miner would do
|
||||||
parent := bman.bc.CurrentBlock
|
func makeblock(bman *BlockManager, parent *types.Block, i int) *types.Block {
|
||||||
|
addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20)
|
||||||
|
block := newBlockFromParent(addr, parent)
|
||||||
|
cbase := block.State().GetOrNewStateObject(addr)
|
||||||
|
cbase.SetGasPool(block.CalcGasLimit(parent))
|
||||||
|
receipts, txs, _, _, _ := bman.ProcessTransactions(cbase, block.State(), block, block, types.Transactions{})
|
||||||
|
block.SetTransactions(txs)
|
||||||
|
block.SetReceipts(receipts)
|
||||||
|
bman.AccumelateRewards(block.State(), block, parent)
|
||||||
|
block.State().Update()
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a chain with real blocks
|
||||||
|
// Runs ProcessWithParent to get proper state roots
|
||||||
|
func makechain(bman *BlockManager, parent *types.Block, max int) *BlockChain {
|
||||||
|
bman.bc.CurrentBlock = parent
|
||||||
|
bman.bc.LastBlockHash = parent.Hash()
|
||||||
blocks := make(types.Blocks, max)
|
blocks := make(types.Blocks, max)
|
||||||
|
var td *big.Int
|
||||||
for i := 0; i < max; i++ {
|
for i := 0; i < max; i++ {
|
||||||
addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20)
|
block := makeblock(bman, parent, i)
|
||||||
block := bman.bc.NewBlock(addr)
|
// add the parent and its difficulty to the working chain
|
||||||
cbase := block.State().GetOrNewStateObject(addr)
|
// so ProcessWithParent can access it
|
||||||
cbase.SetGasPool(block.CalcGasLimit(parent))
|
bman.bc.workingChain = NewChain(types.Blocks{parent})
|
||||||
receipts, txs, _, _, _ := bman.ProcessTransactions(cbase, block.State(), block, block, types.Transactions{})
|
bman.bc.workingChain.Back().Value.(*link).Td = td
|
||||||
block.SetTransactions(txs)
|
td, _, _ = bman.bc.processor.ProcessWithParent(block, parent)
|
||||||
block.SetReceipts(receipts)
|
|
||||||
|
|
||||||
bman.AccumelateRewards(block.State(), block, parent)
|
|
||||||
|
|
||||||
block.State().Update()
|
|
||||||
lchain := NewChain(types.Blocks{block})
|
|
||||||
_, err := bman.bc.TestChain(lchain)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("failed to run test chain!:", err)
|
|
||||||
}
|
|
||||||
bman.bc.InsertChain(lchain, func(block *types.Block, _ state.Messages) {})
|
|
||||||
|
|
||||||
blocks[i] = block
|
blocks[i] = block
|
||||||
parent = block
|
parent = block
|
||||||
}
|
}
|
||||||
return NewChain(blocks)
|
lchain := NewChain(blocks)
|
||||||
|
return lchain
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a new canonical chain by running TestChain and InsertChain
|
||||||
|
// on result of makechain
|
||||||
|
func newCanonical(n int) (*BlockManager, error) {
|
||||||
|
bman := &BlockManager{bc: NewChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||||
|
bman.bc.SetProcessor(bman)
|
||||||
|
parent := bman.bc.CurrentBlock
|
||||||
|
lchain := makechain(bman, parent, 5)
|
||||||
|
|
||||||
|
_, err := bman.bc.TestChain(lchain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bman.bc.InsertChain(lchain, func(block *types.Block, _ state.Messages) {})
|
||||||
|
return bman, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// new chain manager without setLastBlock
|
||||||
|
func newChainManager() *ChainManager {
|
||||||
|
bc := &ChainManager{}
|
||||||
|
bc.genesisBlock = types.NewBlockFromBytes(ethutil.Encode(Genesis))
|
||||||
|
bc.Reset()
|
||||||
|
return bc
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtendCanonical(t *testing.T) {
|
||||||
|
initDB()
|
||||||
|
// make first chain starting from genesis
|
||||||
|
bman, err := newCanonical(5)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Could not make new canonical chain:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make second chain starting from end of first chain
|
||||||
|
bman2 := &BlockManager{bc: NewChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||||
|
bman2.bc.SetProcessor(bman2)
|
||||||
|
parent := bman.bc.CurrentBlock
|
||||||
|
chainB := makechain(bman2, parent, 3)
|
||||||
|
|
||||||
|
// test second chain against first
|
||||||
|
td2, err := bman.bc.TestChain(chainB)
|
||||||
|
if err != nil && !IsTDError(err) {
|
||||||
|
t.Error("expected chainB not to give errors:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if td2.Cmp(bman.bc.TD) <= 0 {
|
||||||
|
t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", bman.bc.TD)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShorterFork(t *testing.T) {
|
func TestShorterFork(t *testing.T) {
|
||||||
cman := NewChainManager()
|
initDB()
|
||||||
bman := &BlockManager{bc: cman, Pow: fakePow{}, eth: &fakeEth{}}
|
// make first chain starting from genesis
|
||||||
bman.bc.SetProcessor(bman)
|
bman, err := newCanonical(5)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Could not make new canonical chain:", err)
|
||||||
|
}
|
||||||
|
|
||||||
makechain2(bman, 5)
|
// make second, shorter chain, starting from genesis
|
||||||
|
bman2 := &BlockManager{bc: newChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||||
cman2 := NewChainManager()
|
|
||||||
cman2.Reset() // so we don't end up with last block of cman1
|
|
||||||
bman2 := &BlockManager{bc: cman2, Pow: fakePow{}, eth: &fakeEth{}}
|
|
||||||
bman2.bc.SetProcessor(bman2)
|
bman2.bc.SetProcessor(bman2)
|
||||||
|
parent := bman2.bc.CurrentBlock
|
||||||
|
chainB := makechain(bman2, parent, 3)
|
||||||
|
|
||||||
chainB := makechain2(bman2, 3)
|
// test second chain against first
|
||||||
|
|
||||||
td2, err := bman.bc.TestChain(chainB)
|
td2, err := bman.bc.TestChain(chainB)
|
||||||
if err != nil && !IsTDError(err) {
|
if err != nil && !IsTDError(err) {
|
||||||
t.Error("expected chainB not to give errors:", err)
|
t.Error("expected chainB not to give errors:", err)
|
||||||
|
|
@ -122,76 +174,88 @@ func TestShorterFork(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLongerFork(t *testing.T) {
|
func TestLongerFork(t *testing.T) {
|
||||||
cman := NewChainManager()
|
initDB()
|
||||||
cman.SetProcessor(fakeproc{})
|
// make first chain starting from genesis
|
||||||
|
bman, err := newCanonical(5)
|
||||||
TD = big.NewInt(1)
|
|
||||||
chainA := makechain(cman, 5)
|
|
||||||
|
|
||||||
TD = big.NewInt(1)
|
|
||||||
chainB := makechain(cman, 10)
|
|
||||||
|
|
||||||
td, err := cman.TestChain(chainA)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("unable to create new TD from chainA:", err)
|
t.Fatal("Could not make new canonical chain:", err)
|
||||||
}
|
}
|
||||||
cman.TD = td
|
|
||||||
|
|
||||||
_, err = cman.TestChain(chainB)
|
// make second, longer chain, starting from genesis
|
||||||
|
bman2 := &BlockManager{bc: newChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||||
|
bman2.bc.SetProcessor(bman2)
|
||||||
|
parent := bman2.bc.CurrentBlock
|
||||||
|
chainB := makechain(bman2, parent, 10)
|
||||||
|
|
||||||
|
td, err := bman.bc.TestChain(chainB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("expected chainB not to give errors:", err)
|
t.Error("expected chainB not to give errors:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if td.Cmp(bman.bc.TD) <= 0 {
|
||||||
|
t.Error("expected chainB to have higher difficulty. Got", td, "expected more than", bman.bc.TD)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEqualFork(t *testing.T) {
|
func TestEqualFork(t *testing.T) {
|
||||||
cman := NewChainManager()
|
initDB()
|
||||||
cman.SetProcessor(fakeproc{})
|
bman, err := newCanonical(5)
|
||||||
|
|
||||||
TD = big.NewInt(1)
|
|
||||||
chainA := makechain(cman, 5)
|
|
||||||
|
|
||||||
TD = big.NewInt(2)
|
|
||||||
chainB := makechain(cman, 5)
|
|
||||||
|
|
||||||
td, err := cman.TestChain(chainA)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("unable to create new TD from chainA:", err)
|
t.Fatal("Could not make new canonical chain:", err)
|
||||||
}
|
}
|
||||||
cman.TD = td
|
|
||||||
|
|
||||||
_, err = cman.TestChain(chainB)
|
bman2 := &BlockManager{bc: newChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||||
if err != nil {
|
bman2.bc.SetProcessor(bman2)
|
||||||
|
parent := bman2.bc.CurrentBlock
|
||||||
|
|
||||||
|
chainB := makechain(bman2, parent, 5)
|
||||||
|
|
||||||
|
td, err := bman.bc.TestChain(chainB)
|
||||||
|
if err != nil && !IsTDError(err) {
|
||||||
t.Error("expected chainB not to give errors:", err)
|
t.Error("expected chainB not to give errors:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if td.Cmp(bman.bc.TD) != 0 {
|
||||||
|
t.Error("expected chainB to have equal difficulty. Got", td, "expected less than", bman.bc.TD)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBrokenChain(t *testing.T) {
|
func TestBrokenChain(t *testing.T) {
|
||||||
cman := NewChainManager()
|
initDB()
|
||||||
cman.SetProcessor(fakeproc{})
|
bman, err := newCanonical(5)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Could not make new canonical chain:", err)
|
||||||
|
}
|
||||||
|
|
||||||
TD = big.NewInt(1)
|
bman2 := &BlockManager{bc: NewChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||||
chain := makechain(cman, 5)
|
bman2.bc.SetProcessor(bman2)
|
||||||
chain.Remove(chain.Front())
|
parent := bman2.bc.CurrentBlock
|
||||||
|
|
||||||
_, err := cman.TestChain(chain)
|
chainB := makechain(bman2, parent, 5)
|
||||||
|
chainB.Remove(chainB.Front())
|
||||||
|
|
||||||
|
_, err = bman.bc.TestChain(chainB)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected broken chain to return error")
|
t.Error("expected broken chain to return error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkChainTesting(b *testing.B) {
|
func BenchmarkChainTesting(b *testing.B) {
|
||||||
|
initDB()
|
||||||
const chainlen = 1000
|
const chainlen = 1000
|
||||||
|
|
||||||
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
|
bman, err := newCanonical(5)
|
||||||
ethutil.Config.Db, _ = ethdb.NewMemDatabase()
|
if err != nil {
|
||||||
|
b.Fatal("Could not make new canonical chain:", err)
|
||||||
|
}
|
||||||
|
|
||||||
cman := NewChainManager()
|
bman2 := &BlockManager{bc: NewChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||||
cman.SetProcessor(fakeproc{})
|
bman2.bc.SetProcessor(bman2)
|
||||||
|
parent := bman2.bc.CurrentBlock
|
||||||
|
|
||||||
TD = big.NewInt(1)
|
chain := makechain(bman2, parent, chainlen)
|
||||||
chain := makechain(cman, chainlen)
|
|
||||||
|
|
||||||
stime := time.Now()
|
stime := time.Now()
|
||||||
cman.TestChain(chain)
|
bman.bc.TestChain(chain)
|
||||||
fmt.Println(chainlen, "took", time.Since(stime))
|
fmt.Println(chainlen, "took", time.Since(stime))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue