Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify Header.EncodeRLP #5995

Merged
merged 2 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 28 additions & 153 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (n *BlockNonce) UnmarshalText(input []byte) error {
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner" gencodec:"required"`
Coinbase common.Address `json:"miner"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Expand All @@ -89,27 +89,22 @@ type Header struct {
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
BaseFee *big.Int `json:"baseFeePerGas"`
AuRaStep uint64
AuRaSeal []byte
// AuRa extensions (alternative to MixDigest & Nonce)
AuRaStep uint64
AuRaSeal []byte

BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559

// The verkle proof is ignored in legacy headers
Verkle bool
VerkleProof []byte `json:"verkleProof"`
VerkleKeyVals []verkle.KeyValuePair `json:"verkleKeyVals"`
VerkleProof []byte
VerkleKeyVals []verkle.KeyValuePair
}

func (h Header) EncodingSize() int {
func (h *Header) EncodingSize() int {
encodingSize := 33 /* ParentHash */ + 33 /* UncleHash */ + 21 /* Coinbase */ + 33 /* Root */ + 33 /* TxHash */ +
33 /* ReceiptHash */ + 259 /* Bloom */

if len(h.AuRaSeal) != 0 {
encodingSize += 1 + rlp.IntLenExcludingHead(h.AuRaStep) + 1 + len(h.AuRaSeal)
if len(h.AuRaSeal) >= 56 {
encodingSize += (bits.Len(uint(len(h.AuRaSeal))) + 7) / 8
}
} else {
encodingSize += 33 /* MixDigest */ + 9 /* BlockNonce */
}
encodingSize++
if h.Difficulty != nil {
encodingSize += rlp.BigIntLenExcludingHead(h.Difficulty)
Expand Down Expand Up @@ -138,48 +133,6 @@ func (h Header) EncodingSize() int {
}
encodingSize += len(h.Extra)
}
// size of BaseFee
var baseFeeBitLen, baseFeeLen int
if h.BaseFee != nil {
encodingSize++
baseFeeBitLen = h.BaseFee.BitLen()
if baseFeeBitLen >= 8 {
baseFeeLen = (baseFeeBitLen + 7) / 8
}
encodingSize += baseFeeLen
}

if h.Verkle {
// Encoding of Verkle Proof
encodingSize++
switch len(h.VerkleProof) {
case 0:
case 1:
if h.VerkleProof[0] >= 128 {
encodingSize++
}
default:
if len(h.VerkleProof) >= 56 {
encodingSize += (bits.Len(uint(len(h.VerkleProof))) + 7) / 8
}
encodingSize += len(h.VerkleProof)
}
encodingSize++

var tmpBuffer bytes.Buffer
if err := rlp.Encode(&tmpBuffer, h.VerkleKeyVals); err != nil {
panic(err)
}
encodingSize += tmpBuffer.Len()
}

return encodingSize
}

func (h Header) EncodeRLP(w io.Writer) error {
// Precompute the size of the encoding
encodingSize := 33 /* ParentHash */ + 33 /* UncleHash */ + 21 /* Coinbase */ + 33 /* Root */ + 33 /* TxHash */ +
33 /* ReceiptHash */ + 259 /* Bloom */

if len(h.AuRaSeal) != 0 {
encodingSize += 1 + rlp.IntLenExcludingHead(h.AuRaStep) + 1 + len(h.AuRaSeal)
Expand All @@ -189,6 +142,12 @@ func (h Header) EncodeRLP(w io.Writer) error {
} else {
encodingSize += 33 /* MixDigest */ + 9 /* BlockNonce */
}

if h.BaseFee != nil {
encodingSize++
encodingSize += rlp.BigIntLenExcludingHead(h.BaseFee)
}

if h.Verkle {
// Encoding of Verkle Proof
encodingSize++
Expand All @@ -208,62 +167,16 @@ func (h Header) EncodeRLP(w io.Writer) error {

var tmpBuffer bytes.Buffer
if err := rlp.Encode(&tmpBuffer, h.VerkleKeyVals); err != nil {
return nil
panic(err)
}
encodingSize += tmpBuffer.Len()
}

encodingSize++
var diffBitLen, diffLen int
if h.Difficulty != nil {
diffBitLen = h.Difficulty.BitLen()
if diffBitLen >= 8 {
diffLen = (diffBitLen + 7) / 8
}
}
encodingSize += diffLen

encodingSize++
var numberBitLen, numberLen int
if h.Number != nil {
numberBitLen = h.Number.BitLen()
if numberBitLen >= 8 {
numberLen = (numberBitLen + 7) / 8
}
}
encodingSize += numberLen

encodingSize++
encodingSize += rlp.IntLenExcludingHead(h.GasLimit)
return encodingSize
}

encodingSize++
encodingSize += rlp.IntLenExcludingHead(h.GasUsed)

encodingSize++
encodingSize += rlp.IntLenExcludingHead(h.Time)
// size of Extra
encodingSize++
switch len(h.Extra) {
case 0:
case 1:
if h.Extra[0] >= 128 {
encodingSize++
}
default:
if len(h.Extra) >= 56 {
encodingSize += (bits.Len(uint(len(h.Extra))) + 7) / 8
}
encodingSize += len(h.Extra)
}
var baseFeeBitLen, baseFeeLen int
if h.BaseFee != nil {
encodingSize++
baseFeeBitLen = h.BaseFee.BitLen()
if baseFeeBitLen >= 8 {
baseFeeLen = (baseFeeBitLen + 7) / 8
}
encodingSize += baseFeeLen
}
func (h *Header) EncodeRLP(w io.Writer) error {
encodingSize := h.EncodingSize()

var b [33]byte
// Prefix
Expand Down Expand Up @@ -318,37 +231,11 @@ func (h Header) EncodeRLP(w io.Writer) error {
if _, err := w.Write(h.Bloom.Bytes()); err != nil {
return err
}
if diffBitLen < 8 {
if diffBitLen > 0 {
b[0] = byte(h.Difficulty.Uint64())
} else {
b[0] = 128
}
if _, err := w.Write(b[:1]); err != nil {
return err
}
} else {
b[0] = 128 + byte(diffLen)
h.Difficulty.FillBytes(b[1 : 1+diffLen])
if _, err := w.Write(b[:1+diffLen]); err != nil {
return err
}
if err := rlp.EncodeBigInt(h.Difficulty, w, b[:]); err != nil {
return err
}
if numberBitLen < 8 {
if numberBitLen > 0 {
b[0] = byte(h.Number.Uint64())
} else {
b[0] = 128
}
if _, err := w.Write(b[:1]); err != nil {
return err
}
} else {
b[0] = 128 + byte(numberLen)
h.Number.FillBytes(b[1 : 1+numberLen])
if _, err := w.Write(b[:1+numberLen]); err != nil {
return err
}
if err := rlp.EncodeBigInt(h.Number, w, b[:]); err != nil {
return err
}
if err := rlp.EncodeInt(h.GasLimit, w, b[:]); err != nil {
return err
Expand Down Expand Up @@ -388,21 +275,8 @@ func (h Header) EncodeRLP(w io.Writer) error {
}

if h.BaseFee != nil {
if baseFeeBitLen < 8 {
if baseFeeBitLen > 0 {
b[0] = byte(h.BaseFee.Uint64())
} else {
b[0] = 128
}
if _, err := w.Write(b[:1]); err != nil {
return err
}
} else {
b[0] = 128 + byte(baseFeeLen)
h.BaseFee.FillBytes(b[1 : 1+baseFeeLen])
if _, err := w.Write(b[:1+baseFeeLen]); err != nil {
return err
}
if err := rlp.EncodeBigInt(h.BaseFee, w, b[:]); err != nil {
return err
}
}

Expand Down Expand Up @@ -544,6 +418,7 @@ func (h *Header) DecodeRLP(s *rlp.Stream) error {
}
rlp.DecodeBytes(rawKv, h.VerkleKeyVals)
}

if err := s.ListEnd(); err != nil {
return fmt.Errorf("close header struct: %w", err)
}
Expand Down
13 changes: 6 additions & 7 deletions core/types/gen_header_json.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions rlp/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,28 @@ func EncodeInt(i uint64, w io.Writer, buffer []byte) error {
return err
}

func EncodeBigInt(i *big.Int, w io.Writer, buffer []byte) error {
bitLen := 0 // treat nil as 0
if i != nil {
bitLen = i.BitLen()
}
if bitLen < 8 {
if bitLen > 0 {
buffer[0] = byte(i.Uint64())
} else {
buffer[0] = 0x80
}
_, err := w.Write(buffer[:1])
return err
}

size := (bitLen + 7) / 8
buffer[0] = 0x80 + byte(size)
i.FillBytes(buffer[1 : 1+size])
_, err := w.Write(buffer[:1+size])
return err
}

func EncodeString(s []byte, w io.Writer, buffer []byte) error {
switch len(s) {
case 0:
Expand Down