|
|
|
@ -20,6 +20,7 @@ import ( |
|
|
|
|
"crypto/sha256" |
|
|
|
|
"encoding/binary" |
|
|
|
|
"errors" |
|
|
|
|
"fmt" |
|
|
|
|
"math/big" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
@ -28,6 +29,7 @@ import ( |
|
|
|
|
"github.com/ethereum/go-ethereum/crypto/blake2b" |
|
|
|
|
"github.com/ethereum/go-ethereum/crypto/bls12381" |
|
|
|
|
"github.com/ethereum/go-ethereum/crypto/bn256" |
|
|
|
|
"github.com/ethereum/go-ethereum/crypto/kzg4844" |
|
|
|
|
"github.com/ethereum/go-ethereum/params" |
|
|
|
|
"golang.org/x/crypto/ripemd160" |
|
|
|
|
) |
|
|
|
@ -90,6 +92,21 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{ |
|
|
|
|
common.BytesToAddress([]byte{9}): &blake2F{}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// PrecompiledContractsCancun contains the default set of pre-compiled Ethereum
|
|
|
|
|
// contracts used in the Cancun release.
|
|
|
|
|
var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{ |
|
|
|
|
common.BytesToAddress([]byte{1}): &ecrecover{}, |
|
|
|
|
common.BytesToAddress([]byte{2}): &sha256hash{}, |
|
|
|
|
common.BytesToAddress([]byte{3}): &ripemd160hash{}, |
|
|
|
|
common.BytesToAddress([]byte{4}): &dataCopy{}, |
|
|
|
|
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, |
|
|
|
|
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, |
|
|
|
|
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, |
|
|
|
|
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, |
|
|
|
|
common.BytesToAddress([]byte{9}): &blake2F{}, |
|
|
|
|
common.BytesToAddress([]byte{20}): &kzgPointEvaluation{}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
|
|
|
|
|
// contracts specified in EIP-2537. These are exported for testing purposes.
|
|
|
|
|
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ |
|
|
|
@ -105,6 +122,7 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
PrecompiledAddressesCancun []common.Address |
|
|
|
|
PrecompiledAddressesBerlin []common.Address |
|
|
|
|
PrecompiledAddressesIstanbul []common.Address |
|
|
|
|
PrecompiledAddressesByzantium []common.Address |
|
|
|
@ -124,11 +142,16 @@ func init() { |
|
|
|
|
for k := range PrecompiledContractsBerlin { |
|
|
|
|
PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) |
|
|
|
|
} |
|
|
|
|
for k := range PrecompiledContractsCancun { |
|
|
|
|
PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ActivePrecompiles returns the precompiles enabled with the current configuration.
|
|
|
|
|
func ActivePrecompiles(rules params.Rules) []common.Address { |
|
|
|
|
switch { |
|
|
|
|
case rules.IsCancun: |
|
|
|
|
return PrecompiledAddressesCancun |
|
|
|
|
case rules.IsBerlin: |
|
|
|
|
return PrecompiledAddressesBerlin |
|
|
|
|
case rules.IsIstanbul: |
|
|
|
@ -1048,3 +1071,67 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) { |
|
|
|
|
// Encode the G2 point to 256 bytes
|
|
|
|
|
return g.EncodePoint(r), nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// kzgPointEvaluation implements the EIP-4844 point evaluation precompile.
|
|
|
|
|
type kzgPointEvaluation struct{} |
|
|
|
|
|
|
|
|
|
// RequiredGas estimates the gas required for running the point evaluation precompile.
|
|
|
|
|
func (b *kzgPointEvaluation) RequiredGas(input []byte) uint64 { |
|
|
|
|
return params.BlobTxPointEvaluationPrecompileGas |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
|
blobVerifyInputLength = 192 // Max input length for the point evaluation precompile.
|
|
|
|
|
blobCommitmentVersionKZG uint8 = 0x01 // Version byte for the point evaluation precompile.
|
|
|
|
|
blobPrecompileReturnValue = "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
errBlobVerifyInvalidInputLength = errors.New("invalid input length") |
|
|
|
|
errBlobVerifyMismatchedVersion = errors.New("mismatched versioned hash") |
|
|
|
|
errBlobVerifyKZGProof = errors.New("error verifying kzg proof") |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Run executes the point evaluation precompile.
|
|
|
|
|
func (b *kzgPointEvaluation) Run(input []byte) ([]byte, error) { |
|
|
|
|
if len(input) != blobVerifyInputLength { |
|
|
|
|
return nil, errBlobVerifyInvalidInputLength |
|
|
|
|
} |
|
|
|
|
// versioned hash: first 32 bytes
|
|
|
|
|
var versionedHash common.Hash |
|
|
|
|
copy(versionedHash[:], input[:]) |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
point kzg4844.Point |
|
|
|
|
claim kzg4844.Claim |
|
|
|
|
) |
|
|
|
|
// Evaluation point: next 32 bytes
|
|
|
|
|
copy(point[:], input[32:]) |
|
|
|
|
// Expected output: next 32 bytes
|
|
|
|
|
copy(claim[:], input[64:]) |
|
|
|
|
|
|
|
|
|
// input kzg point: next 48 bytes
|
|
|
|
|
var commitment kzg4844.Commitment |
|
|
|
|
copy(commitment[:], input[96:]) |
|
|
|
|
if kZGToVersionedHash(commitment) != versionedHash { |
|
|
|
|
return nil, errBlobVerifyMismatchedVersion |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Proof: next 48 bytes
|
|
|
|
|
var proof kzg4844.Proof |
|
|
|
|
copy(proof[:], input[144:]) |
|
|
|
|
|
|
|
|
|
if err := kzg4844.VerifyProof(commitment, point, claim, proof); err != nil { |
|
|
|
|
return nil, fmt.Errorf("%w: %v", errBlobVerifyKZGProof, err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return common.Hex2Bytes(blobPrecompileReturnValue), nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// kZGToVersionedHash implements kzg_to_versioned_hash from EIP-4844
|
|
|
|
|
func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash { |
|
|
|
|
h := sha256.Sum256(kzg[:]) |
|
|
|
|
h[0] = blobCommitmentVersionKZG |
|
|
|
|
|
|
|
|
|
return h |
|
|
|
|
} |
|
|
|
|