Skip to content

Commit 5f22105

Browse files
committed
add unit-test for fastnode
1 parent 5a254c4 commit 5f22105

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed

core/blockchain_notries_test.go

+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
// Copyright 2020 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
// Tests that abnormal program termination (i.e.crash) and restart doesn't leave
18+
// the database in some strange state with gaps in the chain, nor with block data
19+
// dangling in the future.
20+
21+
package core
22+
23+
import (
24+
"math/big"
25+
"testing"
26+
27+
"github.com/ethereum/go-ethereum/common"
28+
"github.com/ethereum/go-ethereum/consensus/ethash"
29+
"github.com/ethereum/go-ethereum/core/rawdb"
30+
"github.com/ethereum/go-ethereum/core/types"
31+
"github.com/ethereum/go-ethereum/core/vm"
32+
"github.com/ethereum/go-ethereum/ethdb/memorydb"
33+
"github.com/ethereum/go-ethereum/params"
34+
)
35+
36+
func newMockVerifyPeer() *mockVerifyPeer {
37+
return &mockVerifyPeer{}
38+
}
39+
40+
type requestRoot struct {
41+
blockNumber uint64
42+
blockHash common.Hash
43+
diffHash common.Hash
44+
}
45+
46+
// mockVerifyPeer is a mocking struct that simulates p2p signals for verification tasks.
47+
type mockVerifyPeer struct {
48+
callback func(*requestRoot)
49+
}
50+
51+
func (peer *mockVerifyPeer) setCallBack(callback func(*requestRoot)) {
52+
peer.callback = callback
53+
}
54+
55+
func (peer *mockVerifyPeer) RequestRoot(blockNumber uint64, blockHash common.Hash, diffHash common.Hash) error {
56+
if peer.callback != nil {
57+
peer.callback(&requestRoot{blockNumber, blockHash, diffHash})
58+
}
59+
return nil
60+
}
61+
62+
func (peer *mockVerifyPeer) ID() string {
63+
return "mock_peer"
64+
}
65+
66+
type mockVerifyPeers struct {
67+
peers []VerifyPeer
68+
}
69+
70+
func (peers *mockVerifyPeers) GetVerifyPeers() []VerifyPeer {
71+
return peers.peers
72+
}
73+
74+
func newMockRemoteVerifyPeer(peers []VerifyPeer) *mockVerifyPeers {
75+
return &mockVerifyPeers{peers}
76+
}
77+
78+
func makeTestBackendWithRemoteValidator(blocks int) (*testBackend, *testBackend, []*types.Block, error) {
79+
signer := types.HomesteadSigner{}
80+
81+
// Create a database pre-initialize with a genesis block
82+
db := rawdb.NewMemoryDatabase()
83+
db.SetDiffStore(memorydb.New())
84+
(&Genesis{
85+
Config: params.TestChainConfig,
86+
Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}},
87+
}).MustCommit(db)
88+
engine := ethash.NewFaker()
89+
90+
db2 := rawdb.NewMemoryDatabase()
91+
db2.SetDiffStore(memorydb.New())
92+
(&Genesis{
93+
Config: params.TestChainConfig,
94+
Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}},
95+
}).MustCommit(db2)
96+
engine2 := ethash.NewFaker()
97+
98+
peer := newMockVerifyPeer()
99+
peers := []VerifyPeer{peer}
100+
101+
verifier, err := NewBlockChain(db, nil, params.TestChainConfig, engine, vm.Config{},
102+
nil, nil, EnablePersistDiff(100000), EnableBlockValidator(params.TestChainConfig, engine2, LocalVerify, nil))
103+
if err != nil {
104+
return nil, nil, nil, err
105+
}
106+
107+
fastnode, err := NewBlockChain(db2, nil, params.TestChainConfig, engine2, vm.Config{},
108+
nil, nil, EnableBlockValidator(params.TestChainConfig, engine2, FullVerify, newMockRemoteVerifyPeer(peers)))
109+
if err != nil {
110+
return nil, nil, nil, err
111+
}
112+
113+
generator := func(i int, block *BlockGen) {
114+
// The chain maker doesn't have access to a chain, so the difficulty will be
115+
// lets unset (nil). Set it here to the correct value.
116+
block.SetCoinbase(testAddr)
117+
118+
for idx, testBlock := range testBlocks {
119+
// Specific block setting, the index in this generator has 1 diff from specified blockNr.
120+
if i+1 == testBlock.blockNr {
121+
for _, testTransaction := range testBlock.txs {
122+
var transaction *types.Transaction
123+
if testTransaction.to == nil {
124+
transaction = types.NewContractCreation(block.TxNonce(testAddr),
125+
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
126+
} else {
127+
transaction = types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
128+
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
129+
}
130+
tx, err := types.SignTx(transaction, signer, testKey)
131+
if err != nil {
132+
panic(err)
133+
}
134+
block.AddTxWithChain(verifier, tx)
135+
}
136+
break
137+
}
138+
139+
// Default block setting.
140+
if idx == len(testBlocks)-1 {
141+
// We want to simulate an empty middle block, having the same state as the
142+
// first one. The last is needs a state change again to force a reorg.
143+
for _, testTransaction := range testBlocks[0].txs {
144+
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
145+
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data), signer, testKey)
146+
if err != nil {
147+
panic(err)
148+
}
149+
block.AddTxWithChain(verifier, tx)
150+
}
151+
}
152+
}
153+
}
154+
155+
bs, _ := GenerateChain(params.TestChainConfig, verifier.Genesis(), ethash.NewFaker(), db, blocks, generator)
156+
157+
peer.setCallBack(func(req *requestRoot) {
158+
if fastnode.validator != nil && fastnode.validator.RemoteVerifyManager() != nil {
159+
fastnode.validator.RemoteVerifyManager().
160+
HandleRootResponse(
161+
verifier.GetRootByDiffHash(req.blockNumber, req.blockHash, req.diffHash), "mock")
162+
}
163+
})
164+
if _, err := verifier.InsertChain(bs); err != nil {
165+
return nil, nil, nil, err
166+
}
167+
168+
return &testBackend{
169+
db: db,
170+
chain: verifier,
171+
},
172+
&testBackend{
173+
db: db2,
174+
chain: fastnode,
175+
}, bs, nil
176+
}
177+
178+
func TestFastNode(t *testing.T) {
179+
_, fastnode, blocks, err := makeTestBackendWithRemoteValidator(10240)
180+
if err != nil {
181+
t.Fatalf(err.Error())
182+
}
183+
_, err = fastnode.chain.InsertChain(blocks)
184+
if err != nil {
185+
t.Fatalf(err.Error())
186+
}
187+
}

0 commit comments

Comments
 (0)