mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
feat(transactions): support blob tx only in encoding/decoding (#626)
* draft change * fix CI * remove CancunBlock params and change cancunSigner to londonSignerWithEIP4844 * support blob transactions in receipt * trigger ci * bump version
This commit is contained in:
parent
d86b42cdaa
commit
ae7cbae19c
16 changed files with 5474 additions and 150 deletions
238
core/types/blob_tx.go
Normal file
238
core/types/blob_tx.go
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
// Copyright 2023 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/holiman/uint256"
|
||||||
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
|
"github.com/scroll-tech/go-ethereum/crypto/kzg4844"
|
||||||
|
"github.com/scroll-tech/go-ethereum/params"
|
||||||
|
"github.com/scroll-tech/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BlobTx represents an EIP-4844 transaction.
|
||||||
|
type BlobTx struct {
|
||||||
|
ChainID *uint256.Int
|
||||||
|
Nonce uint64
|
||||||
|
GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas
|
||||||
|
GasFeeCap *uint256.Int // a.k.a. maxFeePerGas
|
||||||
|
Gas uint64
|
||||||
|
To common.Address
|
||||||
|
Value *uint256.Int
|
||||||
|
Data []byte
|
||||||
|
AccessList AccessList
|
||||||
|
BlobFeeCap *uint256.Int // a.k.a. maxFeePerBlobGas
|
||||||
|
BlobHashes []common.Hash
|
||||||
|
|
||||||
|
// A blob transaction can optionally contain blobs. This field must be set when BlobTx
|
||||||
|
// is used to create a transaction for sigining.
|
||||||
|
Sidecar *BlobTxSidecar `rlp:"-"`
|
||||||
|
|
||||||
|
// Signature values
|
||||||
|
V *uint256.Int `json:"v" gencodec:"required"`
|
||||||
|
R *uint256.Int `json:"r" gencodec:"required"`
|
||||||
|
S *uint256.Int `json:"s" gencodec:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobTxSidecar contains the blobs of a blob transaction.
|
||||||
|
type BlobTxSidecar struct {
|
||||||
|
Blobs []kzg4844.Blob // Blobs needed by the blob pool
|
||||||
|
Commitments []kzg4844.Commitment // Commitments needed by the blob pool
|
||||||
|
Proofs []kzg4844.Proof // Proofs needed by the blob pool
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobHashes computes the blob hashes of the given blobs.
|
||||||
|
func (sc *BlobTxSidecar) BlobHashes() []common.Hash {
|
||||||
|
hasher := sha256.New()
|
||||||
|
h := make([]common.Hash, len(sc.Commitments))
|
||||||
|
for i := range sc.Blobs {
|
||||||
|
h[i] = kzg4844.CalcBlobHashV1(hasher, &sc.Commitments[i])
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodedSize computes the RLP size of the sidecar elements. This does NOT return the
|
||||||
|
// encoded size of the BlobTxSidecar, it's just a helper for tx.Size().
|
||||||
|
func (sc *BlobTxSidecar) encodedSize() uint64 {
|
||||||
|
var blobs, commitments, proofs uint64
|
||||||
|
for i := range sc.Blobs {
|
||||||
|
blobs += rlp.BytesSize(sc.Blobs[i][:])
|
||||||
|
}
|
||||||
|
for i := range sc.Commitments {
|
||||||
|
commitments += rlp.BytesSize(sc.Commitments[i][:])
|
||||||
|
}
|
||||||
|
for i := range sc.Proofs {
|
||||||
|
proofs += rlp.BytesSize(sc.Proofs[i][:])
|
||||||
|
}
|
||||||
|
return rlp.ListSize(blobs) + rlp.ListSize(commitments) + rlp.ListSize(proofs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// blobTxWithBlobs is used for encoding of transactions when blobs are present.
|
||||||
|
type blobTxWithBlobs struct {
|
||||||
|
BlobTx *BlobTx
|
||||||
|
Blobs []kzg4844.Blob
|
||||||
|
Commitments []kzg4844.Commitment
|
||||||
|
Proofs []kzg4844.Proof
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy creates a deep copy of the transaction data and initializes all fields.
|
||||||
|
func (tx *BlobTx) copy() TxData {
|
||||||
|
cpy := &BlobTx{
|
||||||
|
Nonce: tx.Nonce,
|
||||||
|
To: tx.To,
|
||||||
|
Data: common.CopyBytes(tx.Data),
|
||||||
|
Gas: tx.Gas,
|
||||||
|
// These are copied below.
|
||||||
|
AccessList: make(AccessList, len(tx.AccessList)),
|
||||||
|
BlobHashes: make([]common.Hash, len(tx.BlobHashes)),
|
||||||
|
Value: new(uint256.Int),
|
||||||
|
ChainID: new(uint256.Int),
|
||||||
|
GasTipCap: new(uint256.Int),
|
||||||
|
GasFeeCap: new(uint256.Int),
|
||||||
|
BlobFeeCap: new(uint256.Int),
|
||||||
|
V: new(uint256.Int),
|
||||||
|
R: new(uint256.Int),
|
||||||
|
S: new(uint256.Int),
|
||||||
|
}
|
||||||
|
copy(cpy.AccessList, tx.AccessList)
|
||||||
|
copy(cpy.BlobHashes, tx.BlobHashes)
|
||||||
|
|
||||||
|
if tx.Value != nil {
|
||||||
|
cpy.Value.Set(tx.Value)
|
||||||
|
}
|
||||||
|
if tx.ChainID != nil {
|
||||||
|
cpy.ChainID.Set(tx.ChainID)
|
||||||
|
}
|
||||||
|
if tx.GasTipCap != nil {
|
||||||
|
cpy.GasTipCap.Set(tx.GasTipCap)
|
||||||
|
}
|
||||||
|
if tx.GasFeeCap != nil {
|
||||||
|
cpy.GasFeeCap.Set(tx.GasFeeCap)
|
||||||
|
}
|
||||||
|
if tx.BlobFeeCap != nil {
|
||||||
|
cpy.BlobFeeCap.Set(tx.BlobFeeCap)
|
||||||
|
}
|
||||||
|
if tx.V != nil {
|
||||||
|
cpy.V.Set(tx.V)
|
||||||
|
}
|
||||||
|
if tx.R != nil {
|
||||||
|
cpy.R.Set(tx.R)
|
||||||
|
}
|
||||||
|
if tx.S != nil {
|
||||||
|
cpy.S.Set(tx.S)
|
||||||
|
}
|
||||||
|
if tx.Sidecar != nil {
|
||||||
|
cpy.Sidecar = &BlobTxSidecar{
|
||||||
|
Blobs: append([]kzg4844.Blob(nil), tx.Sidecar.Blobs...),
|
||||||
|
Commitments: append([]kzg4844.Commitment(nil), tx.Sidecar.Commitments...),
|
||||||
|
Proofs: append([]kzg4844.Proof(nil), tx.Sidecar.Proofs...),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// accessors for innerTx.
|
||||||
|
func (tx *BlobTx) txType() byte { return BlobTxType }
|
||||||
|
func (tx *BlobTx) chainID() *big.Int { return tx.ChainID.ToBig() }
|
||||||
|
func (tx *BlobTx) accessList() AccessList { return tx.AccessList }
|
||||||
|
func (tx *BlobTx) data() []byte { return tx.Data }
|
||||||
|
func (tx *BlobTx) gas() uint64 { return tx.Gas }
|
||||||
|
func (tx *BlobTx) gasFeeCap() *big.Int { return tx.GasFeeCap.ToBig() }
|
||||||
|
func (tx *BlobTx) gasTipCap() *big.Int { return tx.GasTipCap.ToBig() }
|
||||||
|
func (tx *BlobTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() }
|
||||||
|
func (tx *BlobTx) value() *big.Int { return tx.Value.ToBig() }
|
||||||
|
func (tx *BlobTx) nonce() uint64 { return tx.Nonce }
|
||||||
|
func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp }
|
||||||
|
func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) }
|
||||||
|
|
||||||
|
func (tx *BlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||||
|
if baseFee == nil {
|
||||||
|
return dst.Set(tx.GasFeeCap.ToBig())
|
||||||
|
}
|
||||||
|
tip := dst.Sub(tx.GasFeeCap.ToBig(), baseFee)
|
||||||
|
if tip.Cmp(tx.GasTipCap.ToBig()) > 0 {
|
||||||
|
tip.Set(tx.GasTipCap.ToBig())
|
||||||
|
}
|
||||||
|
return tip.Add(tip, baseFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *BlobTx) rawSignatureValues() (v, r, s *big.Int) {
|
||||||
|
return tx.V.ToBig(), tx.R.ToBig(), tx.S.ToBig()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *BlobTx) setSignatureValues(chainID, v, r, s *big.Int) {
|
||||||
|
tx.ChainID.SetFromBig(chainID)
|
||||||
|
tx.V.SetFromBig(v)
|
||||||
|
tx.R.SetFromBig(r)
|
||||||
|
tx.S.SetFromBig(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *BlobTx) withoutSidecar() *BlobTx {
|
||||||
|
cpy := *tx
|
||||||
|
cpy.Sidecar = nil
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *BlobTx) encode(b *bytes.Buffer) error {
|
||||||
|
if tx.Sidecar == nil {
|
||||||
|
return rlp.Encode(b, tx)
|
||||||
|
}
|
||||||
|
inner := &blobTxWithBlobs{
|
||||||
|
BlobTx: tx,
|
||||||
|
Blobs: tx.Sidecar.Blobs,
|
||||||
|
Commitments: tx.Sidecar.Commitments,
|
||||||
|
Proofs: tx.Sidecar.Proofs,
|
||||||
|
}
|
||||||
|
return rlp.Encode(b, inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *BlobTx) decode(input []byte) error {
|
||||||
|
// Here we need to support two formats: the network protocol encoding of the tx (with
|
||||||
|
// blobs) or the canonical encoding without blobs.
|
||||||
|
//
|
||||||
|
// The two encodings can be distinguished by checking whether the first element of the
|
||||||
|
// input list is itself a list.
|
||||||
|
|
||||||
|
outerList, _, err := rlp.SplitList(input)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
firstElemKind, _, _, err := rlp.Split(outerList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if firstElemKind != rlp.List {
|
||||||
|
return rlp.DecodeBytes(input, tx)
|
||||||
|
}
|
||||||
|
// It's a tx with blobs.
|
||||||
|
var inner blobTxWithBlobs
|
||||||
|
if err := rlp.DecodeBytes(input, &inner); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*tx = *inner.BlobTx
|
||||||
|
tx.Sidecar = &BlobTxSidecar{
|
||||||
|
Blobs: inner.Blobs,
|
||||||
|
Commitments: inner.Commitments,
|
||||||
|
Proofs: inner.Proofs,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -61,9 +61,12 @@ type Receipt struct {
|
||||||
|
|
||||||
// Implementation fields: These fields are added by geth when processing a transaction.
|
// Implementation fields: These fields are added by geth when processing a transaction.
|
||||||
// They are stored in the chain database.
|
// They are stored in the chain database.
|
||||||
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
|
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
|
||||||
ContractAddress common.Address `json:"contractAddress"`
|
ContractAddress common.Address `json:"contractAddress"`
|
||||||
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
||||||
|
EffectiveGasPrice *big.Int `json:"effectiveGasPrice"` // required, but tag omitted for backwards compatibility
|
||||||
|
BlobGasUsed uint64 `json:"blobGasUsed,omitempty"`
|
||||||
|
BlobGasPrice *big.Int `json:"blobGasPrice,omitempty"`
|
||||||
|
|
||||||
// Inclusion information: These fields provide information about the inclusion of the
|
// Inclusion information: These fields provide information about the inclusion of the
|
||||||
// transaction corresponding to this receipt.
|
// transaction corresponding to this receipt.
|
||||||
|
|
@ -84,6 +87,7 @@ type receiptMarshaling struct {
|
||||||
Status hexutil.Uint64
|
Status hexutil.Uint64
|
||||||
CumulativeGasUsed hexutil.Uint64
|
CumulativeGasUsed hexutil.Uint64
|
||||||
GasUsed hexutil.Uint64
|
GasUsed hexutil.Uint64
|
||||||
|
EffectiveGasPrice *hexutil.Big
|
||||||
BlockNumber *hexutil.Big
|
BlockNumber *hexutil.Big
|
||||||
TransactionIndex hexutil.Uint
|
TransactionIndex hexutil.Uint
|
||||||
L1Fee *hexutil.Big
|
L1Fee *hexutil.Big
|
||||||
|
|
@ -203,18 +207,7 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(b) == 0 {
|
return r.decodeTyped(b)
|
||||||
return errEmptyTypedReceipt
|
|
||||||
}
|
|
||||||
r.Type = b[0]
|
|
||||||
if r.Type == AccessListTxType || r.Type == DynamicFeeTxType || r.Type == L1MessageTxType {
|
|
||||||
var dec receiptRLP
|
|
||||||
if err := rlp.DecodeBytes(b[1:], &dec); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.setFromRLP(dec)
|
|
||||||
}
|
|
||||||
return ErrTxTypeNotSupported
|
|
||||||
default:
|
default:
|
||||||
return rlp.ErrExpectedList
|
return rlp.ErrExpectedList
|
||||||
}
|
}
|
||||||
|
|
@ -243,7 +236,7 @@ func (r *Receipt) decodeTyped(b []byte) error {
|
||||||
return errEmptyTypedReceipt
|
return errEmptyTypedReceipt
|
||||||
}
|
}
|
||||||
switch b[0] {
|
switch b[0] {
|
||||||
case DynamicFeeTxType, AccessListTxType, L1MessageTxType:
|
case DynamicFeeTxType, AccessListTxType, BlobTxType, L1MessageTxType:
|
||||||
var data receiptRLP
|
var data receiptRLP
|
||||||
err := rlp.DecodeBytes(b[1:], &data)
|
err := rlp.DecodeBytes(b[1:], &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -435,6 +428,9 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
|
||||||
case DynamicFeeTxType:
|
case DynamicFeeTxType:
|
||||||
w.WriteByte(DynamicFeeTxType)
|
w.WriteByte(DynamicFeeTxType)
|
||||||
rlp.Encode(w, data)
|
rlp.Encode(w, data)
|
||||||
|
case BlobTxType:
|
||||||
|
w.WriteByte(BlobTxType)
|
||||||
|
rlp.Encode(w, data)
|
||||||
case L1MessageTxType:
|
case L1MessageTxType:
|
||||||
w.WriteByte(L1MessageTxType)
|
w.WriteByte(L1MessageTxType)
|
||||||
rlp.Encode(w, data)
|
rlp.Encode(w, data)
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,17 @@ var (
|
||||||
ErrTxTypeNotSupported = errors.New("transaction type not supported")
|
ErrTxTypeNotSupported = errors.New("transaction type not supported")
|
||||||
ErrGasFeeCapTooLow = errors.New("fee cap less than base fee")
|
ErrGasFeeCapTooLow = errors.New("fee cap less than base fee")
|
||||||
errEmptyTypedTx = errors.New("empty typed transaction bytes")
|
errEmptyTypedTx = errors.New("empty typed transaction bytes")
|
||||||
|
errInvalidYParity = errors.New("'yParity' field must be 0 or 1")
|
||||||
|
errVYParityMismatch = errors.New("'v' and 'yParity' fields do not match")
|
||||||
|
errVYParityMissing = errors.New("missing 'yParity' or 'v' field in transaction")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transaction types.
|
// Transaction types.
|
||||||
const (
|
const (
|
||||||
LegacyTxType = iota
|
LegacyTxType = 0x00
|
||||||
AccessListTxType
|
AccessListTxType = 0x01
|
||||||
DynamicFeeTxType
|
DynamicFeeTxType = 0x02
|
||||||
|
BlobTxType = 0x03
|
||||||
|
|
||||||
L1MessageTxType = 0x7E
|
L1MessageTxType = 0x7E
|
||||||
)
|
)
|
||||||
|
|
@ -191,6 +195,10 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
||||||
var inner DynamicFeeTx
|
var inner DynamicFeeTx
|
||||||
err := rlp.DecodeBytes(b[1:], &inner)
|
err := rlp.DecodeBytes(b[1:], &inner)
|
||||||
return &inner, err
|
return &inner, err
|
||||||
|
case BlobTxType:
|
||||||
|
var inner BlobTx
|
||||||
|
err := rlp.DecodeBytes(b[1:], &inner)
|
||||||
|
return &inner, err
|
||||||
case L1MessageTxType:
|
case L1MessageTxType:
|
||||||
var inner L1MessageTx
|
var inner L1MessageTx
|
||||||
err := rlp.DecodeBytes(b[1:], &inner)
|
err := rlp.DecodeBytes(b[1:], &inner)
|
||||||
|
|
@ -296,6 +304,68 @@ func (tx *Transaction) To() *common.Address {
|
||||||
return copyAddressPtr(tx.inner.to())
|
return copyAddressPtr(tx.inner.to())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise.
|
||||||
|
func (tx *Transaction) BlobGas() uint64 {
|
||||||
|
if blobtx, ok := tx.inner.(*BlobTx); ok {
|
||||||
|
return blobtx.blobGas()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobGasFeeCap returns the blob gas fee cap per blob gas of the transaction for blob transactions, nil otherwise.
|
||||||
|
func (tx *Transaction) BlobGasFeeCap() *big.Int {
|
||||||
|
if blobtx, ok := tx.inner.(*BlobTx); ok {
|
||||||
|
return blobtx.BlobFeeCap.ToBig()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobHashes returns the hashes of the blob commitments for blob transactions, nil otherwise.
|
||||||
|
func (tx *Transaction) BlobHashes() []common.Hash {
|
||||||
|
if blobtx, ok := tx.inner.(*BlobTx); ok {
|
||||||
|
return blobtx.BlobHashes
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobTxSidecar returns the sidecar of a blob transaction, nil otherwise.
|
||||||
|
func (tx *Transaction) BlobTxSidecar() *BlobTxSidecar {
|
||||||
|
if blobtx, ok := tx.inner.(*BlobTx); ok {
|
||||||
|
return blobtx.Sidecar
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobGasFeeCapCmp compares the blob fee cap of two transactions.
|
||||||
|
func (tx *Transaction) BlobGasFeeCapCmp(other *Transaction) int {
|
||||||
|
return tx.BlobGasFeeCap().Cmp(other.BlobGasFeeCap())
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobGasFeeCapIntCmp compares the blob fee cap of the transaction against the given blob fee cap.
|
||||||
|
func (tx *Transaction) BlobGasFeeCapIntCmp(other *big.Int) int {
|
||||||
|
return tx.BlobGasFeeCap().Cmp(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutBlobTxSidecar returns a copy of tx with the blob sidecar removed.
|
||||||
|
func (tx *Transaction) WithoutBlobTxSidecar() *Transaction {
|
||||||
|
blobtx, ok := tx.inner.(*BlobTx)
|
||||||
|
if !ok {
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
cpy := &Transaction{
|
||||||
|
inner: blobtx.withoutSidecar(),
|
||||||
|
time: tx.time,
|
||||||
|
}
|
||||||
|
// Note: tx.size cache not carried over because the sidecar is included in size!
|
||||||
|
if h := tx.hash.Load(); h != nil {
|
||||||
|
cpy.hash.Store(h)
|
||||||
|
}
|
||||||
|
if f := tx.from.Load(); f != nil {
|
||||||
|
cpy.from.Store(f)
|
||||||
|
}
|
||||||
|
return cpy
|
||||||
|
}
|
||||||
|
|
||||||
// IsL1MessageTx returns true if the transaction is an L1 cross-domain tx.
|
// IsL1MessageTx returns true if the transaction is an L1 cross-domain tx.
|
||||||
func (tx *Transaction) IsL1MessageTx() bool {
|
func (tx *Transaction) IsL1MessageTx() bool {
|
||||||
return tx.Type() == L1MessageTxType
|
return tx.Type() == L1MessageTxType
|
||||||
|
|
@ -408,16 +478,32 @@ func (tx *Transaction) Hash() common.Hash {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the true RLP encoded storage size of the transaction, either by
|
// Size returns the true encoded storage size of the transaction, either by encoding
|
||||||
// encoding and returning it, or returning a previously cached value.
|
// and returning it, or returning a previously cached value.
|
||||||
func (tx *Transaction) Size() common.StorageSize {
|
func (tx *Transaction) Size() common.StorageSize {
|
||||||
if size := tx.size.Load(); size != nil {
|
if size := tx.size.Load(); size != nil {
|
||||||
return size.(common.StorageSize)
|
return size.(common.StorageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache miss, encode and cache.
|
||||||
|
// Note we rely on the assumption that all tx.inner values are RLP-encoded!
|
||||||
c := writeCounter(0)
|
c := writeCounter(0)
|
||||||
rlp.Encode(&c, &tx.inner)
|
rlp.Encode(&c, &tx.inner)
|
||||||
tx.size.Store(common.StorageSize(c))
|
size := common.StorageSize(c)
|
||||||
return common.StorageSize(c)
|
|
||||||
|
// For blob transactions, add the size of the blob content and the outer list of the
|
||||||
|
// tx + sidecar encoding.
|
||||||
|
if sc := tx.BlobTxSidecar(); sc != nil {
|
||||||
|
size += common.StorageSize(rlp.ListSize(sc.encodedSize()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// For typed transactions, the encoding also includes the leading type byte.
|
||||||
|
if tx.Type() != LegacyTxType {
|
||||||
|
size += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.size.Store(size)
|
||||||
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithSignature returns a new transaction with the given signature.
|
// WithSignature returns a new transaction with the given signature.
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/holiman/uint256"
|
||||||
"github.com/scroll-tech/go-ethereum/common"
|
"github.com/scroll-tech/go-ethereum/common"
|
||||||
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
||||||
)
|
)
|
||||||
|
|
@ -29,22 +30,22 @@ import (
|
||||||
type txJSON struct {
|
type txJSON struct {
|
||||||
Type hexutil.Uint64 `json:"type"`
|
Type hexutil.Uint64 `json:"type"`
|
||||||
|
|
||||||
// Common transaction fields:
|
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
||||||
Nonce *hexutil.Uint64 `json:"nonce"`
|
Nonce *hexutil.Uint64 `json:"nonce"`
|
||||||
|
To *common.Address `json:"to"`
|
||||||
|
Gas *hexutil.Uint64 `json:"gas"`
|
||||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||||
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
|
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
|
||||||
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
|
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
|
||||||
Gas *hexutil.Uint64 `json:"gas"`
|
MaxFeePerBlobGas *hexutil.Big `json:"maxFeePerBlobGas,omitempty"`
|
||||||
Value *hexutil.Big `json:"value"`
|
Value *hexutil.Big `json:"value"`
|
||||||
Data *hexutil.Bytes `json:"input"`
|
Input *hexutil.Bytes `json:"input"`
|
||||||
|
AccessList *AccessList `json:"accessList,omitempty"`
|
||||||
|
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
|
||||||
V *hexutil.Big `json:"v"`
|
V *hexutil.Big `json:"v"`
|
||||||
R *hexutil.Big `json:"r"`
|
R *hexutil.Big `json:"r"`
|
||||||
S *hexutil.Big `json:"s"`
|
S *hexutil.Big `json:"s"`
|
||||||
To *common.Address `json:"to"`
|
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
|
||||||
|
|
||||||
// Access list transaction fields:
|
|
||||||
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
|
||||||
AccessList *AccessList `json:"accessList,omitempty"`
|
|
||||||
|
|
||||||
// Only used for encoding:
|
// Only used for encoding:
|
||||||
Hash common.Hash `json:"hash"`
|
Hash common.Hash `json:"hash"`
|
||||||
|
|
@ -54,65 +55,106 @@ type txJSON struct {
|
||||||
QueueIndex *hexutil.Uint64 `json:"queueIndex,omitempty"`
|
QueueIndex *hexutil.Uint64 `json:"queueIndex,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// yParityValue returns the YParity value from JSON. For backwards-compatibility reasons,
|
||||||
|
// this can be given in the 'v' field or the 'yParity' field. If both exist, they must match.
|
||||||
|
func (tx *txJSON) yParityValue() (*big.Int, error) {
|
||||||
|
if tx.YParity != nil {
|
||||||
|
val := uint64(*tx.YParity)
|
||||||
|
if val != 0 && val != 1 {
|
||||||
|
return nil, errInvalidYParity
|
||||||
|
}
|
||||||
|
bigval := new(big.Int).SetUint64(val)
|
||||||
|
if tx.V != nil && tx.V.ToInt().Cmp(bigval) != 0 {
|
||||||
|
return nil, errVYParityMismatch
|
||||||
|
}
|
||||||
|
return bigval, nil
|
||||||
|
}
|
||||||
|
if tx.V != nil {
|
||||||
|
return tx.V.ToInt(), nil
|
||||||
|
}
|
||||||
|
return nil, errVYParityMissing
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON marshals as JSON with a hash.
|
// MarshalJSON marshals as JSON with a hash.
|
||||||
func (t *Transaction) MarshalJSON() ([]byte, error) {
|
func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
||||||
var enc txJSON
|
var enc txJSON
|
||||||
// These are set for all tx types.
|
// These are set for all tx types.
|
||||||
enc.Hash = t.Hash()
|
enc.Hash = tx.Hash()
|
||||||
enc.Type = hexutil.Uint64(t.Type())
|
enc.Type = hexutil.Uint64(tx.Type())
|
||||||
|
|
||||||
// Other fields are set conditionally depending on tx type.
|
// Other fields are set conditionally depending on tx type.
|
||||||
switch tx := t.inner.(type) {
|
switch itx := tx.inner.(type) {
|
||||||
case *LegacyTx:
|
case *LegacyTx:
|
||||||
enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
|
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
|
||||||
enc.Gas = (*hexutil.Uint64)(&tx.Gas)
|
enc.To = tx.To()
|
||||||
enc.GasPrice = (*hexutil.Big)(tx.GasPrice)
|
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
|
||||||
enc.Value = (*hexutil.Big)(tx.Value)
|
enc.GasPrice = (*hexutil.Big)(itx.GasPrice)
|
||||||
enc.Data = (*hexutil.Bytes)(&tx.Data)
|
enc.Value = (*hexutil.Big)(itx.Value)
|
||||||
enc.To = t.To()
|
enc.Input = (*hexutil.Bytes)(&itx.Data)
|
||||||
enc.V = (*hexutil.Big)(tx.V)
|
enc.V = (*hexutil.Big)(itx.V)
|
||||||
enc.R = (*hexutil.Big)(tx.R)
|
enc.R = (*hexutil.Big)(itx.R)
|
||||||
enc.S = (*hexutil.Big)(tx.S)
|
enc.S = (*hexutil.Big)(itx.S)
|
||||||
|
if tx.Protected() {
|
||||||
|
enc.ChainID = (*hexutil.Big)(tx.ChainId())
|
||||||
|
}
|
||||||
|
|
||||||
case *AccessListTx:
|
case *AccessListTx:
|
||||||
enc.ChainID = (*hexutil.Big)(tx.ChainID)
|
enc.ChainID = (*hexutil.Big)(itx.ChainID)
|
||||||
enc.AccessList = &tx.AccessList
|
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
|
||||||
enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
|
enc.To = tx.To()
|
||||||
enc.Gas = (*hexutil.Uint64)(&tx.Gas)
|
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
|
||||||
enc.GasPrice = (*hexutil.Big)(tx.GasPrice)
|
enc.GasPrice = (*hexutil.Big)(itx.GasPrice)
|
||||||
enc.Value = (*hexutil.Big)(tx.Value)
|
enc.Value = (*hexutil.Big)(itx.Value)
|
||||||
enc.Data = (*hexutil.Bytes)(&tx.Data)
|
enc.Input = (*hexutil.Bytes)(&itx.Data)
|
||||||
enc.To = t.To()
|
enc.AccessList = &itx.AccessList
|
||||||
enc.V = (*hexutil.Big)(tx.V)
|
enc.V = (*hexutil.Big)(itx.V)
|
||||||
enc.R = (*hexutil.Big)(tx.R)
|
enc.R = (*hexutil.Big)(itx.R)
|
||||||
enc.S = (*hexutil.Big)(tx.S)
|
enc.S = (*hexutil.Big)(itx.S)
|
||||||
|
yparity := itx.V.Uint64()
|
||||||
|
enc.YParity = (*hexutil.Uint64)(&yparity)
|
||||||
|
|
||||||
case *DynamicFeeTx:
|
case *DynamicFeeTx:
|
||||||
enc.ChainID = (*hexutil.Big)(tx.ChainID)
|
enc.ChainID = (*hexutil.Big)(itx.ChainID)
|
||||||
enc.AccessList = &tx.AccessList
|
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
|
||||||
enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
|
enc.To = tx.To()
|
||||||
enc.Gas = (*hexutil.Uint64)(&tx.Gas)
|
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
|
||||||
enc.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap)
|
enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap)
|
||||||
enc.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap)
|
enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap)
|
||||||
enc.Value = (*hexutil.Big)(tx.Value)
|
enc.Value = (*hexutil.Big)(itx.Value)
|
||||||
enc.Data = (*hexutil.Bytes)(&tx.Data)
|
enc.Input = (*hexutil.Bytes)(&itx.Data)
|
||||||
enc.To = t.To()
|
enc.AccessList = &itx.AccessList
|
||||||
enc.V = (*hexutil.Big)(tx.V)
|
enc.V = (*hexutil.Big)(itx.V)
|
||||||
enc.R = (*hexutil.Big)(tx.R)
|
enc.R = (*hexutil.Big)(itx.R)
|
||||||
enc.S = (*hexutil.Big)(tx.S)
|
enc.S = (*hexutil.Big)(itx.S)
|
||||||
case *L1MessageTx:
|
yparity := itx.V.Uint64()
|
||||||
enc.QueueIndex = (*hexutil.Uint64)(&tx.QueueIndex)
|
enc.YParity = (*hexutil.Uint64)(&yparity)
|
||||||
enc.Gas = (*hexutil.Uint64)(&tx.Gas)
|
|
||||||
enc.To = t.To()
|
case *BlobTx:
|
||||||
enc.Value = (*hexutil.Big)(tx.Value)
|
enc.ChainID = (*hexutil.Big)(itx.ChainID.ToBig())
|
||||||
enc.Data = (*hexutil.Bytes)(&tx.Data)
|
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
|
||||||
enc.Sender = tx.Sender
|
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
|
||||||
|
enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap.ToBig())
|
||||||
|
enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap.ToBig())
|
||||||
|
enc.MaxFeePerBlobGas = (*hexutil.Big)(itx.BlobFeeCap.ToBig())
|
||||||
|
enc.Value = (*hexutil.Big)(itx.Value.ToBig())
|
||||||
|
enc.Input = (*hexutil.Bytes)(&itx.Data)
|
||||||
|
enc.AccessList = &itx.AccessList
|
||||||
|
enc.BlobVersionedHashes = itx.BlobHashes
|
||||||
|
enc.To = tx.To()
|
||||||
|
enc.V = (*hexutil.Big)(itx.V.ToBig())
|
||||||
|
enc.R = (*hexutil.Big)(itx.R.ToBig())
|
||||||
|
enc.S = (*hexutil.Big)(itx.S.ToBig())
|
||||||
|
yparity := itx.V.Uint64()
|
||||||
|
enc.YParity = (*hexutil.Uint64)(&yparity)
|
||||||
}
|
}
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
func (t *Transaction) UnmarshalJSON(input []byte) error {
|
func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
var dec txJSON
|
var dec txJSON
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
err := json.Unmarshal(input, &dec)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,43 +164,46 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
case LegacyTxType:
|
case LegacyTxType:
|
||||||
var itx LegacyTx
|
var itx LegacyTx
|
||||||
inner = &itx
|
inner = &itx
|
||||||
if dec.To != nil {
|
|
||||||
itx.To = dec.To
|
|
||||||
}
|
|
||||||
if dec.Nonce == nil {
|
if dec.Nonce == nil {
|
||||||
return errors.New("missing required field 'nonce' in transaction")
|
return errors.New("missing required field 'nonce' in transaction")
|
||||||
}
|
}
|
||||||
itx.Nonce = uint64(*dec.Nonce)
|
itx.Nonce = uint64(*dec.Nonce)
|
||||||
if dec.GasPrice == nil {
|
if dec.To != nil {
|
||||||
return errors.New("missing required field 'gasPrice' in transaction")
|
itx.To = dec.To
|
||||||
}
|
}
|
||||||
itx.GasPrice = (*big.Int)(dec.GasPrice)
|
|
||||||
if dec.Gas == nil {
|
if dec.Gas == nil {
|
||||||
return errors.New("missing required field 'gas' in transaction")
|
return errors.New("missing required field 'gas' in transaction")
|
||||||
}
|
}
|
||||||
itx.Gas = uint64(*dec.Gas)
|
itx.Gas = uint64(*dec.Gas)
|
||||||
|
if dec.GasPrice == nil {
|
||||||
|
return errors.New("missing required field 'gasPrice' in transaction")
|
||||||
|
}
|
||||||
|
itx.GasPrice = (*big.Int)(dec.GasPrice)
|
||||||
if dec.Value == nil {
|
if dec.Value == nil {
|
||||||
return errors.New("missing required field 'value' in transaction")
|
return errors.New("missing required field 'value' in transaction")
|
||||||
}
|
}
|
||||||
itx.Value = (*big.Int)(dec.Value)
|
itx.Value = (*big.Int)(dec.Value)
|
||||||
if dec.Data == nil {
|
if dec.Input == nil {
|
||||||
return errors.New("missing required field 'input' in transaction")
|
return errors.New("missing required field 'input' in transaction")
|
||||||
}
|
}
|
||||||
itx.Data = *dec.Data
|
itx.Data = *dec.Input
|
||||||
if dec.V == nil {
|
|
||||||
return errors.New("missing required field 'v' in transaction")
|
// signature R
|
||||||
}
|
|
||||||
itx.V = (*big.Int)(dec.V)
|
|
||||||
if dec.R == nil {
|
if dec.R == nil {
|
||||||
return errors.New("missing required field 'r' in transaction")
|
return errors.New("missing required field 'r' in transaction")
|
||||||
}
|
}
|
||||||
itx.R = (*big.Int)(dec.R)
|
itx.R = (*big.Int)(dec.R)
|
||||||
|
// signature S
|
||||||
if dec.S == nil {
|
if dec.S == nil {
|
||||||
return errors.New("missing required field 's' in transaction")
|
return errors.New("missing required field 's' in transaction")
|
||||||
}
|
}
|
||||||
itx.S = (*big.Int)(dec.S)
|
itx.S = (*big.Int)(dec.S)
|
||||||
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
|
// signature V
|
||||||
if withSignature {
|
if dec.V == nil {
|
||||||
|
return errors.New("missing required field 'v' in transaction")
|
||||||
|
}
|
||||||
|
itx.V = (*big.Int)(dec.V)
|
||||||
|
if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
|
||||||
if err := sanityCheckSignature(itx.V, itx.R, itx.S, true); err != nil {
|
if err := sanityCheckSignature(itx.V, itx.R, itx.S, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -167,51 +212,53 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
case AccessListTxType:
|
case AccessListTxType:
|
||||||
var itx AccessListTx
|
var itx AccessListTx
|
||||||
inner = &itx
|
inner = &itx
|
||||||
// Access list is optional for now.
|
|
||||||
if dec.AccessList != nil {
|
|
||||||
itx.AccessList = *dec.AccessList
|
|
||||||
}
|
|
||||||
if dec.ChainID == nil {
|
if dec.ChainID == nil {
|
||||||
return errors.New("missing required field 'chainId' in transaction")
|
return errors.New("missing required field 'chainId' in transaction")
|
||||||
}
|
}
|
||||||
itx.ChainID = (*big.Int)(dec.ChainID)
|
itx.ChainID = (*big.Int)(dec.ChainID)
|
||||||
if dec.To != nil {
|
|
||||||
itx.To = dec.To
|
|
||||||
}
|
|
||||||
if dec.Nonce == nil {
|
if dec.Nonce == nil {
|
||||||
return errors.New("missing required field 'nonce' in transaction")
|
return errors.New("missing required field 'nonce' in transaction")
|
||||||
}
|
}
|
||||||
itx.Nonce = uint64(*dec.Nonce)
|
itx.Nonce = uint64(*dec.Nonce)
|
||||||
if dec.GasPrice == nil {
|
if dec.To != nil {
|
||||||
return errors.New("missing required field 'gasPrice' in transaction")
|
itx.To = dec.To
|
||||||
}
|
}
|
||||||
itx.GasPrice = (*big.Int)(dec.GasPrice)
|
|
||||||
if dec.Gas == nil {
|
if dec.Gas == nil {
|
||||||
return errors.New("missing required field 'gas' in transaction")
|
return errors.New("missing required field 'gas' in transaction")
|
||||||
}
|
}
|
||||||
itx.Gas = uint64(*dec.Gas)
|
itx.Gas = uint64(*dec.Gas)
|
||||||
|
if dec.GasPrice == nil {
|
||||||
|
return errors.New("missing required field 'gasPrice' in transaction")
|
||||||
|
}
|
||||||
|
itx.GasPrice = (*big.Int)(dec.GasPrice)
|
||||||
if dec.Value == nil {
|
if dec.Value == nil {
|
||||||
return errors.New("missing required field 'value' in transaction")
|
return errors.New("missing required field 'value' in transaction")
|
||||||
}
|
}
|
||||||
itx.Value = (*big.Int)(dec.Value)
|
itx.Value = (*big.Int)(dec.Value)
|
||||||
if dec.Data == nil {
|
if dec.Input == nil {
|
||||||
return errors.New("missing required field 'input' in transaction")
|
return errors.New("missing required field 'input' in transaction")
|
||||||
}
|
}
|
||||||
itx.Data = *dec.Data
|
itx.Data = *dec.Input
|
||||||
if dec.V == nil {
|
if dec.AccessList != nil {
|
||||||
return errors.New("missing required field 'v' in transaction")
|
itx.AccessList = *dec.AccessList
|
||||||
}
|
}
|
||||||
itx.V = (*big.Int)(dec.V)
|
|
||||||
|
// signature R
|
||||||
if dec.R == nil {
|
if dec.R == nil {
|
||||||
return errors.New("missing required field 'r' in transaction")
|
return errors.New("missing required field 'r' in transaction")
|
||||||
}
|
}
|
||||||
itx.R = (*big.Int)(dec.R)
|
itx.R = (*big.Int)(dec.R)
|
||||||
|
// signature S
|
||||||
if dec.S == nil {
|
if dec.S == nil {
|
||||||
return errors.New("missing required field 's' in transaction")
|
return errors.New("missing required field 's' in transaction")
|
||||||
}
|
}
|
||||||
itx.S = (*big.Int)(dec.S)
|
itx.S = (*big.Int)(dec.S)
|
||||||
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
|
// signature V
|
||||||
if withSignature {
|
itx.V, err = dec.yParityValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
|
||||||
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -220,21 +267,21 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
case DynamicFeeTxType:
|
case DynamicFeeTxType:
|
||||||
var itx DynamicFeeTx
|
var itx DynamicFeeTx
|
||||||
inner = &itx
|
inner = &itx
|
||||||
// Access list is optional for now.
|
|
||||||
if dec.AccessList != nil {
|
|
||||||
itx.AccessList = *dec.AccessList
|
|
||||||
}
|
|
||||||
if dec.ChainID == nil {
|
if dec.ChainID == nil {
|
||||||
return errors.New("missing required field 'chainId' in transaction")
|
return errors.New("missing required field 'chainId' in transaction")
|
||||||
}
|
}
|
||||||
itx.ChainID = (*big.Int)(dec.ChainID)
|
itx.ChainID = (*big.Int)(dec.ChainID)
|
||||||
if dec.To != nil {
|
|
||||||
itx.To = dec.To
|
|
||||||
}
|
|
||||||
if dec.Nonce == nil {
|
if dec.Nonce == nil {
|
||||||
return errors.New("missing required field 'nonce' in transaction")
|
return errors.New("missing required field 'nonce' in transaction")
|
||||||
}
|
}
|
||||||
itx.Nonce = uint64(*dec.Nonce)
|
itx.Nonce = uint64(*dec.Nonce)
|
||||||
|
if dec.To != nil {
|
||||||
|
itx.To = dec.To
|
||||||
|
}
|
||||||
|
if dec.Gas == nil {
|
||||||
|
return errors.New("missing required field 'gas' for txdata")
|
||||||
|
}
|
||||||
|
itx.Gas = uint64(*dec.Gas)
|
||||||
if dec.MaxPriorityFeePerGas == nil {
|
if dec.MaxPriorityFeePerGas == nil {
|
||||||
return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
|
return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
|
||||||
}
|
}
|
||||||
|
|
@ -243,37 +290,118 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
return errors.New("missing required field 'maxFeePerGas' for txdata")
|
return errors.New("missing required field 'maxFeePerGas' for txdata")
|
||||||
}
|
}
|
||||||
itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas)
|
itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas)
|
||||||
if dec.Gas == nil {
|
|
||||||
return errors.New("missing required field 'gas' for txdata")
|
|
||||||
}
|
|
||||||
itx.Gas = uint64(*dec.Gas)
|
|
||||||
if dec.Value == nil {
|
if dec.Value == nil {
|
||||||
return errors.New("missing required field 'value' in transaction")
|
return errors.New("missing required field 'value' in transaction")
|
||||||
}
|
}
|
||||||
itx.Value = (*big.Int)(dec.Value)
|
itx.Value = (*big.Int)(dec.Value)
|
||||||
if dec.Data == nil {
|
if dec.Input == nil {
|
||||||
return errors.New("missing required field 'input' in transaction")
|
return errors.New("missing required field 'input' in transaction")
|
||||||
}
|
}
|
||||||
itx.Data = *dec.Data
|
itx.Data = *dec.Input
|
||||||
if dec.V == nil {
|
if dec.AccessList != nil {
|
||||||
return errors.New("missing required field 'v' in transaction")
|
itx.AccessList = *dec.AccessList
|
||||||
}
|
}
|
||||||
itx.V = (*big.Int)(dec.V)
|
|
||||||
|
// signature R
|
||||||
if dec.R == nil {
|
if dec.R == nil {
|
||||||
return errors.New("missing required field 'r' in transaction")
|
return errors.New("missing required field 'r' in transaction")
|
||||||
}
|
}
|
||||||
itx.R = (*big.Int)(dec.R)
|
itx.R = (*big.Int)(dec.R)
|
||||||
|
// signature S
|
||||||
if dec.S == nil {
|
if dec.S == nil {
|
||||||
return errors.New("missing required field 's' in transaction")
|
return errors.New("missing required field 's' in transaction")
|
||||||
}
|
}
|
||||||
itx.S = (*big.Int)(dec.S)
|
itx.S = (*big.Int)(dec.S)
|
||||||
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
|
// signature V
|
||||||
if withSignature {
|
itx.V, err = dec.yParityValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
|
||||||
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BlobTxType:
|
||||||
|
var itx BlobTx
|
||||||
|
inner = &itx
|
||||||
|
if dec.ChainID == nil {
|
||||||
|
return errors.New("missing required field 'chainId' in transaction")
|
||||||
|
}
|
||||||
|
itx.ChainID = uint256.MustFromBig((*big.Int)(dec.ChainID))
|
||||||
|
if dec.Nonce == nil {
|
||||||
|
return errors.New("missing required field 'nonce' in transaction")
|
||||||
|
}
|
||||||
|
itx.Nonce = uint64(*dec.Nonce)
|
||||||
|
if dec.To == nil {
|
||||||
|
return errors.New("missing required field 'to' in transaction")
|
||||||
|
}
|
||||||
|
itx.To = *dec.To
|
||||||
|
if dec.Gas == nil {
|
||||||
|
return errors.New("missing required field 'gas' for txdata")
|
||||||
|
}
|
||||||
|
itx.Gas = uint64(*dec.Gas)
|
||||||
|
if dec.MaxPriorityFeePerGas == nil {
|
||||||
|
return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
|
||||||
|
}
|
||||||
|
itx.GasTipCap = uint256.MustFromBig((*big.Int)(dec.MaxPriorityFeePerGas))
|
||||||
|
if dec.MaxFeePerGas == nil {
|
||||||
|
return errors.New("missing required field 'maxFeePerGas' for txdata")
|
||||||
|
}
|
||||||
|
itx.GasFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerGas))
|
||||||
|
if dec.MaxFeePerBlobGas == nil {
|
||||||
|
return errors.New("missing required field 'maxFeePerBlobGas' for txdata")
|
||||||
|
}
|
||||||
|
itx.BlobFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerBlobGas))
|
||||||
|
if dec.Value == nil {
|
||||||
|
return errors.New("missing required field 'value' in transaction")
|
||||||
|
}
|
||||||
|
itx.Value = uint256.MustFromBig((*big.Int)(dec.Value))
|
||||||
|
if dec.Input == nil {
|
||||||
|
return errors.New("missing required field 'input' in transaction")
|
||||||
|
}
|
||||||
|
itx.Data = *dec.Input
|
||||||
|
if dec.AccessList != nil {
|
||||||
|
itx.AccessList = *dec.AccessList
|
||||||
|
}
|
||||||
|
if dec.BlobVersionedHashes == nil {
|
||||||
|
return errors.New("missing required field 'blobVersionedHashes' in transaction")
|
||||||
|
}
|
||||||
|
itx.BlobHashes = dec.BlobVersionedHashes
|
||||||
|
|
||||||
|
// signature R
|
||||||
|
var overflow bool
|
||||||
|
if dec.R == nil {
|
||||||
|
return errors.New("missing required field 'r' in transaction")
|
||||||
|
}
|
||||||
|
itx.R, overflow = uint256.FromBig((*big.Int)(dec.R))
|
||||||
|
if overflow {
|
||||||
|
return errors.New("'r' value overflows uint256")
|
||||||
|
}
|
||||||
|
// signature S
|
||||||
|
if dec.S == nil {
|
||||||
|
return errors.New("missing required field 's' in transaction")
|
||||||
|
}
|
||||||
|
itx.S, overflow = uint256.FromBig((*big.Int)(dec.S))
|
||||||
|
if overflow {
|
||||||
|
return errors.New("'s' value overflows uint256")
|
||||||
|
}
|
||||||
|
// signature V
|
||||||
|
vbig, err := dec.yParityValue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
itx.V, overflow = uint256.FromBig(vbig)
|
||||||
|
if overflow {
|
||||||
|
return errors.New("'v' value overflows uint256")
|
||||||
|
}
|
||||||
|
if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
|
||||||
|
if err := sanityCheckSignature(vbig, itx.R.ToBig(), itx.S.ToBig(), false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case L1MessageTxType:
|
case L1MessageTxType:
|
||||||
var itx L1MessageTx
|
var itx L1MessageTx
|
||||||
inner = &itx
|
inner = &itx
|
||||||
|
|
@ -292,10 +420,10 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
return errors.New("missing required field 'value' in transaction")
|
return errors.New("missing required field 'value' in transaction")
|
||||||
}
|
}
|
||||||
itx.Value = (*big.Int)(dec.Value)
|
itx.Value = (*big.Int)(dec.Value)
|
||||||
if dec.Data == nil {
|
if dec.Input == nil {
|
||||||
return errors.New("missing required field 'input' in transaction")
|
return errors.New("missing required field 'input' in transaction")
|
||||||
}
|
}
|
||||||
itx.Data = *dec.Data
|
itx.Data = *dec.Input
|
||||||
itx.Sender = dec.Sender
|
itx.Sender = dec.Sender
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -303,7 +431,7 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now set the inner transaction.
|
// Now set the inner transaction.
|
||||||
t.setDecoded(inner, 0)
|
tx.setDecoded(inner, 0)
|
||||||
|
|
||||||
// TODO: check hash here?
|
// TODO: check hash here?
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
||||||
var signer Signer
|
var signer Signer
|
||||||
switch {
|
switch {
|
||||||
case config.IsLondon(blockNumber):
|
case config.IsLondon(blockNumber):
|
||||||
signer = NewLondonSigner(config.ChainID)
|
signer = NewLondonSignerWithEIP4844(config.ChainID)
|
||||||
case config.IsBerlin(blockNumber):
|
case config.IsBerlin(blockNumber):
|
||||||
signer = NewEIP2930Signer(config.ChainID)
|
signer = NewEIP2930Signer(config.ChainID)
|
||||||
case config.IsEIP155(blockNumber):
|
case config.IsEIP155(blockNumber):
|
||||||
|
|
@ -64,7 +64,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
|
||||||
func LatestSigner(config *params.ChainConfig) Signer {
|
func LatestSigner(config *params.ChainConfig) Signer {
|
||||||
if config.ChainID != nil {
|
if config.ChainID != nil {
|
||||||
if config.LondonBlock != nil {
|
if config.LondonBlock != nil {
|
||||||
return NewLondonSigner(config.ChainID)
|
return NewLondonSignerWithEIP4844(config.ChainID)
|
||||||
}
|
}
|
||||||
if config.BerlinBlock != nil {
|
if config.BerlinBlock != nil {
|
||||||
return NewEIP2930Signer(config.ChainID)
|
return NewEIP2930Signer(config.ChainID)
|
||||||
|
|
@ -87,7 +87,7 @@ func LatestSignerForChainID(chainID *big.Int) Signer {
|
||||||
if chainID == nil {
|
if chainID == nil {
|
||||||
return HomesteadSigner{}
|
return HomesteadSigner{}
|
||||||
}
|
}
|
||||||
return NewLondonSigner(chainID)
|
return NewLondonSignerWithEIP4844(chainID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignTx signs the transaction using the given signer and private key.
|
// SignTx signs the transaction using the given signer and private key.
|
||||||
|
|
@ -170,6 +170,75 @@ type Signer interface {
|
||||||
Equal(Signer) bool
|
Equal(Signer) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type londonSignerWithEIP4844 struct{ londonSigner }
|
||||||
|
|
||||||
|
// NewLondonSignerWithEIP4844 returns a signer that accepts
|
||||||
|
// - EIP-4844 blob transactions
|
||||||
|
// - EIP-1559 dynamic fee transactions
|
||||||
|
// - EIP-2930 access list transactions,
|
||||||
|
// - EIP-155 replay protected transactions, and
|
||||||
|
// - legacy Homestead transactions.
|
||||||
|
func NewLondonSignerWithEIP4844(chainId *big.Int) Signer {
|
||||||
|
return londonSignerWithEIP4844{londonSigner{eip2930Signer{NewEIP155Signer(chainId)}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s londonSignerWithEIP4844) Sender(tx *Transaction) (common.Address, error) {
|
||||||
|
if tx.Type() != BlobTxType {
|
||||||
|
return s.londonSigner.Sender(tx)
|
||||||
|
}
|
||||||
|
V, R, S := tx.RawSignatureValues()
|
||||||
|
// Blob txs are defined to use 0 and 1 as their recovery
|
||||||
|
// id, add 27 to become equivalent to unprotected Homestead signatures.
|
||||||
|
V = new(big.Int).Add(V, big.NewInt(27))
|
||||||
|
if tx.ChainId().Cmp(s.chainId) != 0 {
|
||||||
|
return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId)
|
||||||
|
}
|
||||||
|
return recoverPlain(s.Hash(tx), R, S, V, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s londonSignerWithEIP4844) Equal(s2 Signer) bool {
|
||||||
|
x, ok := s2.(londonSignerWithEIP4844)
|
||||||
|
return ok && x.chainId.Cmp(s.chainId) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s londonSignerWithEIP4844) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) {
|
||||||
|
txdata, ok := tx.inner.(*BlobTx)
|
||||||
|
if !ok {
|
||||||
|
return s.londonSigner.SignatureValues(tx, sig)
|
||||||
|
}
|
||||||
|
// Check that chain ID of tx matches the signer. We also accept ID zero here,
|
||||||
|
// because it indicates that the chain ID was not specified in the tx.
|
||||||
|
if txdata.ChainID.Sign() != 0 && txdata.ChainID.ToBig().Cmp(s.chainId) != 0 {
|
||||||
|
return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId)
|
||||||
|
}
|
||||||
|
R, S, _ = decodeSignature(sig)
|
||||||
|
V = big.NewInt(int64(sig[64]))
|
||||||
|
return R, S, V, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash returns the hash to be signed by the sender.
|
||||||
|
// It does not uniquely identify the transaction.
|
||||||
|
func (s londonSignerWithEIP4844) Hash(tx *Transaction) common.Hash {
|
||||||
|
if tx.Type() != BlobTxType {
|
||||||
|
return s.londonSigner.Hash(tx)
|
||||||
|
}
|
||||||
|
return prefixedRlpHash(
|
||||||
|
tx.Type(),
|
||||||
|
[]interface{}{
|
||||||
|
s.chainId,
|
||||||
|
tx.Nonce(),
|
||||||
|
tx.GasTipCap(),
|
||||||
|
tx.GasFeeCap(),
|
||||||
|
tx.Gas(),
|
||||||
|
tx.To(),
|
||||||
|
tx.Value(),
|
||||||
|
tx.Data(),
|
||||||
|
tx.AccessList(),
|
||||||
|
tx.BlobGasFeeCap(),
|
||||||
|
tx.BlobHashes(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type londonSigner struct{ eip2930Signer }
|
type londonSigner struct{ eip2930Signer }
|
||||||
|
|
||||||
// NewLondonSigner returns a signer that accepts
|
// NewLondonSigner returns a signer that accepts
|
||||||
|
|
|
||||||
129
crypto/kzg4844/kzg4844.go
Normal file
129
crypto/kzg4844/kzg4844.go
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
// Copyright 2023 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Package kzg4844 implements the KZG crypto for EIP-4844.
|
||||||
|
package kzg4844
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"errors"
|
||||||
|
"hash"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed trusted_setup.json
|
||||||
|
var content embed.FS
|
||||||
|
|
||||||
|
// Blob represents a 4844 data blob.
|
||||||
|
type Blob [131072]byte
|
||||||
|
|
||||||
|
// Commitment is a serialized commitment to a polynomial.
|
||||||
|
type Commitment [48]byte
|
||||||
|
|
||||||
|
// Proof is a serialized commitment to the quotient polynomial.
|
||||||
|
type Proof [48]byte
|
||||||
|
|
||||||
|
// Point is a BLS field element.
|
||||||
|
type Point [32]byte
|
||||||
|
|
||||||
|
// Claim is a claimed evaluation value in a specific point.
|
||||||
|
type Claim [32]byte
|
||||||
|
|
||||||
|
// useCKZG controls whether the cryptography should use the Go or C backend.
|
||||||
|
var useCKZG atomic.Bool
|
||||||
|
|
||||||
|
// UseCKZG can be called to switch the default Go implementation of KZG to the C
|
||||||
|
// library if fo some reason the user wishes to do so (e.g. consensus bug in one
|
||||||
|
// or the other).
|
||||||
|
func UseCKZG(use bool) error {
|
||||||
|
if use && !ckzgAvailable {
|
||||||
|
return errors.New("CKZG unavailable on your platform")
|
||||||
|
}
|
||||||
|
useCKZG.Store(use)
|
||||||
|
|
||||||
|
// Initializing the library can take 2-4 seconds - and can potentially crash
|
||||||
|
// on CKZG and non-ADX CPUs - so might as well do it now and don't wait until
|
||||||
|
// a crypto operation is actually needed live.
|
||||||
|
if use {
|
||||||
|
ckzgIniter.Do(ckzgInit)
|
||||||
|
} else {
|
||||||
|
gokzgIniter.Do(gokzgInit)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobToCommitment creates a small commitment out of a data blob.
|
||||||
|
func BlobToCommitment(blob Blob) (Commitment, error) {
|
||||||
|
if useCKZG.Load() {
|
||||||
|
return ckzgBlobToCommitment(blob)
|
||||||
|
}
|
||||||
|
return gokzgBlobToCommitment(blob)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComputeProof computes the KZG proof at the given point for the polynomial
|
||||||
|
// represented by the blob.
|
||||||
|
func ComputeProof(blob Blob, point Point) (Proof, Claim, error) {
|
||||||
|
if useCKZG.Load() {
|
||||||
|
return ckzgComputeProof(blob, point)
|
||||||
|
}
|
||||||
|
return gokzgComputeProof(blob, point)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyProof verifies the KZG proof that the polynomial represented by the blob
|
||||||
|
// evaluated at the given point is the claimed value.
|
||||||
|
func VerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error {
|
||||||
|
if useCKZG.Load() {
|
||||||
|
return ckzgVerifyProof(commitment, point, claim, proof)
|
||||||
|
}
|
||||||
|
return gokzgVerifyProof(commitment, point, claim, proof)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComputeBlobProof returns the KZG proof that is used to verify the blob against
|
||||||
|
// the commitment.
|
||||||
|
//
|
||||||
|
// This method does not verify that the commitment is correct with respect to blob.
|
||||||
|
func ComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
|
||||||
|
if useCKZG.Load() {
|
||||||
|
return ckzgComputeBlobProof(blob, commitment)
|
||||||
|
}
|
||||||
|
return gokzgComputeBlobProof(blob, commitment)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyBlobProof verifies that the blob data corresponds to the provided commitment.
|
||||||
|
func VerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
|
||||||
|
if useCKZG.Load() {
|
||||||
|
return ckzgVerifyBlobProof(blob, commitment, proof)
|
||||||
|
}
|
||||||
|
return gokzgVerifyBlobProof(blob, commitment, proof)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalcBlobHashV1 calculates the 'versioned blob hash' of a commitment.
|
||||||
|
// The given hasher must be a sha256 hash instance, otherwise the result will be invalid!
|
||||||
|
func CalcBlobHashV1(hasher hash.Hash, commit *Commitment) (vh [32]byte) {
|
||||||
|
if hasher.Size() != 32 {
|
||||||
|
panic("wrong hash size")
|
||||||
|
}
|
||||||
|
hasher.Reset()
|
||||||
|
hasher.Write(commit[:])
|
||||||
|
hasher.Sum(vh[:0])
|
||||||
|
vh[0] = 0x01 // version
|
||||||
|
return vh
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidVersionedHash checks that h is a structurally-valid versioned blob hash.
|
||||||
|
func IsValidVersionedHash(h []byte) bool {
|
||||||
|
return len(h) == 32 && h[0] == 0x01
|
||||||
|
}
|
||||||
127
crypto/kzg4844/kzg4844_ckzg_cgo.go
Normal file
127
crypto/kzg4844/kzg4844_ckzg_cgo.go
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
// Copyright 2023 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//go:build ckzg && !nacl && !js && cgo && !gofuzz
|
||||||
|
|
||||||
|
package kzg4844
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
|
||||||
|
ckzg4844 "github.com/ethereum/c-kzg-4844/bindings/go"
|
||||||
|
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ckzgAvailable signals whether the library was compiled into Geth.
|
||||||
|
const ckzgAvailable = true
|
||||||
|
|
||||||
|
// ckzgIniter ensures that we initialize the KZG library once before using it.
|
||||||
|
var ckzgIniter sync.Once
|
||||||
|
|
||||||
|
// ckzgInit initializes the KZG library with the provided trusted setup.
|
||||||
|
func ckzgInit() {
|
||||||
|
config, err := content.ReadFile("trusted_setup.json")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
params := new(gokzg4844.JSONTrustedSetup)
|
||||||
|
if err = json.Unmarshal(config, params); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err = gokzg4844.CheckTrustedSetupIsWellFormed(params); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
g1s := make([]byte, len(params.SetupG1Lagrange)*(len(params.SetupG1Lagrange[0])-2)/2)
|
||||||
|
for i, g1 := range params.SetupG1Lagrange {
|
||||||
|
copy(g1s[i*(len(g1)-2)/2:], hexutil.MustDecode(g1))
|
||||||
|
}
|
||||||
|
g2s := make([]byte, len(params.SetupG2)*(len(params.SetupG2[0])-2)/2)
|
||||||
|
for i, g2 := range params.SetupG2 {
|
||||||
|
copy(g2s[i*(len(g2)-2)/2:], hexutil.MustDecode(g2))
|
||||||
|
}
|
||||||
|
if err = ckzg4844.LoadTrustedSetup(g1s, g2s); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgBlobToCommitment creates a small commitment out of a data blob.
|
||||||
|
func ckzgBlobToCommitment(blob Blob) (Commitment, error) {
|
||||||
|
ckzgIniter.Do(ckzgInit)
|
||||||
|
|
||||||
|
commitment, err := ckzg4844.BlobToKZGCommitment((ckzg4844.Blob)(blob))
|
||||||
|
if err != nil {
|
||||||
|
return Commitment{}, err
|
||||||
|
}
|
||||||
|
return (Commitment)(commitment), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgComputeProof computes the KZG proof at the given point for the polynomial
|
||||||
|
// represented by the blob.
|
||||||
|
func ckzgComputeProof(blob Blob, point Point) (Proof, Claim, error) {
|
||||||
|
ckzgIniter.Do(ckzgInit)
|
||||||
|
|
||||||
|
proof, claim, err := ckzg4844.ComputeKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes32)(point))
|
||||||
|
if err != nil {
|
||||||
|
return Proof{}, Claim{}, err
|
||||||
|
}
|
||||||
|
return (Proof)(proof), (Claim)(claim), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgVerifyProof verifies the KZG proof that the polynomial represented by the blob
|
||||||
|
// evaluated at the given point is the claimed value.
|
||||||
|
func ckzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error {
|
||||||
|
ckzgIniter.Do(ckzgInit)
|
||||||
|
|
||||||
|
valid, err := ckzg4844.VerifyKZGProof((ckzg4844.Bytes48)(commitment), (ckzg4844.Bytes32)(point), (ckzg4844.Bytes32)(claim), (ckzg4844.Bytes48)(proof))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !valid {
|
||||||
|
return errors.New("invalid proof")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgComputeBlobProof returns the KZG proof that is used to verify the blob against
|
||||||
|
// the commitment.
|
||||||
|
//
|
||||||
|
// This method does not verify that the commitment is correct with respect to blob.
|
||||||
|
func ckzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
|
||||||
|
ckzgIniter.Do(ckzgInit)
|
||||||
|
|
||||||
|
proof, err := ckzg4844.ComputeBlobKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment))
|
||||||
|
if err != nil {
|
||||||
|
return Proof{}, err
|
||||||
|
}
|
||||||
|
return (Proof)(proof), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment.
|
||||||
|
func ckzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
|
||||||
|
ckzgIniter.Do(ckzgInit)
|
||||||
|
|
||||||
|
valid, err := ckzg4844.VerifyBlobKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment), (ckzg4844.Bytes48)(proof))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !valid {
|
||||||
|
return errors.New("invalid proof")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
62
crypto/kzg4844/kzg4844_ckzg_nocgo.go
Normal file
62
crypto/kzg4844/kzg4844_ckzg_nocgo.go
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright 2023 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//go:build !ckzg || nacl || js || !cgo || gofuzz
|
||||||
|
|
||||||
|
package kzg4844
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
// ckzgAvailable signals whether the library was compiled into Geth.
|
||||||
|
const ckzgAvailable = false
|
||||||
|
|
||||||
|
// ckzgIniter ensures that we initialize the KZG library once before using it.
|
||||||
|
var ckzgIniter sync.Once
|
||||||
|
|
||||||
|
// ckzgInit initializes the KZG library with the provided trusted setup.
|
||||||
|
func ckzgInit() {
|
||||||
|
panic("unsupported platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgBlobToCommitment creates a small commitment out of a data blob.
|
||||||
|
func ckzgBlobToCommitment(blob Blob) (Commitment, error) {
|
||||||
|
panic("unsupported platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgComputeProof computes the KZG proof at the given point for the polynomial
|
||||||
|
// represented by the blob.
|
||||||
|
func ckzgComputeProof(blob Blob, point Point) (Proof, Claim, error) {
|
||||||
|
panic("unsupported platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgVerifyProof verifies the KZG proof that the polynomial represented by the blob
|
||||||
|
// evaluated at the given point is the claimed value.
|
||||||
|
func ckzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error {
|
||||||
|
panic("unsupported platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgComputeBlobProof returns the KZG proof that is used to verify the blob against
|
||||||
|
// the commitment.
|
||||||
|
//
|
||||||
|
// This method does not verify that the commitment is correct with respect to blob.
|
||||||
|
func ckzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
|
||||||
|
panic("unsupported platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ckzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment.
|
||||||
|
func ckzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
|
||||||
|
panic("unsupported platform")
|
||||||
|
}
|
||||||
98
crypto/kzg4844/kzg4844_gokzg.go
Normal file
98
crypto/kzg4844/kzg4844_gokzg.go
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright 2023 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package kzg4844
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
|
||||||
|
)
|
||||||
|
|
||||||
|
// context is the crypto primitive pre-seeded with the trusted setup parameters.
|
||||||
|
var context *gokzg4844.Context
|
||||||
|
|
||||||
|
// gokzgIniter ensures that we initialize the KZG library once before using it.
|
||||||
|
var gokzgIniter sync.Once
|
||||||
|
|
||||||
|
// gokzgInit initializes the KZG library with the provided trusted setup.
|
||||||
|
func gokzgInit() {
|
||||||
|
config, err := content.ReadFile("trusted_setup.json")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
params := new(gokzg4844.JSONTrustedSetup)
|
||||||
|
if err = json.Unmarshal(config, params); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
context, err = gokzg4844.NewContext4096(params)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// gokzgBlobToCommitment creates a small commitment out of a data blob.
|
||||||
|
func gokzgBlobToCommitment(blob Blob) (Commitment, error) {
|
||||||
|
gokzgIniter.Do(gokzgInit)
|
||||||
|
|
||||||
|
commitment, err := context.BlobToKZGCommitment((gokzg4844.Blob)(blob), 0)
|
||||||
|
if err != nil {
|
||||||
|
return Commitment{}, err
|
||||||
|
}
|
||||||
|
return (Commitment)(commitment), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// gokzgComputeProof computes the KZG proof at the given point for the polynomial
|
||||||
|
// represented by the blob.
|
||||||
|
func gokzgComputeProof(blob Blob, point Point) (Proof, Claim, error) {
|
||||||
|
gokzgIniter.Do(gokzgInit)
|
||||||
|
|
||||||
|
proof, claim, err := context.ComputeKZGProof((gokzg4844.Blob)(blob), (gokzg4844.Scalar)(point), 0)
|
||||||
|
if err != nil {
|
||||||
|
return Proof{}, Claim{}, err
|
||||||
|
}
|
||||||
|
return (Proof)(proof), (Claim)(claim), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// gokzgVerifyProof verifies the KZG proof that the polynomial represented by the blob
|
||||||
|
// evaluated at the given point is the claimed value.
|
||||||
|
func gokzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error {
|
||||||
|
gokzgIniter.Do(gokzgInit)
|
||||||
|
|
||||||
|
return context.VerifyKZGProof((gokzg4844.KZGCommitment)(commitment), (gokzg4844.Scalar)(point), (gokzg4844.Scalar)(claim), (gokzg4844.KZGProof)(proof))
|
||||||
|
}
|
||||||
|
|
||||||
|
// gokzgComputeBlobProof returns the KZG proof that is used to verify the blob against
|
||||||
|
// the commitment.
|
||||||
|
//
|
||||||
|
// This method does not verify that the commitment is correct with respect to blob.
|
||||||
|
func gokzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
|
||||||
|
gokzgIniter.Do(gokzgInit)
|
||||||
|
|
||||||
|
proof, err := context.ComputeBlobKZGProof((gokzg4844.Blob)(blob), (gokzg4844.KZGCommitment)(commitment), 0)
|
||||||
|
if err != nil {
|
||||||
|
return Proof{}, err
|
||||||
|
}
|
||||||
|
return (Proof)(proof), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// gokzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment.
|
||||||
|
func gokzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
|
||||||
|
gokzgIniter.Do(gokzgInit)
|
||||||
|
|
||||||
|
return context.VerifyBlobKZGProof((gokzg4844.Blob)(blob), (gokzg4844.KZGCommitment)(commitment), (gokzg4844.KZGProof)(proof))
|
||||||
|
}
|
||||||
195
crypto/kzg4844/kzg4844_test.go
Normal file
195
crypto/kzg4844/kzg4844_test.go
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
// Copyright 2023 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package kzg4844
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
|
||||||
|
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
|
||||||
|
)
|
||||||
|
|
||||||
|
func randFieldElement() [32]byte {
|
||||||
|
bytes := make([]byte, 32)
|
||||||
|
_, err := rand.Read(bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to get random field element")
|
||||||
|
}
|
||||||
|
var r fr.Element
|
||||||
|
r.SetBytes(bytes)
|
||||||
|
|
||||||
|
return gokzg4844.SerializeScalar(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func randBlob() Blob {
|
||||||
|
var blob Blob
|
||||||
|
for i := 0; i < len(blob); i += gokzg4844.SerializedScalarSize {
|
||||||
|
fieldElementBytes := randFieldElement()
|
||||||
|
copy(blob[i:i+gokzg4844.SerializedScalarSize], fieldElementBytes[:])
|
||||||
|
}
|
||||||
|
return blob
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCKZGWithPoint(t *testing.T) { testKZGWithPoint(t, true) }
|
||||||
|
func TestGoKZGWithPoint(t *testing.T) { testKZGWithPoint(t, false) }
|
||||||
|
func testKZGWithPoint(t *testing.T, ckzg bool) {
|
||||||
|
if ckzg && !ckzgAvailable {
|
||||||
|
t.Skip("CKZG unavailable in this test build")
|
||||||
|
}
|
||||||
|
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
|
||||||
|
useCKZG.Store(ckzg)
|
||||||
|
|
||||||
|
blob := randBlob()
|
||||||
|
|
||||||
|
commitment, err := BlobToCommitment(blob)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create KZG commitment from blob: %v", err)
|
||||||
|
}
|
||||||
|
point := randFieldElement()
|
||||||
|
proof, claim, err := ComputeProof(blob, point)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create KZG proof at point: %v", err)
|
||||||
|
}
|
||||||
|
if err := VerifyProof(commitment, point, claim, proof); err != nil {
|
||||||
|
t.Fatalf("failed to verify KZG proof at point: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCKZGWithBlob(t *testing.T) { testKZGWithBlob(t, true) }
|
||||||
|
func TestGoKZGWithBlob(t *testing.T) { testKZGWithBlob(t, false) }
|
||||||
|
func testKZGWithBlob(t *testing.T, ckzg bool) {
|
||||||
|
if ckzg && !ckzgAvailable {
|
||||||
|
t.Skip("CKZG unavailable in this test build")
|
||||||
|
}
|
||||||
|
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
|
||||||
|
useCKZG.Store(ckzg)
|
||||||
|
|
||||||
|
blob := randBlob()
|
||||||
|
|
||||||
|
commitment, err := BlobToCommitment(blob)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create KZG commitment from blob: %v", err)
|
||||||
|
}
|
||||||
|
proof, err := ComputeBlobProof(blob, commitment)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create KZG proof for blob: %v", err)
|
||||||
|
}
|
||||||
|
if err := VerifyBlobProof(blob, commitment, proof); err != nil {
|
||||||
|
t.Fatalf("failed to verify KZG proof for blob: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCKZGBlobToCommitment(b *testing.B) { benchmarkBlobToCommitment(b, true) }
|
||||||
|
func BenchmarkGoKZGBlobToCommitment(b *testing.B) { benchmarkBlobToCommitment(b, false) }
|
||||||
|
func benchmarkBlobToCommitment(b *testing.B, ckzg bool) {
|
||||||
|
if ckzg && !ckzgAvailable {
|
||||||
|
b.Skip("CKZG unavailable in this test build")
|
||||||
|
}
|
||||||
|
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
|
||||||
|
useCKZG.Store(ckzg)
|
||||||
|
|
||||||
|
blob := randBlob()
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
BlobToCommitment(blob)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCKZGComputeProof(b *testing.B) { benchmarkComputeProof(b, true) }
|
||||||
|
func BenchmarkGoKZGComputeProof(b *testing.B) { benchmarkComputeProof(b, false) }
|
||||||
|
func benchmarkComputeProof(b *testing.B, ckzg bool) {
|
||||||
|
if ckzg && !ckzgAvailable {
|
||||||
|
b.Skip("CKZG unavailable in this test build")
|
||||||
|
}
|
||||||
|
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
|
||||||
|
useCKZG.Store(ckzg)
|
||||||
|
|
||||||
|
var (
|
||||||
|
blob = randBlob()
|
||||||
|
point = randFieldElement()
|
||||||
|
)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
ComputeProof(blob, point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCKZGVerifyProof(b *testing.B) { benchmarkVerifyProof(b, true) }
|
||||||
|
func BenchmarkGoKZGVerifyProof(b *testing.B) { benchmarkVerifyProof(b, false) }
|
||||||
|
func benchmarkVerifyProof(b *testing.B, ckzg bool) {
|
||||||
|
if ckzg && !ckzgAvailable {
|
||||||
|
b.Skip("CKZG unavailable in this test build")
|
||||||
|
}
|
||||||
|
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
|
||||||
|
useCKZG.Store(ckzg)
|
||||||
|
|
||||||
|
var (
|
||||||
|
blob = randBlob()
|
||||||
|
point = randFieldElement()
|
||||||
|
commitment, _ = BlobToCommitment(blob)
|
||||||
|
proof, claim, _ = ComputeProof(blob, point)
|
||||||
|
)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
VerifyProof(commitment, point, claim, proof)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCKZGComputeBlobProof(b *testing.B) { benchmarkComputeBlobProof(b, true) }
|
||||||
|
func BenchmarkGoKZGComputeBlobProof(b *testing.B) { benchmarkComputeBlobProof(b, false) }
|
||||||
|
func benchmarkComputeBlobProof(b *testing.B, ckzg bool) {
|
||||||
|
if ckzg && !ckzgAvailable {
|
||||||
|
b.Skip("CKZG unavailable in this test build")
|
||||||
|
}
|
||||||
|
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
|
||||||
|
useCKZG.Store(ckzg)
|
||||||
|
|
||||||
|
var (
|
||||||
|
blob = randBlob()
|
||||||
|
commitment, _ = BlobToCommitment(blob)
|
||||||
|
)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
ComputeBlobProof(blob, commitment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCKZGVerifyBlobProof(b *testing.B) { benchmarkVerifyBlobProof(b, true) }
|
||||||
|
func BenchmarkGoKZGVerifyBlobProof(b *testing.B) { benchmarkVerifyBlobProof(b, false) }
|
||||||
|
func benchmarkVerifyBlobProof(b *testing.B, ckzg bool) {
|
||||||
|
if ckzg && !ckzgAvailable {
|
||||||
|
b.Skip("CKZG unavailable in this test build")
|
||||||
|
}
|
||||||
|
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
|
||||||
|
useCKZG.Store(ckzg)
|
||||||
|
|
||||||
|
var (
|
||||||
|
blob = randBlob()
|
||||||
|
commitment, _ = BlobToCommitment(blob)
|
||||||
|
proof, _ = ComputeBlobProof(blob, commitment)
|
||||||
|
)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
VerifyBlobProof(blob, commitment, proof)
|
||||||
|
}
|
||||||
|
}
|
||||||
4167
crypto/kzg4844/trusted_setup.json
Normal file
4167
crypto/kzg4844/trusted_setup.json
Normal file
File diff suppressed because it is too large
Load diff
11
go.mod
11
go.mod
|
|
@ -12,12 +12,14 @@ require (
|
||||||
github.com/btcsuite/btcd v0.20.1-beta
|
github.com/btcsuite/btcd v0.20.1-beta
|
||||||
github.com/cespare/cp v0.1.0
|
github.com/cespare/cp v0.1.0
|
||||||
github.com/cloudflare/cloudflare-go v0.14.0
|
github.com/cloudflare/cloudflare-go v0.14.0
|
||||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f
|
github.com/consensys/gnark-crypto v0.10.0
|
||||||
|
github.com/crate-crypto/go-kzg-4844 v0.7.0
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
|
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
|
||||||
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf
|
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf
|
||||||
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48
|
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48
|
||||||
github.com/edsrzf/mmap-go v1.0.0
|
github.com/edsrzf/mmap-go v1.0.0
|
||||||
|
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4
|
||||||
github.com/fatih/color v1.7.0
|
github.com/fatih/color v1.7.0
|
||||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
|
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
|
||||||
|
|
@ -31,7 +33,7 @@ require (
|
||||||
github.com/hashicorp/go-bexpr v0.1.10
|
github.com/hashicorp/go-bexpr v0.1.10
|
||||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
|
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
|
||||||
github.com/holiman/bloomfilter/v2 v2.0.3
|
github.com/holiman/bloomfilter/v2 v2.0.3
|
||||||
github.com/holiman/uint256 v1.2.0
|
github.com/holiman/uint256 v1.2.4
|
||||||
github.com/huin/goupnp v1.0.2
|
github.com/huin/goupnp v1.0.2
|
||||||
github.com/iden3/go-iden3-crypto v0.0.12
|
github.com/iden3/go-iden3-crypto v0.0.12
|
||||||
github.com/influxdata/influxdb v1.8.3
|
github.com/influxdata/influxdb v1.8.3
|
||||||
|
|
@ -73,7 +75,9 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
|
||||||
github.com/aws/smithy-go v1.1.0 // indirect
|
github.com/aws/smithy-go v1.1.0 // indirect
|
||||||
|
github.com/bits-and-blooms/bitset v1.5.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||||
|
github.com/consensys/bavard v0.1.13 // indirect
|
||||||
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
|
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.1 // indirect
|
github.com/go-ole/go-ole v1.2.1 // indirect
|
||||||
|
|
@ -85,10 +89,12 @@ require (
|
||||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||||
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
||||||
|
github.com/mmcloughlin/addchain v0.4.0 // indirect
|
||||||
github.com/naoina/go-stringutil v0.1.0 // indirect
|
github.com/naoina/go-stringutil v0.1.0 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.1.0 // indirect
|
github.com/opentracing/opentracing-go v1.1.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||||
golang.org/x/net v0.16.0 // indirect
|
golang.org/x/net v0.16.0 // indirect
|
||||||
|
|
@ -97,4 +103,5 @@ require (
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gotest.tools v1.4.0 // indirect
|
gotest.tools v1.4.0 // indirect
|
||||||
|
rsc.io/tmplfunc v0.0.3 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
36
go.sum
36
go.sum
|
|
@ -70,6 +70,8 @@ github.com/aws/smithy-go v1.1.0 h1:D6CSsM3gdxaGaqXnPgOBCeL6Mophqzu7KJOu7zW78sU=
|
||||||
github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
|
github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD6ZIpQT8=
|
||||||
|
github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||||
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
||||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||||
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
|
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
|
||||||
|
|
@ -94,10 +96,13 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA=
|
github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA=
|
||||||
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
|
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
|
||||||
github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
|
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
|
||||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f h1:C43yEtQ6NIf4ftFXD/V55gnGFgPbMQobd//YlnLjUJ8=
|
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
|
||||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
|
github.com/consensys/gnark-crypto v0.10.0 h1:zRh22SR7o4K35SoNqouS9J/TKHTyU2QWaj5ldehyXtA=
|
||||||
|
github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA=
|
||||||
|
github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||||
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
||||||
|
|
@ -126,6 +131,8 @@ github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
|
||||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 h1:B2mpK+MNqgPqk2/KNi1LbqwtZDy5F7iy0mynQiBr8VA=
|
||||||
|
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4/go.mod h1:y4GA2JbAUama1S4QwYjC2hefgGLU8Ul0GMtL/ADMF1c=
|
||||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
|
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
|
||||||
|
|
@ -204,6 +211,7 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||||
github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I=
|
github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I=
|
||||||
github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
|
@ -224,8 +232,8 @@ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuW
|
||||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
|
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
|
||||||
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
|
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
|
||||||
github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
|
github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=
|
||||||
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
|
github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI=
|
github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI=
|
||||||
github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM=
|
github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM=
|
||||||
|
|
@ -317,6 +325,9 @@ github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxd
|
||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
|
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
|
||||||
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
|
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
|
||||||
|
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
|
||||||
|
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
|
||||||
|
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
||||||
|
|
@ -406,6 +417,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2 h1:wh1wzwAhZBNiZO37uWS/nDaKiIwHz4mDo4pnA+fqTO0=
|
||||||
|
github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||||
|
|
@ -421,7 +434,6 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
|
@ -439,7 +451,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
|
|
@ -471,8 +482,6 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
|
@ -492,7 +501,6 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
|
@ -513,7 +521,6 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
|
|
@ -545,12 +552,9 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
@ -608,7 +612,6 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn
|
||||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
@ -692,6 +695,7 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
|
||||||
|
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,8 @@ const (
|
||||||
// up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529
|
// up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529
|
||||||
RefundQuotient uint64 = 2
|
RefundQuotient uint64 = 2
|
||||||
RefundQuotientEIP3529 uint64 = 5
|
RefundQuotientEIP3529 uint64 = 5
|
||||||
|
|
||||||
|
BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations
|
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import (
|
||||||
const (
|
const (
|
||||||
VersionMajor = 5 // Major version component of the current release
|
VersionMajor = 5 // Major version component of the current release
|
||||||
VersionMinor = 1 // Minor version component of the current release
|
VersionMinor = 1 // Minor version component of the current release
|
||||||
VersionPatch = 14 // Patch version component of the current release
|
VersionPatch = 15 // Patch version component of the current release
|
||||||
VersionMeta = "mainnet" // Version metadata to append to the version string
|
VersionMeta = "mainnet" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
16
rlp/raw.go
16
rlp/raw.go
|
|
@ -42,6 +42,22 @@ func IntSize(x uint64) int {
|
||||||
return 1 + intsize(x)
|
return 1 + intsize(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BytesSize returns the encoded size of a byte slice.
|
||||||
|
func BytesSize(b []byte) uint64 {
|
||||||
|
switch {
|
||||||
|
case len(b) == 0:
|
||||||
|
return 1
|
||||||
|
case len(b) == 1:
|
||||||
|
if b[0] <= 0x7f {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return uint64(headsize(uint64(len(b))) + len(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Split returns the content of first RLP value and any
|
// Split returns the content of first RLP value and any
|
||||||
// bytes after the value as subslices of b.
|
// bytes after the value as subslices of b.
|
||||||
func Split(b []byte) (k Kind, content, rest []byte, err error) {
|
func Split(b []byte) (k Kind, content, rest []byte, err error) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue