Skip to content

Commit

Permalink
cmd/geth: Set compatible genesis and IBFT hash method (#3)
Browse files Browse the repository at this point in the history
## Description

The rlp hasher of PolygonEdge is wired, but we still need to support it
since huge amount data already exist in Dogechain Mainnet. And the PR
adds hard forks of Dogechain too, including `portland` and `detroit`.

We separate the `Header` rlp Hasher(for indexing) and rlp Encoder(for
persistence), so as to support IBFT verification consensus (which shall
be deprecated in next hard fork).

## Test cases

### Multiple consensus

* Parlia(BSC) Mainnet genesis and normal header.
* Clique(Rinkeby) Testnet genesis and normal header.
* IBFT(Dogechain) Devnet genesis and normal header.

Compare the header hash, and they are correct.

### Dogechain Mainnet

Provide Mainnet genesis:

[genesis-dbsc.json](https://github.com/dogechain-lab/dbsc/files/11145646/genesis-dbsc.txt)

Compile and use current PR branch geth to init genesis block in datadir.

```bash
go run cmd/geth init --datadir $PWD/data genesis-dbsc.json
```

The log should print like this:

```
Successfully wrote genesis state         database=chaindata hash=5ee4e7..da5b74
```

Query the [genesis block](https://explorer.dogechain.dog/block/0) in
Dogechain explorer, found the hash
`0x5ee4e79b3d798f8bd5a3a5f92e24f62198888aed028354ad5463aea8e5da5b74` is
equal and right.

Use [leveldb-tools](https://github.com/dogechain-lab/leveldb-tools) to
query local database:

```bash
$ ldb show "h*"
0x485ee4e79b3d798f8bd5a3a5f92e24f62198888aed028354ad5463aea8e5da5b74:0x0000000000000000
0x6800000000000000005ee4e79b3d798f8bd5a3a5f92e24f62198888aed028354ad5463aea8e5da5b74:0xf9026fa00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0de17336927fa082de0b75e9c9853121e2711419f33e434799df5ab20d9863ad6a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001808401c9c3808307000080b87a0000000000000000000000000000000000000000000000000000000000000000f858f85494d668bba507d0438ff22ee8ceb341323765669a24947175996ff9dcb8fbb83b68e2b88f1a029014555b9492bb5d1a856e54157232b43fe1c9c7e89ee36abe9464f2686e3ac7492c3b3f662d32ecb8b6bfa548fe80c0a00000000000000000000000000000000000000000000000000000000000000000880000000000000000
0x6800000000000000005ee4e79b3d798f8bd5a3a5f92e24f62198888aed028354ad5463aea8e5da5b7474:0x01
0x6800000000000000006e:0x5ee4e79b3d798f8bd5a3a5f92e24f62198888aed028354ad5463aea8e5da5b74
```

Use [online rlp decoder](https://codechain-io.github.io/rlp-debugger/)
to parse the header info (key:
`0x6800000000000000005ee4e79b3d798f8bd5a3a5f92e24f62198888aed028354ad5463aea8e5da5b74`):
We'll find that all fields are correctly set, including IBFT verifying
field `Extra`.
  • Loading branch information
DarianShawn authored Apr 8, 2023
1 parent dc2a5af commit d68e36f
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 24 deletions.
11 changes: 1 addition & 10 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"golang.org/x/crypto/sha3"
)

type Prestate struct {
Expand Down Expand Up @@ -261,7 +259,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)),
ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)),
Bloom: types.CreateBloom(receipts),
LogsHash: rlpHash(statedb.Logs()),
LogsHash: statedb.Logs().Hash(),
Receipts: receipts,
Rejected: rejectedTxs,
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
Expand Down Expand Up @@ -289,13 +287,6 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
return statedb
}

func rlpHash(x interface{}) (h common.Hash) {
hw := sha3.NewLegacyKeccak256()
rlp.Encode(hw, x)
hw.Sum(h[:0])
return h
}

// calcDifficulty is based on ethash.CalcDifficulty. This method is used in case
// the caller does not provide an explicit difficulty, but instead provides only
// parent timestamp + difficulty.
Expand Down
2 changes: 1 addition & 1 deletion core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ func (s *StateDB) GetLogs(hash common.Hash, blockHash common.Hash) []*types.Log
return logs
}

func (s *StateDB) Logs() []*types.Log {
func (s *StateDB) Logs() types.Logs {
var logs []*types.Log
for _, lgs := range s.logs {
logs = append(logs, lgs...)
Expand Down
20 changes: 20 additions & 0 deletions core/types/hashing.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,31 @@ func rlpHash(x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState)
defer hasherPool.Put(sha)
sha.Reset()

switch t := x.(type) {
case Header:
return headerHashWithFallback(sha, &t)
case *Header:
return headerHashWithFallback(sha, t)
}

// other types use default rlp hasher
rlp.Encode(sha, x)
sha.Read(h[:])
return h
}

func headerHashWithFallback(sha crypto.KeccakState, header *Header) (h common.Hash) {
// rlp marshal to hasher
if err := ibftHeaderHashRLP(sha, header); err != nil {
sha.Reset() // reset buffer to prevent mixup
rlp.Encode(sha, header) // fallback to usual rlp hasher
}

sha.Read(h[:])
return h
}

// prefixedRlpHash writes the prefix into the hasher before rlp-encoding x.
// It's used for typed transactions.
func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) {
Expand Down
143 changes: 143 additions & 0 deletions core/types/hashing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,146 @@ func (d *hashToHumanReadable) Update(i []byte, i2 []byte) {
func (d *hashToHumanReadable) Hash() common.Hash {
return common.Hash{}
}

func TestHeader_Hasher(t *testing.T) {
for _, tc := range []struct {
name string
data *types.Header
expHash common.Hash
}{
{
name: "clique genesis header",
data: &types.Header{
ParentHash: common.Hash{},
UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
Coinbase: common.Address{},
Root: common.HexToHash("0x804a07455284a0617ca98be637aa753ecf3b8fa742dd5dff2089c709454586c3"),
TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
Bloom: types.BytesToBloom(common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
Difficulty: big.NewInt(1),
Number: big.NewInt(0),
GasLimit: 0x47b760,
GasUsed: 0,
Time: 0x58ee40ba,
Extra: common.Hex2Bytes("52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
MixDigest: common.Hash{},
Nonce: types.BlockNonce{},
},
expHash: common.HexToHash("0x41216dd5455205ce4182dfff13369a53fda71aa8b81a52c0383b4c8de36b7f3c"),
},
{
name: "clique chain header",
data: &types.Header{
ParentHash: common.HexToHash("0xa1d9eda6cbed736ccd96e6c9ac497f5f668141765d819b6e4054001d67134239"),
UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
Coinbase: common.HexToAddress("0x70f657164e5b75689b64b7fd1fa275f334f28e18"),
Root: common.HexToHash("0xbad93e9bda0b01f91abff7e29ae2bf215a265bf04b86f3d04b187ad3c920b4ef"),
TxHash: common.HexToHash("0x42a8532a659ba9ddffa9308995c93b872fa18d4782318b176ae4502c158faa8c"),
ReceiptHash: common.HexToHash("0x32732e389ad883eacfe7d270492a544181cf7a015daca3de9368288a66b5e599"),
Bloom: types.BytesToBloom(common.Hex2Bytes("09750269321014196e08b0528120948373cc4a199e198f58783a60ec04926214f3291d5050051964a7603679141a65824a8bc32116ae3fa47e3c2a393d2e20a3a6609c30e14520e2856fce29a1b460a8fab9c0008bf63a37e00464278e17c0072724d13ecec3b59d96d35ae40784b9dd990083edc9f944e01770481cb8da441ad0c329a59c15b24a78ed5608ac00302e343c34957c4c768b3d8e05f98c49d8f487d984445c1ea309223663e7065e442c34ae20e3ce184104133c6231d612c0ec210414969017eb1611947ca912b93071a145cd64c5ae0b9d0f1211324021e77376f6d5435f57041a4da51a9227a51ca9cdc4742f502d4fdc22865dd39ae22e02")),
Difficulty: big.NewInt(0x2),
Number: big.NewInt(0x19d9ef3),
GasLimit: 0x8583b00,
GasUsed: 0xd23185,
Time: 0x642e7bdf,
Extra: common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000000291d5050051964a7603679141a65824a8bc32116ae3fa47e3c2a393d2e20a3a6609c30e14520e2856fce29a1b460a8fab9c0008bf63a37e00464278e17c0072724d13ecec3b59d96d35ae40784b9dd990083edc9f944e01770481cb8da441ad0c329a59c15b24a78ed5608ac00302e343c34957c4c768b3d8e05f98c49d8f487d984445c1ea309223663e7065e442c34ae20e3ce184104133c6231d612c0ec210414969017eb1611947ca912b93071a145cd64c5ae0b9d0f1211324021e77376f6d5435f57041a4da51a9227a51ca9cdc4742f502d4fdc22865dd39ae22e02"),
MixDigest: common.Hash{},
Nonce: types.BlockNonce{},
},
expHash: common.HexToHash("0x3b96d403aa885d8b83ee54fdebcb8a63e85ca1b9284ef1f8b1eccf777c0104ad"),
},
{
name: "bsc genesis header",
data: &types.Header{
ParentHash: common.Hash{},
UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
Coinbase: common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe"),
Root: common.HexToHash("0x919fcc7ad870b53db0aa76eb588da06bacb6d230195100699fc928511003b422"),
TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
Bloom: types.BytesToBloom(common.Hex2Bytes("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
Difficulty: big.NewInt(1),
Number: big.NewInt(0),
GasLimit: 0x2625a00,
GasUsed: 0,
Time: 0x5e9da7ce,
Extra: common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000002a7cdd959bfe8d9487b2a43b33565295a698f7e26488aa4d1955ee33403f8ccb1d4de5fb97c7ade29ef9f4360c606c7ab4db26b016007d3ad0ab86a0ee01c3b1283aa067c58eab4709f85e99d46de5fe685b1ded8013785d6623cc18d214320b6bb6475978f3adfc719c99674c072166708589033e2d9afec2be4ec20253b8642161bc3f444f53679c1f3d472f7be8361c80a4c1e7e9aaf001d0877f1cfde218ce2fd7544e0b2cc94692d4a704debef7bcb61328b8f7166496996a7da21cf1f1b04d9b3e26a3d0772d4c407bbe49438ed859fe965b140dcf1aab71a96bbad7cf34b5fa511d8e963dbba288b1960e75d64430b3230294d12c6ab2aac5c2cd68e80b16b581ea0a6e3c511bbd10f4519ece37dc24887e11b55d7ae2f5b9e386cd1b50a4550696d957cb4900f03a82012708dafc9e1b880fd083b32182b869be8e0922b81f8e175ffde54d797fe11eb03f9e3bf75f1d68bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d8c4d90829ce8f72d0163c1d5cf348a862d55063035e7a025f4da968de7e4d7e4004197917f4070f1d6caa02bbebaebb5d7e581e4b66559e635f805ff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
MixDigest: common.Hash{},
Nonce: types.BlockNonce{},
},
expHash: common.HexToHash("0x0d21840abff46b96c84b2ac9e10e4f5cdaeb5693cb665db62a2f3b02d2d57b5b"),
},
{
name: "bsc chain header",
data: &types.Header{
ParentHash: common.HexToHash("0xa1d9eda6cbed736ccd96e6c9ac497f5f668141765d819b6e4054001d67134239"),
UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
Coinbase: common.HexToAddress("0x70f657164e5b75689b64b7fd1fa275f334f28e18"),
Root: common.HexToHash("0xbad93e9bda0b01f91abff7e29ae2bf215a265bf04b86f3d04b187ad3c920b4ef"),
TxHash: common.HexToHash("0x42a8532a659ba9ddffa9308995c93b872fa18d4782318b176ae4502c158faa8c"),
ReceiptHash: common.HexToHash("0x32732e389ad883eacfe7d270492a544181cf7a015daca3de9368288a66b5e599"),
Bloom: types.BytesToBloom(common.Hex2Bytes("09750269321014196e08b0528120948373cc4a199e198f58783a60ec04926214f3291d5050051964a7603679141a65824a8bc32116ae3fa47e3c2a393d2e20a3a6609c30e14520e2856fce29a1b460a8fab9c0008bf63a37e00464278e17c0072724d13ecec3b59d96d35ae40784b9dd990083edc9f944e01770481cb8da441ad0c329a59c15b24a78ed5608ac00302e343c34957c4c768b3d8e05f98c49d8f487d984445c1ea309223663e7065e442c34ae20e3ce184104133c6231d612c0ec210414969017eb1611947ca912b93071a145cd64c5ae0b9d0f1211324021e77376f6d5435f57041a4da51a9227a51ca9cdc4742f502d4fdc22865dd39ae22e02")),
Difficulty: big.NewInt(2),
Number: big.NewInt(0x19d9ef3),
GasLimit: 0x8583b00,
GasUsed: 0xd23185,
Time: 0x642e7bdf,
Extra: common.Hex2Bytes("d883010115846765746888676f312e31392e37856c696e7578000000f98d107232553b5676d8dcdd9f73b2689f63fe37a709ce1f5d71d7166d58a088ad4530835d45872be4789f15e14cd3bf0bb7d1d5a029e3f0b15095c5e91564d35bb949c100"),
MixDigest: common.Hash{},
Nonce: types.BlockNonce{},
},
expHash: common.HexToHash("0x21e7c0e3322a45292bae14f8e4ce5bea537908766397d43fabb32e03970a249e"),
},
{
name: "ibft genesis header",
data: &types.Header{
ParentHash: common.Hash{},
UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
Coinbase: common.Address{},
Root: common.HexToHash("0x804a07455284a0617ca98be637aa753ecf3b8fa742dd5dff2089c709454586c3"),
TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
Bloom: types.BytesToBloom(common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
Difficulty: big.NewInt(1),
Number: big.NewInt(0),
GasLimit: 0x1c9c380,
GasUsed: 0x70000,
Time: 0,
Extra: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000f858f8549474c8ab07501014c3c58f6529d9bd966a02548b44945f66fe5430613154a9b82e382d400fb4475f8ab7949c5d3e328515636e0564b2ba3becac32f972657f948a5207bdd70cedde5ca6124fca0de772acf3ccfc80c0"),
MixDigest: common.Hash{},
Nonce: types.BlockNonce{},
},
expHash: common.HexToHash("0x75d36607ff0e081d53cf9999d3abd2050f1865e443fe2197236e0ab76aad4443"),
},
{
name: "ibft chain header",
data: &types.Header{
ParentHash: common.HexToHash("0x98295ad58f5ccab9d79efc55d15ecbf1f06dfc30f0cfd0125a28d5d7ee2270e6"),
UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
Coinbase: common.HexToAddress("0x92bB5D1A856E54157232b43Fe1C9C7e89eE36ABE"),
Root: common.HexToHash("0xf096fcfe18f104b080b40aea0d925b43c77265cc9af978183ed17933d7042c66"),
TxHash: common.HexToHash("0x6e6cadced99ed9ca7e587ce6ecb164913f99d6faebe12add39dc8bfc5a67110c"),
ReceiptHash: common.HexToHash("0xcdb9f10980cf5502a35c0a26433f59b4883a3d7022d627c9e575348648ea386f"),
Bloom: types.BytesToBloom(common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
Difficulty: big.NewInt(10290979),
Number: big.NewInt(10290979),
GasLimit: 30000000,
GasUsed: 568092,
Time: 1680769939,
Extra: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000f90164f85494d668bba507d0438ff22ee8ceb341323765669a24947175996ff9dcb8fbb83b68e2b88f1a029014555b9492bb5d1a856e54157232b43fe1c9c7e89ee36abe9464f2686e3ac7492c3b3f662d32ecb8b6bfa548feb8416f304ad7974ff598142d561335bef9d2cf081260c432127ef80e910c57269ef61d24f439e7aac71869b8b014d11ae0b4fec5bb41ef5876aa51f751d7c02d2ae600f8c9b841837ab7e53839529eafb8f6fc96886bd43050bd130b2036b07634489b47cab0193b133543941d1a3e6483f20c771573da3450f8f746c3afb2396d577e51655fe801b8419a63a2e97f544c7e4633f2c1e858ced5338aebd4b105a31ba39dfb710c6df0520ce5d23e4c87c69c3b5dbc32540a7cd954835758ed5897f498ddca80f58d1fa301b841fbd43d90202965e7f0a9de6018261661925d611810c6d0be606dc274476f5d00177175159cc57f184b8cc965d074516b46d3a8a9a1e962305229ef8f140c7c0501"),
MixDigest: types.IBFTMixHash,
Nonce: types.BlockNonce{},
},
expHash: common.HexToHash("0x9b84a2811d55ec8fe72d223b81554a109c3591aa9e4330bc80078921009f0b94"),
},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
h := tc.data.Hash()
if h != tc.expHash {
t.Errorf("header hash mismatch, want %s, got %s", tc.expHash, h)
}
})
}
}
131 changes: 131 additions & 0 deletions core/types/ibft_header_rlp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package types

import (
"bytes"
"errors"
"io"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
)

const (
// IBFTExtraVanity (Istanbul BFT Vanity) represents a fixed number of extra-data bytes reserved for proposer vanity
IBFTExtraVanity = 32
)

var (
ErrIBFTInvalidMixHash = errors.New("invalid ibft mix hash")
ErrInvalidIBFTExtraLength = errors.New("invalid ibft extra length")
ErrNotIBFTExtraPrefix = errors.New("not ibft extra prefix")
)

var (
// IBFTMixHash represents a hash of "Istanbul practical byzantine fault tolerance"
// to identify whether the block is from Istanbul consensus engine
IBFTMixHash = common.HexToHash("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365")

// IBFTExtraPrefix represents extra hash prefix of "Istanbul practical byzantine fault tolerance".
// The difference of extra between geth, bsc and dogechain (ibft) is that ibft uses zero instead of
// client version on prefix
IBFTExtraPrefix = common.Hash{}
)

// IBFTExtra defines the structure of the extra field for I(stanbul)BFT
type IBFTExtra struct {
Validators []common.Address
Seal []byte
CommittedSeal [][]byte
}

// getIbftExtra returns the istanbul extra data field from the passed in header
func getIbftExtra(h *Header) (*IBFTExtra, error) {
// must longer than ibft extra prefix
if len(h.Extra) < IBFTExtraVanity {
return nil, ErrInvalidIBFTExtraLength
}

// must be ibft extra prefix
if !bytes.Equal(h.Extra[:IBFTExtraVanity], IBFTExtraPrefix[:]) {
return nil, ErrNotIBFTExtraPrefix
}

data := h.Extra[IBFTExtraVanity:]
extra := &IBFTExtra{}

if err := rlp.DecodeBytes(data, extra); err != nil {
return nil, err
}

return extra, nil
}

// putIBFTExtraValidators is a helper method that adds validators to the extra field in the header
func putIBFTExtraValidators(h *Header, validators []common.Address) error {
ibftExtra := &IBFTExtra{
Validators: validators,
Seal: []byte{},
CommittedSeal: [][]byte{},
}

extra, err := rlp.EncodeToBytes(ibftExtra)
if err != nil {
return err
}

var zeroBytes = make([]byte, 32)
h.Extra = append(zeroBytes, extra...)

return nil
}

func ibftHeaderHashRLP(_w io.Writer, obj *Header) error {
// genesis will not check ibft mix hash
if obj.Number.Sign() > 0 && obj.MixDigest != IBFTMixHash {
return ErrIBFTInvalidMixHash
}

// when hashing the block for signing we have to remove from
// the extra field the seal and committed seal items
extra, err := getIbftExtra(obj)
if err != nil {
return err
}

// this function replaces extra so we need to make a copy
h := CopyHeader(obj) // Remove later

putIBFTExtraValidators(h, extra.Validators)

w := rlp.NewEncoderBuffer(_w)
_tmp0 := w.List()
w.WriteBytes(h.ParentHash[:])
w.WriteBytes(h.UncleHash[:])
w.WriteBytes(h.Coinbase[:])
w.WriteBytes(h.Root[:])
w.WriteBytes(h.TxHash[:])
w.WriteBytes(h.ReceiptHash[:])
w.WriteBytes(h.Bloom[:])
if h.Difficulty == nil {
w.Write(rlp.EmptyString)
} else {
if h.Difficulty.Sign() == -1 {
return rlp.ErrNegativeBigInt
}
w.WriteBigInt(h.Difficulty)
}
if h.Number == nil {
w.Write(rlp.EmptyString)
} else {
if h.Number.Sign() == -1 {
return rlp.ErrNegativeBigInt
}
w.WriteBigInt(h.Number)
}
w.WriteUint64(h.GasLimit)
w.WriteUint64(h.GasUsed)
w.WriteUint64(h.Time)
w.WriteBytes(h.Extra)
w.ListEnd(_tmp0)
return w.Flush()
}
6 changes: 6 additions & 0 deletions core/types/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,9 @@ func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
}
return err
}

type Logs []*Log

func (l Logs) Hash() common.Hash {
return rlpHash(l)
}
Loading

0 comments on commit d68e36f

Please sign in to comment.