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
a4e19c5c
Unverified
Commit
a4e19c5c
authored
2 years ago
by
Marius van der Wijden
Committed by
Péter Szilágyi
2 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
all: implement forkid changes for shanghai
parent
efc9409c
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
277 additions
and
48 deletions
+277
-48
chain.go
cmd/devp2p/internal/ethtest/chain.go
+1
-1
forkid.go
core/forkid/forkid.go
+80
-35
forkid_test.go
core/forkid/forkid_test.go
+186
-2
handler.go
eth/handler.go
+1
-1
discovery.go
eth/protocols/eth/discovery.go
+1
-1
handshake_test.go
eth/protocols/eth/handshake_test.go
+1
-1
client_handler.go
les/client_handler.go
+1
-1
peer_test.go
les/peer_test.go
+2
-2
server_handler.go
les/server_handler.go
+1
-1
test_helper.go
les/test_helper.go
+2
-2
state_test.go
tests/state_test.go
+1
-1
No files found.
cmd/devp2p/internal/ethtest/chain.go
View file @
a4e19c5c
...
...
@@ -76,7 +76,7 @@ func (c *Chain) RootAt(height int) common.Hash {
// ForkID gets the fork id of the chain.
func
(
c
*
Chain
)
ForkID
()
forkid
.
ID
{
return
forkid
.
NewID
(
c
.
chainConfig
,
c
.
blocks
[
0
]
.
Hash
(),
uint64
(
c
.
Len
()))
return
forkid
.
NewID
(
c
.
chainConfig
,
c
.
blocks
[
0
]
.
Hash
(),
uint64
(
c
.
Len
())
,
c
.
blocks
[
0
]
.
Time
()
)
}
// Shorten returns a copy chain of a desired height from the imported
...
...
This diff is collapsed.
Click to expand it.
core/forkid/forkid.go
View file @
a4e19c5c
...
...
@@ -24,6 +24,7 @@ import (
"math"
"math/big"
"reflect"
"sort"
"strings"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -65,19 +66,28 @@ type ID struct {
// Filter is a fork id filter to validate a remotely advertised ID.
type
Filter
func
(
id
ID
)
error
// NewID calculates the Ethereum fork ID from the chain config, genesis hash,
and head
.
func
NewID
(
config
*
params
.
ChainConfig
,
genesis
common
.
Hash
,
head
uint64
)
ID
{
// NewID calculates the Ethereum fork ID from the chain config, genesis hash,
head and time
.
func
NewID
(
config
*
params
.
ChainConfig
,
genesis
common
.
Hash
,
head
,
time
uint64
)
ID
{
// Calculate the starting checksum from the genesis hash
hash
:=
crc32
.
ChecksumIEEE
(
genesis
[
:
])
// Calculate the current fork checksum and the next fork block
var
next
uint64
for
_
,
fork
:=
range
gatherForks
(
config
)
{
forks
,
forksByTime
:=
gatherForks
(
config
)
for
_
,
fork
:=
range
forks
{
if
fork
<=
head
{
// Fork already passed, checksum the previous hash and the fork number
hash
=
checksumUpdate
(
hash
,
fork
)
continue
}
return
ID
{
Hash
:
checksumToBytes
(
hash
),
Next
:
fork
}
}
var
next
uint64
for
_
,
fork
:=
range
forksByTime
{
if
time
>=
fork
{
// Fork passed, checksum previous hash and fork time
hash
=
checksumUpdate
(
hash
,
fork
)
continue
}
next
=
fork
break
}
...
...
@@ -90,6 +100,7 @@ func NewIDWithChain(chain Blockchain) ID {
chain
.
Config
(),
chain
.
Genesis
()
.
Hash
(),
chain
.
CurrentHeader
()
.
Number
.
Uint64
(),
chain
.
CurrentHeader
()
.
Time
,
)
}
...
...
@@ -99,36 +110,40 @@ func NewFilter(chain Blockchain) Filter {
return
newFilter
(
chain
.
Config
(),
chain
.
Genesis
()
.
Hash
(),
func
()
uint64
{
return
chain
.
CurrentHeader
()
.
Number
.
Uint64
()
func
()
(
uint64
,
uint64
)
{
return
chain
.
CurrentHeader
()
.
Number
.
Uint64
()
,
chain
.
CurrentHeader
()
.
Time
},
)
}
// NewStaticFilter creates a filter at block zero.
func
NewStaticFilter
(
config
*
params
.
ChainConfig
,
genesis
common
.
Hash
)
Filter
{
head
:=
func
()
uint64
{
return
0
}
head
:=
func
()
(
uint64
,
uint64
)
{
return
0
,
0
}
return
newFilter
(
config
,
genesis
,
head
)
}
// newFilter is the internal version of NewFilter, taking closures as its arguments
// instead of a chain. The reason is to allow testing it without having to simulate
// an entire blockchain.
func
newFilter
(
config
*
params
.
ChainConfig
,
genesis
common
.
Hash
,
headfn
func
()
uint64
)
Filter
{
func
newFilter
(
config
*
params
.
ChainConfig
,
genesis
common
.
Hash
,
headfn
func
()
(
uint64
,
uint64
)
)
Filter
{
// Calculate the all the valid fork hash and fork next combos
var
(
forks
=
gatherForks
(
config
)
sums
=
make
([][
4
]
byte
,
len
(
forks
)
+
1
)
// 0th is the genesis
forks
,
forksByTime
=
gatherForks
(
config
)
sums
=
make
([][
4
]
byte
,
len
(
forks
)
+
len
(
forksByTime
)
+
1
)
// 0th is the genesis
)
allForks
:=
append
(
forks
,
forksByTime
...
)
hash
:=
crc32
.
ChecksumIEEE
(
genesis
[
:
])
sums
[
0
]
=
checksumToBytes
(
hash
)
for
i
,
fork
:=
range
f
orks
{
for
i
,
fork
:=
range
allF
orks
{
hash
=
checksumUpdate
(
hash
,
fork
)
sums
[
i
+
1
]
=
checksumToBytes
(
hash
)
}
// Add two sentries to simplify the fork checks and don't require special
// casing the last one.
forks
=
append
(
forks
,
math
.
MaxUint64
)
// Last fork will never be passed
if
len
(
forksByTime
)
==
0
{
forks
=
append
(
forks
,
math
.
MaxUint64
)
}
forksByTime
=
append
(
forksByTime
,
math
.
MaxUint64
)
// Last fork will never be passed
// Create a validator that will filter out incompatible chains
return
func
(
id
ID
)
error
{
...
...
@@ -151,19 +166,14 @@ func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() ui
// the remote, but at this current point in time we don't have enough
// information.
// 4. Reject in all other cases.
head
:=
headfn
()
for
i
,
fork
:=
range
forks
{
// If our head is beyond this fork, continue to the next (we have a dummy
// fork of maxuint64 as the last item to always fail this check eventually).
if
head
>=
fork
{
continue
}
verify
:=
func
(
index
int
,
headOrTime
uint64
)
error
{
// Found the first unpassed fork block, check if our current state matches
// the remote checksum (rule #1).
if
sums
[
i
]
==
id
.
Hash
{
if
sums
[
i
ndex
]
==
id
.
Hash
{
// Fork checksum matched, check if a remote future fork block already passed
// locally without the local node being aware of it (rule #1a).
if
id
.
Next
>
0
&&
head
>=
id
.
Next
{
if
id
.
Next
>
0
&&
head
OrTime
>=
id
.
Next
{
return
ErrLocalIncompatibleOrStale
}
// Haven't passed locally a remote-only fork, accept the connection (rule #1b).
...
...
@@ -171,10 +181,10 @@ func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() ui
}
// The local and remote nodes are in different forks currently, check if the
// remote checksum is a subset of our local forks (rule #2).
for
j
:=
0
;
j
<
i
;
j
++
{
for
j
:=
0
;
j
<
i
ndex
;
j
++
{
if
sums
[
j
]
==
id
.
Hash
{
// Remote checksum is a subset, validate based on the announced next fork
if
f
orks
[
j
]
!=
id
.
Next
{
if
allF
orks
[
j
]
!=
id
.
Next
{
return
ErrRemoteStale
}
return
nil
...
...
@@ -182,7 +192,7 @@ func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() ui
}
// Remote chain is not a subset of our local one, check if it's a superset by
// any chance, signalling that we're simply out of sync (rule #3).
for
j
:=
i
+
1
;
j
<
len
(
sums
);
j
++
{
for
j
:=
i
ndex
+
1
;
j
<
len
(
sums
);
j
++
{
if
sums
[
j
]
==
id
.
Hash
{
// Yay, remote checksum is a superset, ignore upcoming forks
return
nil
...
...
@@ -191,6 +201,27 @@ func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() ui
// No exact, subset or superset match. We are on differing chains, reject.
return
ErrLocalIncompatibleOrStale
}
head
,
time
:=
headfn
()
// Verify forks by block
for
i
,
fork
:=
range
forks
{
// If our head is beyond this fork, continue to the next (we have a dummy
// fork of maxuint64 as the last item to always fail this check eventually).
if
head
>=
fork
{
continue
}
return
verify
(
i
,
head
)
}
// Verify forks by time
for
i
,
fork
:=
range
forksByTime
{
// If our head is beyond this fork, continue to the next (we have a dummy
// fork of maxuint64 as the last item to always fail this check eventually).
if
time
>=
fork
{
continue
}
return
verify
(
len
(
forks
)
+
i
,
time
)
}
log
.
Error
(
"Impossible fork ID validation"
,
"id"
,
id
)
return
nil
// Something's very wrong, accept rather than reject
}
...
...
@@ -212,17 +243,22 @@ func checksumToBytes(hash uint32) [4]byte {
}
// gatherForks gathers all the known forks and creates a sorted list out of them.
func
gatherForks
(
config
*
params
.
ChainConfig
)
[]
uint64
{
func
gatherForks
(
config
*
params
.
ChainConfig
)
([]
uint64
,
[]
uint64
)
{
// Gather all the fork block numbers via reflection
kind
:=
reflect
.
TypeOf
(
params
.
ChainConfig
{})
conf
:=
reflect
.
ValueOf
(
config
)
.
Elem
()
var
forks
[]
uint64
var
forksByTime
[]
uint64
for
i
:=
0
;
i
<
kind
.
NumField
();
i
++
{
// Fetch the next field and skip non-fork rules
field
:=
kind
.
Field
(
i
)
time
:=
false
if
!
strings
.
HasSuffix
(
field
.
Name
,
"Block"
)
{
continue
if
!
strings
.
HasSuffix
(
field
.
Name
,
"Time"
)
{
continue
}
time
=
true
}
if
field
.
Type
!=
reflect
.
TypeOf
(
new
(
big
.
Int
))
{
continue
...
...
@@ -230,17 +266,17 @@ func gatherForks(config *params.ChainConfig) []uint64 {
// Extract the fork rule block number and aggregate it
rule
:=
conf
.
Field
(
i
)
.
Interface
()
.
(
*
big
.
Int
)
if
rule
!=
nil
{
forks
=
append
(
forks
,
rule
.
Uint64
())
}
}
// Sort the fork block numbers to permit chronological XOR
for
i
:=
0
;
i
<
len
(
forks
);
i
++
{
for
j
:=
i
+
1
;
j
<
len
(
forks
);
j
++
{
if
forks
[
i
]
>
forks
[
j
]
{
forks
[
i
],
forks
[
j
]
=
forks
[
j
],
forks
[
i
]
if
time
{
forksByTime
=
append
(
forksByTime
,
rule
.
Uint64
())
}
else
{
forks
=
append
(
forks
,
rule
.
Uint64
())
}
}
}
sort
.
Slice
(
forks
,
func
(
i
,
j
int
)
bool
{
return
forks
[
i
]
<
forks
[
j
]
})
sort
.
Slice
(
forksByTime
,
func
(
i
,
j
int
)
bool
{
return
forksByTime
[
i
]
<
forksByTime
[
j
]
})
// Deduplicate block numbers applying multiple forks
for
i
:=
1
;
i
<
len
(
forks
);
i
++
{
if
forks
[
i
]
==
forks
[
i
-
1
]
{
...
...
@@ -248,9 +284,18 @@ func gatherForks(config *params.ChainConfig) []uint64 {
i
--
}
}
for
i
:=
1
;
i
<
len
(
forksByTime
);
i
++
{
if
forksByTime
[
i
]
==
forksByTime
[
i
-
1
]
{
forksByTime
=
append
(
forksByTime
[
:
i
],
forksByTime
[
i
+
1
:
]
...
)
i
--
}
}
// Skip any forks in block 0, that's the genesis ruleset
if
len
(
forks
)
>
0
&&
forks
[
0
]
==
0
{
forks
=
forks
[
1
:
]
}
return
forks
if
len
(
forksByTime
)
>
0
&&
forksByTime
[
0
]
==
0
{
forksByTime
=
forksByTime
[
1
:
]
}
return
forks
,
forksByTime
}
This diff is collapsed.
Click to expand it.
core/forkid/forkid_test.go
View file @
a4e19c5c
This diff is collapsed.
Click to expand it.
eth/handler.go
View file @
a4e19c5c
...
...
@@ -331,7 +331,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
number
=
head
.
Number
.
Uint64
()
td
=
h
.
chain
.
GetTd
(
hash
,
number
)
)
forkID
:=
forkid
.
NewID
(
h
.
chain
.
Config
(),
h
.
chain
.
Genesis
()
.
Hash
(),
h
.
chain
.
CurrentHeader
()
.
Number
.
Uint64
())
forkID
:=
forkid
.
NewID
(
h
.
chain
.
Config
(),
h
.
chain
.
Genesis
()
.
Hash
(),
h
.
chain
.
CurrentHeader
()
.
Number
.
Uint64
()
,
h
.
chain
.
CurrentHeader
()
.
Time
)
if
err
:=
peer
.
Handshake
(
h
.
networkID
,
td
,
hash
,
genesis
.
Hash
(),
forkID
,
h
.
forkFilter
);
err
!=
nil
{
peer
.
Log
()
.
Debug
(
"Ethereum handshake failed"
,
"err"
,
err
)
return
err
...
...
This diff is collapsed.
Click to expand it.
eth/protocols/eth/discovery.go
View file @
a4e19c5c
...
...
@@ -60,6 +60,6 @@ func StartENRUpdater(chain *core.BlockChain, ln *enode.LocalNode) {
// currentENREntry constructs an `eth` ENR entry based on the current state of the chain.
func
currentENREntry
(
chain
*
core
.
BlockChain
)
*
enrEntry
{
return
&
enrEntry
{
ForkID
:
forkid
.
NewID
(
chain
.
Config
(),
chain
.
Genesis
()
.
Hash
(),
chain
.
CurrentHeader
()
.
Number
.
Uint64
()),
ForkID
:
forkid
.
NewID
(
chain
.
Config
(),
chain
.
Genesis
()
.
Hash
(),
chain
.
CurrentHeader
()
.
Number
.
Uint64
()
,
chain
.
CurrentHeader
()
.
Time
),
}
}
This diff is collapsed.
Click to expand it.
eth/protocols/eth/handshake_test.go
View file @
a4e19c5c
...
...
@@ -40,7 +40,7 @@ func testHandshake(t *testing.T, protocol uint) {
genesis
=
backend
.
chain
.
Genesis
()
head
=
backend
.
chain
.
CurrentBlock
()
td
=
backend
.
chain
.
GetTd
(
head
.
Hash
(),
head
.
NumberU64
())
forkID
=
forkid
.
NewID
(
backend
.
chain
.
Config
(),
backend
.
chain
.
Genesis
()
.
Hash
(),
backend
.
chain
.
CurrentHeader
()
.
Number
.
Uint64
())
forkID
=
forkid
.
NewID
(
backend
.
chain
.
Config
(),
backend
.
chain
.
Genesis
()
.
Hash
(),
backend
.
chain
.
CurrentHeader
()
.
Number
.
Uint64
()
,
backend
.
chain
.
CurrentHeader
()
.
Time
)
)
tests
:=
[]
struct
{
code
uint64
...
...
This diff is collapsed.
Click to expand it.
les/client_handler.go
View file @
a4e19c5c
...
...
@@ -111,7 +111,7 @@ func (h *clientHandler) handle(p *serverPeer, noInitAnnounce bool) error {
p
.
Log
()
.
Debug
(
"Light Ethereum peer connected"
,
"name"
,
p
.
Name
())
// Execute the LES handshake
forkid
:=
forkid
.
NewID
(
h
.
backend
.
blockchain
.
Config
(),
h
.
backend
.
genesis
,
h
.
backend
.
blockchain
.
CurrentHeader
()
.
Number
.
Uint64
())
forkid
:=
forkid
.
NewID
(
h
.
backend
.
blockchain
.
Config
(),
h
.
backend
.
genesis
,
h
.
backend
.
blockchain
.
CurrentHeader
()
.
Number
.
Uint64
()
,
h
.
backend
.
blockchain
.
CurrentHeader
()
.
Time
)
if
err
:=
p
.
Handshake
(
h
.
backend
.
blockchain
.
Genesis
()
.
Hash
(),
forkid
,
h
.
forkFilter
);
err
!=
nil
{
p
.
Log
()
.
Debug
(
"Light Ethereum handshake failed"
,
"err"
,
err
)
return
err
...
...
This diff is collapsed.
Click to expand it.
les/peer_test.go
View file @
a4e19c5c
...
...
@@ -124,8 +124,8 @@ func TestHandshake(t *testing.T) {
genesis
=
common
.
HexToHash
(
"cafebabe"
)
chain1
,
chain2
=
&
fakeChain
{},
&
fakeChain
{}
forkID1
=
forkid
.
NewID
(
chain1
.
Config
(),
chain1
.
Genesis
()
.
Hash
(),
chain1
.
CurrentHeader
()
.
Number
.
Uint64
())
forkID2
=
forkid
.
NewID
(
chain2
.
Config
(),
chain2
.
Genesis
()
.
Hash
(),
chain2
.
CurrentHeader
()
.
Number
.
Uint64
())
forkID1
=
forkid
.
NewID
(
chain1
.
Config
(),
chain1
.
Genesis
()
.
Hash
(),
chain1
.
CurrentHeader
()
.
Number
.
Uint64
()
,
chain1
.
CurrentHeader
()
.
Time
)
forkID2
=
forkid
.
NewID
(
chain2
.
Config
(),
chain2
.
Genesis
()
.
Hash
(),
chain2
.
CurrentHeader
()
.
Number
.
Uint64
()
,
chain2
.
CurrentHeader
()
.
Time
)
filter1
,
filter2
=
forkid
.
NewFilter
(
chain1
),
forkid
.
NewFilter
(
chain2
)
)
...
...
This diff is collapsed.
Click to expand it.
les/server_handler.go
View file @
a4e19c5c
...
...
@@ -117,7 +117,7 @@ func (h *serverHandler) handle(p *clientPeer) error {
hash
=
head
.
Hash
()
number
=
head
.
Number
.
Uint64
()
td
=
h
.
blockchain
.
GetTd
(
hash
,
number
)
forkID
=
forkid
.
NewID
(
h
.
blockchain
.
Config
(),
h
.
blockchain
.
Genesis
()
.
Hash
(),
h
.
blockchain
.
CurrentBlock
()
.
NumberU64
())
forkID
=
forkid
.
NewID
(
h
.
blockchain
.
Config
(),
h
.
blockchain
.
Genesis
()
.
Hash
(),
h
.
blockchain
.
CurrentBlock
()
.
NumberU64
()
,
h
.
blockchain
.
CurrentBlock
()
.
Time
()
)
)
if
err
:=
p
.
Handshake
(
td
,
hash
,
number
,
h
.
blockchain
.
Genesis
()
.
Hash
(),
forkID
,
h
.
forkFilter
,
h
.
server
);
err
!=
nil
{
p
.
Log
()
.
Debug
(
"Light Ethereum handshake failed"
,
"err"
,
err
)
...
...
This diff is collapsed.
Click to expand it.
les/test_helper.go
View file @
a4e19c5c
...
...
@@ -489,7 +489,7 @@ func (client *testClient) newRawPeer(t *testing.T, name string, version int, rec
head
=
client
.
handler
.
backend
.
blockchain
.
CurrentHeader
()
td
=
client
.
handler
.
backend
.
blockchain
.
GetTd
(
head
.
Hash
(),
head
.
Number
.
Uint64
())
)
forkID
:=
forkid
.
NewID
(
client
.
handler
.
backend
.
blockchain
.
Config
(),
genesis
.
Hash
(),
head
.
Number
.
Uint64
())
forkID
:=
forkid
.
NewID
(
client
.
handler
.
backend
.
blockchain
.
Config
(),
genesis
.
Hash
(),
head
.
Number
.
Uint64
()
,
head
.
Time
)
tp
.
handshakeWithClient
(
t
,
td
,
head
.
Hash
(),
head
.
Number
.
Uint64
(),
genesis
.
Hash
(),
forkID
,
testCostList
(
0
),
recentTxLookup
)
// disable flow control by default
// Ensure the connection is established or exits when any error occurs
...
...
@@ -553,7 +553,7 @@ func (server *testServer) newRawPeer(t *testing.T, name string, version int) (*t
head
=
server
.
handler
.
blockchain
.
CurrentHeader
()
td
=
server
.
handler
.
blockchain
.
GetTd
(
head
.
Hash
(),
head
.
Number
.
Uint64
())
)
forkID
:=
forkid
.
NewID
(
server
.
handler
.
blockchain
.
Config
(),
genesis
.
Hash
(),
head
.
Number
.
Uint64
())
forkID
:=
forkid
.
NewID
(
server
.
handler
.
blockchain
.
Config
(),
genesis
.
Hash
(),
head
.
Number
.
Uint64
()
,
head
.
Time
)
tp
.
handshakeWithServer
(
t
,
td
,
head
.
Hash
(),
head
.
Number
.
Uint64
(),
genesis
.
Hash
(),
forkID
)
// Ensure the connection is established or exits when any error occurs
...
...
This diff is collapsed.
Click to expand it.
tests/state_test.go
View file @
a4e19c5c
...
...
@@ -183,7 +183,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
b
.
Error
(
err
)
return
}
var
rules
=
config
.
Rules
(
new
(
big
.
Int
),
false
)
var
rules
=
config
.
Rules
(
new
(
big
.
Int
),
false
,
new
(
big
.
Int
)
)
vmconfig
.
ExtraEips
=
eips
block
:=
t
.
genesis
(
config
)
.
ToBlock
()
...
...
This diff is collapsed.
Click to expand it.
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