Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
9446489c
Commit
9446489c
authored
Feb 18, 2015
by
Ethan Buchman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: chain manager forking tests
parent
2ba65f4f
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
276 additions
and
0 deletions
+276
-0
chain_manager_test.go
core/chain_manager_test.go
+276
-0
No files found.
core/chain_manager_test.go
View file @
9446489c
...
...
@@ -3,6 +3,7 @@ package core
import
(
"bytes"
"fmt"
"math/big"
"os"
"path"
"runtime"
...
...
@@ -13,14 +14,167 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/state"
)
// So we can generate blocks easily
type
fakePow
struct
{}
func
(
f
fakePow
)
Search
(
block
pow
.
Block
,
stop
<-
chan
struct
{})
[]
byte
{
return
nil
}
func
(
f
fakePow
)
Verify
(
block
pow
.
Block
)
bool
{
return
true
}
func
(
f
fakePow
)
GetHashrate
()
int64
{
return
0
}
func
(
f
fakePow
)
Turbo
(
bool
)
{}
func
init
()
{
runtime
.
GOMAXPROCS
(
runtime
.
NumCPU
())
ethutil
.
ReadConfig
(
"/tmp/ethtest"
,
"/tmp/ethtest"
,
"ETH"
)
}
func
newBlockFromParent
(
addr
[]
byte
,
parent
*
types
.
Block
)
*
types
.
Block
{
block
:=
types
.
NewBlock
(
parent
.
Hash
(),
addr
,
parent
.
Root
(),
ethutil
.
BigPow
(
2
,
32
),
nil
,
""
)
block
.
SetUncles
(
nil
)
block
.
SetTransactions
(
nil
)
block
.
SetReceipts
(
nil
)
header
:=
block
.
Header
()
header
.
Difficulty
=
CalcDifficulty
(
block
,
parent
)
header
.
Number
=
new
(
big
.
Int
)
.
Add
(
parent
.
Header
()
.
Number
,
ethutil
.
Big1
)
header
.
GasLimit
=
CalcGasLimit
(
parent
,
block
)
block
.
Td
=
parent
.
Td
return
block
}
// Actually make a block by simulating what miner would do
func
makeBlock
(
bman
*
BlockProcessor
,
parent
*
types
.
Block
,
i
int
,
db
ethutil
.
Database
)
*
types
.
Block
{
addr
:=
ethutil
.
LeftPadBytes
([]
byte
{
byte
(
i
)},
20
)
block
:=
newBlockFromParent
(
addr
,
parent
)
state
:=
state
.
New
(
block
.
Root
(),
db
)
cbase
:=
state
.
GetOrNewStateObject
(
addr
)
cbase
.
SetGasPool
(
CalcGasLimit
(
parent
,
block
))
cbase
.
AddAmount
(
BlockReward
)
state
.
Update
(
ethutil
.
Big0
)
block
.
SetRoot
(
state
.
Root
())
return
block
}
// Make a chain with real blocks
// Runs ProcessWithParent to get proper state roots
func
makeChain
(
bman
*
BlockProcessor
,
parent
*
types
.
Block
,
max
int
,
db
ethutil
.
Database
)
types
.
Blocks
{
bman
.
bc
.
currentBlock
=
parent
blocks
:=
make
(
types
.
Blocks
,
max
)
for
i
:=
0
;
i
<
max
;
i
++
{
block
:=
makeBlock
(
bman
,
parent
,
i
,
db
)
td
,
err
:=
bman
.
processWithParent
(
block
,
parent
)
if
err
!=
nil
{
fmt
.
Println
(
"process with parent failed"
,
err
)
panic
(
err
)
}
block
.
Td
=
td
blocks
[
i
]
=
block
parent
=
block
fmt
.
Printf
(
"New Block: %x
\n
"
,
block
.
Hash
())
}
fmt
.
Println
(
"Done making chain"
)
return
blocks
}
// Create a new chain manager starting from given block
// Effectively a fork factory
func
newChainManager
(
block
*
types
.
Block
,
eventMux
*
event
.
TypeMux
,
db
ethutil
.
Database
)
*
ChainManager
{
bc
:=
&
ChainManager
{
db
:
db
,
genesisBlock
:
GenesisBlock
(
db
),
eventMux
:
eventMux
}
if
block
==
nil
{
bc
.
Reset
()
}
else
{
bc
.
currentBlock
=
block
bc
.
td
=
block
.
Td
}
return
bc
}
// block processor with fake pow
func
newBlockProcessor
(
db
ethutil
.
Database
,
txpool
*
TxPool
,
cman
*
ChainManager
,
eventMux
*
event
.
TypeMux
)
*
BlockProcessor
{
bman
:=
NewBlockProcessor
(
db
,
txpool
,
newChainManager
(
nil
,
eventMux
,
db
),
eventMux
)
bman
.
Pow
=
fakePow
{}
return
bman
}
// Make a new canonical chain by running InsertChain
// on result of makeChain
func
newCanonical
(
n
int
,
db
ethutil
.
Database
)
(
*
BlockProcessor
,
error
)
{
eventMux
:=
&
event
.
TypeMux
{}
txpool
:=
NewTxPool
(
eventMux
)
bman
:=
newBlockProcessor
(
db
,
txpool
,
newChainManager
(
nil
,
eventMux
,
db
),
eventMux
)
bman
.
bc
.
SetProcessor
(
bman
)
parent
:=
bman
.
bc
.
CurrentBlock
()
if
n
==
0
{
return
bman
,
nil
}
lchain
:=
makeChain
(
bman
,
parent
,
n
,
db
)
bman
.
bc
.
InsertChain
(
lchain
)
return
bman
,
nil
}
// Test fork of length N starting from block i
func
testFork
(
t
*
testing
.
T
,
bman
*
BlockProcessor
,
i
,
N
int
,
f
func
(
td1
,
td2
*
big
.
Int
))
{
fmt
.
Println
(
"Testing Fork!"
)
var
b
*
types
.
Block
=
nil
if
i
>
0
{
b
=
bman
.
bc
.
GetBlockByNumber
(
uint64
(
i
))
}
_
=
b
// switch databases to process the new chain
db
,
err
:=
ethdb
.
NewMemDatabase
()
if
err
!=
nil
{
t
.
Fatal
(
"Failed to create db:"
,
err
)
}
// copy old chain up to i into new db with deterministic canonical
bman2
,
err
:=
newCanonical
(
i
,
db
)
if
err
!=
nil
{
t
.
Fatal
(
"could not make new canonical in testFork"
,
err
)
}
bman2
.
bc
.
SetProcessor
(
bman2
)
parent
:=
bman2
.
bc
.
CurrentBlock
()
chainB
:=
makeChain
(
bman2
,
parent
,
N
,
db
)
bman2
.
bc
.
InsertChain
(
chainB
)
tdpre
:=
bman
.
bc
.
Td
()
td
,
err
:=
testChain
(
chainB
,
bman
)
if
err
!=
nil
{
t
.
Fatal
(
"expected chainB not to give errors:"
,
err
)
}
// Compare difficulties
f
(
tdpre
,
td
)
}
func
testChain
(
chainB
types
.
Blocks
,
bman
*
BlockProcessor
)
(
*
big
.
Int
,
error
)
{
td
:=
new
(
big
.
Int
)
for
_
,
block
:=
range
chainB
{
td2
,
err
:=
bman
.
bc
.
processor
.
Process
(
block
)
if
err
!=
nil
{
if
IsKnownBlockErr
(
err
)
{
continue
}
return
nil
,
err
}
block
.
Td
=
td2
td
=
td2
bman
.
bc
.
mu
.
Lock
()
{
bman
.
bc
.
write
(
block
)
}
bman
.
bc
.
mu
.
Unlock
()
}
return
td
,
nil
}
func
loadChain
(
fn
string
,
t
*
testing
.
T
)
(
types
.
Blocks
,
error
)
{
fh
,
err
:=
os
.
OpenFile
(
path
.
Join
(
os
.
Getenv
(
"GOPATH"
),
"src"
,
"github.com"
,
"ethereum"
,
"go-ethereum"
,
"_data"
,
fn
),
os
.
O_RDONLY
,
os
.
ModePerm
)
if
err
!=
nil
{
...
...
@@ -45,6 +199,128 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *
done
<-
true
}
func
TestExtendCanonical
(
t
*
testing
.
T
)
{
db
,
err
:=
ethdb
.
NewMemDatabase
()
if
err
!=
nil
{
t
.
Fatal
(
"Failed to create db:"
,
err
)
}
// make first chain starting from genesis
bman
,
err
:=
newCanonical
(
5
,
db
)
if
err
!=
nil
{
t
.
Fatal
(
"Could not make new canonical chain:"
,
err
)
}
f
:=
func
(
td1
,
td2
*
big
.
Int
)
{
if
td2
.
Cmp
(
td1
)
<=
0
{
t
.
Error
(
"expected chainB to have higher difficulty. Got"
,
td2
,
"expected more than"
,
td1
)
}
}
// Start fork from current height (5)
testFork
(
t
,
bman
,
5
,
1
,
f
)
testFork
(
t
,
bman
,
5
,
2
,
f
)
testFork
(
t
,
bman
,
5
,
5
,
f
)
testFork
(
t
,
bman
,
5
,
10
,
f
)
}
func
TestShorterFork
(
t
*
testing
.
T
)
{
db
,
err
:=
ethdb
.
NewMemDatabase
()
if
err
!=
nil
{
t
.
Fatal
(
"Failed to create db:"
,
err
)
}
// make first chain starting from genesis
bman
,
err
:=
newCanonical
(
10
,
db
)
if
err
!=
nil
{
t
.
Fatal
(
"Could not make new canonical chain:"
,
err
)
}
f
:=
func
(
td1
,
td2
*
big
.
Int
)
{
if
td2
.
Cmp
(
td1
)
>=
0
{
t
.
Error
(
"expected chainB to have lower difficulty. Got"
,
td2
,
"expected less than"
,
td1
)
}
}
// Sum of numbers must be less than 10
// for this to be a shorter fork
testFork
(
t
,
bman
,
0
,
3
,
f
)
testFork
(
t
,
bman
,
0
,
7
,
f
)
testFork
(
t
,
bman
,
1
,
1
,
f
)
testFork
(
t
,
bman
,
1
,
7
,
f
)
testFork
(
t
,
bman
,
5
,
3
,
f
)
testFork
(
t
,
bman
,
5
,
4
,
f
)
}
func
TestLongerFork
(
t
*
testing
.
T
)
{
db
,
err
:=
ethdb
.
NewMemDatabase
()
if
err
!=
nil
{
t
.
Fatal
(
"Failed to create db:"
,
err
)
}
// make first chain starting from genesis
bman
,
err
:=
newCanonical
(
10
,
db
)
if
err
!=
nil
{
t
.
Fatal
(
"Could not make new canonical chain:"
,
err
)
}
f
:=
func
(
td1
,
td2
*
big
.
Int
)
{
if
td2
.
Cmp
(
td1
)
<=
0
{
t
.
Error
(
"expected chainB to have higher difficulty. Got"
,
td2
,
"expected more than"
,
td1
)
}
}
// Sum of numbers must be greater than 10
// for this to be a longer fork
testFork
(
t
,
bman
,
0
,
11
,
f
)
testFork
(
t
,
bman
,
0
,
15
,
f
)
testFork
(
t
,
bman
,
1
,
10
,
f
)
testFork
(
t
,
bman
,
1
,
12
,
f
)
testFork
(
t
,
bman
,
5
,
6
,
f
)
testFork
(
t
,
bman
,
5
,
8
,
f
)
}
func
TestEqualFork
(
t
*
testing
.
T
)
{
db
,
err
:=
ethdb
.
NewMemDatabase
()
if
err
!=
nil
{
t
.
Fatal
(
"Failed to create db:"
,
err
)
}
bman
,
err
:=
newCanonical
(
10
,
db
)
if
err
!=
nil
{
t
.
Fatal
(
"Could not make new canonical chain:"
,
err
)
}
f
:=
func
(
td1
,
td2
*
big
.
Int
)
{
if
td2
.
Cmp
(
td1
)
!=
0
{
t
.
Error
(
"expected chainB to have equal difficulty. Got"
,
td2
,
"expected "
,
td1
)
}
}
// Sum of numbers must be equal to 10
// for this to be an equal fork
testFork
(
t
,
bman
,
1
,
9
,
f
)
testFork
(
t
,
bman
,
2
,
8
,
f
)
testFork
(
t
,
bman
,
5
,
5
,
f
)
testFork
(
t
,
bman
,
6
,
4
,
f
)
testFork
(
t
,
bman
,
9
,
1
,
f
)
}
func
TestBrokenChain
(
t
*
testing
.
T
)
{
db
,
err
:=
ethdb
.
NewMemDatabase
()
if
err
!=
nil
{
t
.
Fatal
(
"Failed to create db:"
,
err
)
}
bman
,
err
:=
newCanonical
(
10
,
db
)
if
err
!=
nil
{
t
.
Fatal
(
"Could not make new canonical chain:"
,
err
)
}
db2
,
err
:=
ethdb
.
NewMemDatabase
()
if
err
!=
nil
{
t
.
Fatal
(
"Failed to create db:"
,
err
)
}
bman2
,
err
:=
newCanonical
(
10
,
db2
)
if
err
!=
nil
{
t
.
Fatal
(
"Could not make new canonical chain:"
,
err
)
}
bman2
.
bc
.
SetProcessor
(
bman2
)
parent
:=
bman2
.
bc
.
CurrentBlock
()
chainB
:=
makeChain
(
bman2
,
parent
,
5
,
db2
)
chainB
=
chainB
[
1
:
]
_
,
err
=
testChain
(
chainB
,
bman
)
if
err
==
nil
{
t
.
Error
(
"expected broken chain to return error"
)
}
}
func
TestChainInsertions
(
t
*
testing
.
T
)
{
t
.
Skip
()
// travil fails.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment