2015-07-07 00:54:22 +00:00
|
|
|
// Copyright 2014 The go-ethereum Authors
|
2015-07-22 16:48:40 +00:00
|
|
|
// This file is part of the go-ethereum library.
|
2015-07-07 00:54:22 +00:00
|
|
|
//
|
2015-07-23 16:35:11 +00:00
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
2015-07-07 00:54:22 +00:00
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
2015-07-22 16:48:40 +00:00
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
2015-07-07 00:54:22 +00:00
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2015-07-22 16:48:40 +00:00
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2015-07-07 00:54:22 +00:00
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
2015-07-22 16:48:40 +00:00
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
2015-07-07 00:54:22 +00:00
|
|
|
|
2014-12-23 12:48:44 +00:00
|
|
|
package types
|
2015-03-16 16:27:23 +00:00
|
|
|
|
|
|
|
import (
|
2015-03-18 12:24:34 +00:00
|
|
|
"bytes"
|
2020-08-21 12:10:40 +00:00
|
|
|
"hash"
|
2015-03-16 16:27:23 +00:00
|
|
|
"math/big"
|
2015-03-18 12:24:34 +00:00
|
|
|
"reflect"
|
2015-03-16 16:27:23 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2020-07-06 09:17:09 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common/math"
|
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
|
|
"github.com/ethereum/go-ethereum/params"
|
2015-03-18 12:24:34 +00:00
|
|
|
"github.com/ethereum/go-ethereum/rlp"
|
2020-08-21 12:10:40 +00:00
|
|
|
"golang.org/x/crypto/sha3"
|
2015-03-16 16:27:23 +00:00
|
|
|
)
|
|
|
|
|
2015-03-18 12:24:34 +00:00
|
|
|
// from bcValidBlockTest.json, "SimpleTx"
|
|
|
|
func TestBlockEncoding(t *testing.T) {
|
|
|
|
blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0")
|
|
|
|
var block Block
|
|
|
|
if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
|
|
|
|
t.Fatal("decode error: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
check := func(f string, got, want interface{}) {
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("%s mismatch: got %v, want %v", f, got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
check("Difficulty", block.Difficulty(), big.NewInt(131072))
|
2017-11-13 11:47:27 +00:00
|
|
|
check("GasLimit", block.GasLimit(), uint64(3141592))
|
|
|
|
check("GasUsed", block.GasUsed(), uint64(21000))
|
2015-03-18 12:24:34 +00:00
|
|
|
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
|
|
|
|
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
|
|
|
|
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
|
|
|
|
check("Hash", block.Hash(), common.HexToHash("0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e"))
|
|
|
|
check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
|
2019-04-02 20:28:48 +00:00
|
|
|
check("Time", block.Time(), uint64(1426516743))
|
2022-10-26 12:23:07 +00:00
|
|
|
check("Size", block.Size(), uint64(len(blockEnc)))
|
2015-03-18 12:24:34 +00:00
|
|
|
|
2017-11-13 11:47:27 +00:00
|
|
|
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil)
|
2017-01-05 10:35:23 +00:00
|
|
|
tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"))
|
2015-06-11 12:05:32 +00:00
|
|
|
check("len(Transactions)", len(block.Transactions()), 1)
|
|
|
|
check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash())
|
2021-02-25 14:26:57 +00:00
|
|
|
ourBlockEnc, err := rlp.EncodeToBytes(&block)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("encode error: ", err)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(ourBlockEnc, blockEnc) {
|
|
|
|
t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-17 13:13:22 +00:00
|
|
|
func TestEIP1559BlockEncoding(t *testing.T) {
|
|
|
|
blockEnc := common.FromHex("f9030bf901fea083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4843b9aca00f90106f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b8a302f8a0018080843b9aca008301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000080a0fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b0a06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a8c0")
|
|
|
|
var block Block
|
|
|
|
if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
|
|
|
|
t.Fatal("decode error: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
check := func(f string, got, want interface{}) {
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("%s mismatch: got %v, want %v", f, got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
check("Difficulty", block.Difficulty(), big.NewInt(131072))
|
|
|
|
check("GasLimit", block.GasLimit(), uint64(3141592))
|
|
|
|
check("GasUsed", block.GasUsed(), uint64(21000))
|
|
|
|
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
|
|
|
|
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
|
|
|
|
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
|
|
|
|
check("Hash", block.Hash(), common.HexToHash("c7252048cd273fe0dac09650027d07f0e3da4ee0675ebbb26627cea92729c372"))
|
|
|
|
check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
|
|
|
|
check("Time", block.Time(), uint64(1426516743))
|
2022-10-26 12:23:07 +00:00
|
|
|
check("Size", block.Size(), uint64(len(blockEnc)))
|
2021-05-17 13:13:22 +00:00
|
|
|
check("BaseFee", block.BaseFee(), new(big.Int).SetUint64(params.InitialBaseFee))
|
|
|
|
|
|
|
|
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil)
|
|
|
|
tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"))
|
|
|
|
|
|
|
|
addr := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
|
|
accesses := AccessList{AccessTuple{
|
|
|
|
Address: addr,
|
|
|
|
StorageKeys: []common.Hash{
|
|
|
|
{0},
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
|
|
|
|
txdata := &DynamicFeeTx{
|
|
|
|
ChainID: big.NewInt(1),
|
|
|
|
Nonce: 0,
|
|
|
|
To: &to,
|
|
|
|
Gas: 123457,
|
2021-06-08 10:05:41 +00:00
|
|
|
GasFeeCap: new(big.Int).Set(block.BaseFee()),
|
|
|
|
GasTipCap: big.NewInt(0),
|
2021-05-17 13:13:22 +00:00
|
|
|
AccessList: accesses,
|
|
|
|
Data: []byte{},
|
|
|
|
}
|
|
|
|
tx2 := NewTx(txdata)
|
|
|
|
tx2, err := tx2.WithSignature(LatestSignerForChainID(big.NewInt(1)), common.Hex2Bytes("fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a800"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("invalid signature error: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
check("len(Transactions)", len(block.Transactions()), 2)
|
|
|
|
check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash())
|
|
|
|
check("Transactions[1].Hash", block.Transactions()[1].Hash(), tx2.Hash())
|
|
|
|
check("Transactions[1].Type", block.Transactions()[1].Type(), tx2.Type())
|
|
|
|
ourBlockEnc, err := rlp.EncodeToBytes(&block)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("encode error: ", err)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(ourBlockEnc, blockEnc) {
|
|
|
|
t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-25 14:26:57 +00:00
|
|
|
func TestEIP2718BlockEncoding(t *testing.T) {
|
|
|
|
blockEnc := common.FromHex("f90319f90211a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a0e6e49996c7ec59f7a23d22b83239a60151512c65613bf84a0d7da336399ebc4aa0cafe75574d59780665a97fbfd11365c7545aa8f1abf4e5e12e8243334ef7286bb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000820200832fefd882a410845506eb0796636f6f6c65737420626c6f636b206f6e20636861696ea0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f90101f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b89e01f89b01800a8301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000001a03dbacc8d0259f2508625e97fdfc57cd85fdd16e5821bc2c10bdd1a52649e8335a0476e10695b183a87b0aa292a7f4b78ef0c3fbe62aa2c42c84e1d9c3da159ef14c0")
|
|
|
|
var block Block
|
|
|
|
if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
|
|
|
|
t.Fatal("decode error: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
check := func(f string, got, want interface{}) {
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("%s mismatch: got %v, want %v", f, got, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
check("Difficulty", block.Difficulty(), big.NewInt(131072))
|
|
|
|
check("GasLimit", block.GasLimit(), uint64(3141592))
|
|
|
|
check("GasUsed", block.GasUsed(), uint64(42000))
|
|
|
|
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
|
|
|
|
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
|
|
|
|
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
|
|
|
|
check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
|
|
|
|
check("Time", block.Time(), uint64(1426516743))
|
2022-10-26 12:23:07 +00:00
|
|
|
check("Size", block.Size(), uint64(len(blockEnc)))
|
2021-02-25 14:26:57 +00:00
|
|
|
|
|
|
|
// Create legacy tx.
|
|
|
|
to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
|
|
|
|
tx1 := NewTx(&LegacyTx{
|
|
|
|
Nonce: 0,
|
|
|
|
To: &to,
|
|
|
|
Value: big.NewInt(10),
|
|
|
|
Gas: 50000,
|
|
|
|
GasPrice: big.NewInt(10),
|
|
|
|
})
|
|
|
|
sig := common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")
|
|
|
|
tx1, _ = tx1.WithSignature(HomesteadSigner{}, sig)
|
|
|
|
|
|
|
|
// Create ACL tx.
|
|
|
|
addr := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
|
|
tx2 := NewTx(&AccessListTx{
|
|
|
|
ChainID: big.NewInt(1),
|
|
|
|
Nonce: 0,
|
|
|
|
To: &to,
|
|
|
|
Gas: 123457,
|
|
|
|
GasPrice: big.NewInt(10),
|
|
|
|
AccessList: AccessList{{Address: addr, StorageKeys: []common.Hash{{0}}}},
|
|
|
|
})
|
|
|
|
sig2 := common.Hex2Bytes("3dbacc8d0259f2508625e97fdfc57cd85fdd16e5821bc2c10bdd1a52649e8335476e10695b183a87b0aa292a7f4b78ef0c3fbe62aa2c42c84e1d9c3da159ef1401")
|
|
|
|
tx2, _ = tx2.WithSignature(NewEIP2930Signer(big.NewInt(1)), sig2)
|
|
|
|
|
|
|
|
check("len(Transactions)", len(block.Transactions()), 2)
|
|
|
|
check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash())
|
|
|
|
check("Transactions[1].Hash", block.Transactions()[1].Hash(), tx2.Hash())
|
|
|
|
check("Transactions[1].Type()", block.Transactions()[1].Type(), uint8(AccessListTxType))
|
2015-03-18 12:24:34 +00:00
|
|
|
|
|
|
|
ourBlockEnc, err := rlp.EncodeToBytes(&block)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("encode error: ", err)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(ourBlockEnc, blockEnc) {
|
|
|
|
t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc)
|
|
|
|
}
|
2015-03-16 16:27:23 +00:00
|
|
|
}
|
2019-04-08 07:13:05 +00:00
|
|
|
|
|
|
|
func TestUncleHash(t *testing.T) {
|
|
|
|
uncles := make([]*Header, 0)
|
|
|
|
h := CalcUncleHash(uncles)
|
|
|
|
exp := common.HexToHash("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
|
|
|
|
if h != exp {
|
|
|
|
t.Fatalf("empty uncle hash is wrong, got %x != %x", h, exp)
|
|
|
|
}
|
|
|
|
}
|
2020-07-06 09:17:09 +00:00
|
|
|
|
|
|
|
var benchBuffer = bytes.NewBuffer(make([]byte, 0, 32000))
|
|
|
|
|
|
|
|
func BenchmarkEncodeBlock(b *testing.B) {
|
|
|
|
block := makeBenchBlock()
|
2019-04-08 07:13:05 +00:00
|
|
|
b.ResetTimer()
|
2020-07-06 09:17:09 +00:00
|
|
|
|
2019-04-08 07:13:05 +00:00
|
|
|
for i := 0; i < b.N; i++ {
|
2020-07-06 09:17:09 +00:00
|
|
|
benchBuffer.Reset()
|
|
|
|
if err := rlp.Encode(benchBuffer, block); err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-21 12:10:40 +00:00
|
|
|
// testHasher is the helper tool for transaction/receipt list hashing.
|
|
|
|
// The original hasher is trie, in order to get rid of import cycle,
|
|
|
|
// use the testing hasher instead.
|
|
|
|
type testHasher struct {
|
|
|
|
hasher hash.Hash
|
|
|
|
}
|
|
|
|
|
|
|
|
func newHasher() *testHasher {
|
|
|
|
return &testHasher{hasher: sha3.NewLegacyKeccak256()}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *testHasher) Reset() {
|
|
|
|
h.hasher.Reset()
|
|
|
|
}
|
|
|
|
|
2023-04-20 10:57:24 +00:00
|
|
|
func (h *testHasher) Update(key, val []byte) error {
|
2020-08-21 12:10:40 +00:00
|
|
|
h.hasher.Write(key)
|
|
|
|
h.hasher.Write(val)
|
2023-04-20 10:57:24 +00:00
|
|
|
return nil
|
2020-08-21 12:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *testHasher) Hash() common.Hash {
|
|
|
|
return common.BytesToHash(h.hasher.Sum(nil))
|
|
|
|
}
|
|
|
|
|
2020-07-06 09:17:09 +00:00
|
|
|
func makeBenchBlock() *Block {
|
|
|
|
var (
|
|
|
|
key, _ = crypto.GenerateKey()
|
|
|
|
txs = make([]*Transaction, 70)
|
|
|
|
receipts = make([]*Receipt, len(txs))
|
2021-02-25 14:26:57 +00:00
|
|
|
signer = LatestSigner(params.TestChainConfig)
|
2020-07-06 09:17:09 +00:00
|
|
|
uncles = make([]*Header, 3)
|
|
|
|
)
|
|
|
|
header := &Header{
|
|
|
|
Difficulty: math.BigPow(11, 11),
|
|
|
|
Number: math.BigPow(2, 9),
|
|
|
|
GasLimit: 12345678,
|
|
|
|
GasUsed: 1476322,
|
|
|
|
Time: 9876543,
|
|
|
|
Extra: []byte("coolest block on chain"),
|
|
|
|
}
|
|
|
|
for i := range txs {
|
|
|
|
amount := math.BigPow(2, int64(i))
|
|
|
|
price := big.NewInt(300000)
|
|
|
|
data := make([]byte, 100)
|
|
|
|
tx := NewTransaction(uint64(i), common.Address{}, amount, 123457, price, data)
|
|
|
|
signedTx, err := SignTx(tx, signer, key)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
txs[i] = signedTx
|
|
|
|
receipts[i] = NewReceipt(make([]byte, 32), false, tx.Gas())
|
|
|
|
}
|
|
|
|
for i := range uncles {
|
|
|
|
uncles[i] = &Header{
|
|
|
|
Difficulty: math.BigPow(11, 11),
|
|
|
|
Number: math.BigPow(2, 9),
|
|
|
|
GasLimit: 12345678,
|
|
|
|
GasUsed: 1476322,
|
|
|
|
Time: 9876543,
|
|
|
|
Extra: []byte("benchmark uncle"),
|
|
|
|
}
|
2019-04-08 07:13:05 +00:00
|
|
|
}
|
2020-08-21 12:10:40 +00:00
|
|
|
return NewBlock(header, txs, uncles, receipts, newHasher())
|
2019-04-08 07:13:05 +00:00
|
|
|
}
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 16:50:58 +00:00
|
|
|
|
|
|
|
func TestRlpDecodeParentHash(t *testing.T) {
|
|
|
|
// A minimum one
|
|
|
|
want := common.HexToHash("0x112233445566778899001122334455667788990011223344556677889900aabb")
|
2022-02-18 07:10:26 +00:00
|
|
|
if rlpData, err := rlp.EncodeToBytes(&Header{ParentHash: want}); err != nil {
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 16:50:58 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
} else {
|
|
|
|
if have := HeaderParentHashFromRLP(rlpData); have != want {
|
|
|
|
t.Fatalf("have %x, want %x", have, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// And a maximum one
|
|
|
|
// | Difficulty | dynamic| *big.Int | 0x5ad3c2c71bbff854908 (current mainnet TD: 76 bits) |
|
|
|
|
// | Number | dynamic| *big.Int | 64 bits |
|
|
|
|
// | Extra | dynamic| []byte | 65+32 byte (clique) |
|
|
|
|
// | BaseFee | dynamic| *big.Int | 64 bits |
|
|
|
|
mainnetTd := new(big.Int)
|
|
|
|
mainnetTd.SetString("5ad3c2c71bbff854908", 16)
|
2022-02-18 07:10:26 +00:00
|
|
|
if rlpData, err := rlp.EncodeToBytes(&Header{
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 16:50:58 +00:00
|
|
|
ParentHash: want,
|
|
|
|
Difficulty: mainnetTd,
|
|
|
|
Number: new(big.Int).SetUint64(math.MaxUint64),
|
|
|
|
Extra: make([]byte, 65+32),
|
|
|
|
BaseFee: new(big.Int).SetUint64(math.MaxUint64),
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else {
|
|
|
|
if have := HeaderParentHashFromRLP(rlpData); have != want {
|
|
|
|
t.Fatalf("have %x, want %x", have, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Also test a very very large header.
|
|
|
|
{
|
2022-08-19 06:00:21 +00:00
|
|
|
// The rlp-encoding of the header belowCauses _total_ length of 65540,
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 16:50:58 +00:00
|
|
|
// which is the first to blow the fast-path.
|
2022-02-18 07:10:26 +00:00
|
|
|
h := &Header{
|
core, eth: improve delivery speed on header requests (#23105)
This PR reduces the amount of work we do when answering header queries, e.g. when a peer
is syncing from us.
For some items, e.g block bodies, when we read the rlp-data from database, we plug it
directly into the response package. We didn't do that for headers, but instead read
headers-rlp, decode to types.Header, and re-encode to rlp. This PR changes that to keep it
in RLP-form as much as possible. When a node is syncing from us, it typically requests 192
contiguous headers. On master it has the following effect:
- For headers not in ancient: 2 db lookups. One for translating hash->number (even though
the request is by number), and another for reading by hash (this latter one is sometimes
cached).
- For headers in ancient: 1 file lookup/syscall for translating hash->number (even though
the request is by number), and another for reading the header itself. After this, it
also performes a hashing of the header, to ensure that the hash is what it expected. In
this PR, I instead move the logic for "give me a sequence of blocks" into the lower
layers, where the database can determine how and what to read from leveldb and/or
ancients.
There are basically four types of requests; three of them are improved this way. The
fourth, by hash going backwards, is more tricky to optimize. However, since we know that
the gap is 0, we can look up by the parentHash, and stlil shave off all the number->hash
lookups.
The gapped collection can be optimized similarly, as a follow-up, at least in three out of
four cases.
Co-authored-by: Felix Lange <fjl@twurst.com>
2021-12-07 16:50:58 +00:00
|
|
|
ParentHash: want,
|
|
|
|
Extra: make([]byte, 65041),
|
|
|
|
}
|
|
|
|
if rlpData, err := rlp.EncodeToBytes(h); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else {
|
|
|
|
if have := HeaderParentHashFromRLP(rlpData); have != want {
|
|
|
|
t.Fatalf("have %x, want %x", have, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// Test some invalid erroneous stuff
|
|
|
|
for i, rlpData := range [][]byte{
|
|
|
|
nil,
|
|
|
|
common.FromHex("0x"),
|
|
|
|
common.FromHex("0x01"),
|
|
|
|
common.FromHex("0x3031323334"),
|
|
|
|
} {
|
|
|
|
if have, want := HeaderParentHashFromRLP(rlpData), (common.Hash{}); have != want {
|
|
|
|
t.Fatalf("invalid %d: have %x, want %x", i, have, want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|