@@ -20,6 +20,7 @@ import (
2020 "crypto/sha256"
2121 "encoding/binary"
2222 "errors"
23+ "fmt"
2324 "math/big"
2425
2526 "github.com/ethereum/go-ethereum/common"
@@ -28,6 +29,7 @@ import (
2829 "github.com/ethereum/go-ethereum/crypto/blake2b"
2930 "github.com/ethereum/go-ethereum/crypto/bls12381"
3031 "github.com/ethereum/go-ethereum/crypto/bn256"
32+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
3133 "github.com/ethereum/go-ethereum/params"
3234 "golang.org/x/crypto/ripemd160"
3335)
@@ -90,6 +92,21 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
9092 common .BytesToAddress ([]byte {9 }): & blake2F {},
9193}
9294
95+ // PrecompiledContractsCancun contains the default set of pre-compiled Ethereum
96+ // contracts used in the Cancun release.
97+ var PrecompiledContractsCancun = map [common.Address ]PrecompiledContract {
98+ common .BytesToAddress ([]byte {1 }): & ecrecover {},
99+ common .BytesToAddress ([]byte {2 }): & sha256hash {},
100+ common .BytesToAddress ([]byte {3 }): & ripemd160hash {},
101+ common .BytesToAddress ([]byte {4 }): & dataCopy {},
102+ common .BytesToAddress ([]byte {5 }): & bigModExp {eip2565 : true },
103+ common .BytesToAddress ([]byte {6 }): & bn256AddIstanbul {},
104+ common .BytesToAddress ([]byte {7 }): & bn256ScalarMulIstanbul {},
105+ common .BytesToAddress ([]byte {8 }): & bn256PairingIstanbul {},
106+ common .BytesToAddress ([]byte {9 }): & blake2F {},
107+ common .BytesToAddress ([]byte {20 }): & kzgPointEvaluation {},
108+ }
109+
93110// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
94111// contracts specified in EIP-2537. These are exported for testing purposes.
95112var PrecompiledContractsBLS = map [common.Address ]PrecompiledContract {
@@ -105,6 +122,7 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
105122}
106123
107124var (
125+ PrecompiledAddressesCancun []common.Address
108126 PrecompiledAddressesBerlin []common.Address
109127 PrecompiledAddressesIstanbul []common.Address
110128 PrecompiledAddressesByzantium []common.Address
@@ -124,11 +142,16 @@ func init() {
124142 for k := range PrecompiledContractsBerlin {
125143 PrecompiledAddressesBerlin = append (PrecompiledAddressesBerlin , k )
126144 }
145+ for k := range PrecompiledContractsCancun {
146+ PrecompiledAddressesCancun = append (PrecompiledAddressesCancun , k )
147+ }
127148}
128149
129150// ActivePrecompiles returns the precompiles enabled with the current configuration.
130151func ActivePrecompiles (rules params.Rules ) []common.Address {
131152 switch {
153+ case rules .IsCancun :
154+ return PrecompiledAddressesCancun
132155 case rules .IsBerlin :
133156 return PrecompiledAddressesBerlin
134157 case rules .IsIstanbul :
@@ -1048,3 +1071,67 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) {
10481071 // Encode the G2 point to 256 bytes
10491072 return g .EncodePoint (r ), nil
10501073}
1074+
1075+ // kzgPointEvaluation implements the EIP-4844 point evaluation precompile.
1076+ type kzgPointEvaluation struct {}
1077+
1078+ // RequiredGas estimates the gas required for running the point evaluation precompile.
1079+ func (b * kzgPointEvaluation ) RequiredGas (input []byte ) uint64 {
1080+ return params .BlobTxPointEvaluationPrecompileGas
1081+ }
1082+
1083+ const (
1084+ blobVerifyInputLength = 192 // Max input length for the point evaluation precompile.
1085+ blobCommitmentVersionKZG uint8 = 0x01 // Version byte for the point evaluation precompile.
1086+ blobPrecompileReturnValue = "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"
1087+ )
1088+
1089+ var (
1090+ errBlobVerifyInvalidInputLength = errors .New ("invalid input length" )
1091+ errBlobVerifyMismatchedVersion = errors .New ("mismatched versioned hash" )
1092+ errBlobVerifyKZGProof = errors .New ("error verifying kzg proof" )
1093+ )
1094+
1095+ // Run executes the point evaluation precompile.
1096+ func (b * kzgPointEvaluation ) Run (input []byte ) ([]byte , error ) {
1097+ if len (input ) != blobVerifyInputLength {
1098+ return nil , errBlobVerifyInvalidInputLength
1099+ }
1100+ // versioned hash: first 32 bytes
1101+ var versionedHash common.Hash
1102+ copy (versionedHash [:], input [:])
1103+
1104+ var (
1105+ point kzg4844.Point
1106+ claim kzg4844.Claim
1107+ )
1108+ // Evaluation point: next 32 bytes
1109+ copy (point [:], input [32 :])
1110+ // Expected output: next 32 bytes
1111+ copy (claim [:], input [64 :])
1112+
1113+ // input kzg point: next 48 bytes
1114+ var commitment kzg4844.Commitment
1115+ copy (commitment [:], input [96 :])
1116+ if kZGToVersionedHash (commitment ) != versionedHash {
1117+ return nil , errBlobVerifyMismatchedVersion
1118+ }
1119+
1120+ // Proof: next 48 bytes
1121+ var proof kzg4844.Proof
1122+ copy (proof [:], input [144 :])
1123+
1124+ if err := kzg4844 .VerifyProof (commitment , point , claim , proof ); err != nil {
1125+ return nil , fmt .Errorf ("%w: %v" , errBlobVerifyKZGProof , err )
1126+ }
1127+
1128+ return common .Hex2Bytes (blobPrecompileReturnValue ), nil
1129+ }
1130+
1131+ // kZGToVersionedHash implements kzg_to_versioned_hash from EIP-4844
1132+ func kZGToVersionedHash (kzg kzg4844.Commitment ) common.Hash {
1133+ h := sha256 .Sum256 (kzg [:])
1134+ h [0 ] = blobCommitmentVersionKZG
1135+
1136+ return h
1137+ }
0 commit comments