Skip to content

Commit

Permalink
core/vm: BLS gas changes for pectra-devnet-5 per EIP-2537 (#13346)
Browse files Browse the repository at this point in the history
Refer to the following:
ethereum/EIPs#9116
ethereum/EIPs#9098
ethereum/EIPs#9097
ethereum/EIPs#8945

Issue board: #12401

---------

Co-authored-by: Sina Mahmoodi <[email protected]>
  • Loading branch information
somnathb1 and s1na authored Jan 15, 2025
1 parent dcd5921 commit c12b113
Show file tree
Hide file tree
Showing 15 changed files with 1,239 additions and 2,284 deletions.
104 changes: 12 additions & 92 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,12 @@ var PrecompiledContractsPrague = map[libcommon.Address]PrecompiledContract{
libcommon.BytesToAddress([]byte{0x09}): &blake2F{},
libcommon.BytesToAddress([]byte{0x0a}): &pointEvaluation{},
libcommon.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
libcommon.BytesToAddress([]byte{0x0c}): &bls12381G1Mul{},
libcommon.BytesToAddress([]byte{0x0d}): &bls12381G1MultiExp{},
libcommon.BytesToAddress([]byte{0x0e}): &bls12381G2Add{},
libcommon.BytesToAddress([]byte{0x0f}): &bls12381G2Mul{},
libcommon.BytesToAddress([]byte{0x10}): &bls12381G2MultiExp{},
libcommon.BytesToAddress([]byte{0x11}): &bls12381Pairing{},
libcommon.BytesToAddress([]byte{0x12}): &bls12381MapFpToG1{},
libcommon.BytesToAddress([]byte{0x13}): &bls12381MapFp2ToG2{},
libcommon.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{},
libcommon.BytesToAddress([]byte{0x0d}): &bls12381G2Add{},
libcommon.BytesToAddress([]byte{0x0e}): &bls12381G2MultiExp{},
libcommon.BytesToAddress([]byte{0x0f}): &bls12381Pairing{},
libcommon.BytesToAddress([]byte{0x10}): &bls12381MapFpToG1{},
libcommon.BytesToAddress([]byte{0x11}): &bls12381MapFp2ToG2{},
}

var (
Expand Down Expand Up @@ -735,45 +733,6 @@ func (c *bls12381G1Add) Run(input []byte) ([]byte, error) {
return encodePointG1(p0), nil
}

// bls12381G1Mul implements EIP-2537 G1Mul precompile.
type bls12381G1Mul struct{}

// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 {
return params.Bls12381G1MulGas
}

func (c *bls12381G1Mul) Run(input []byte) ([]byte, error) {
// Implements EIP-2537 G1Mul precompile.
// > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes).
// > Output is an encoding of multiplication operation result - single G1 point (`128` bytes).
if len(input) != 160 {
return nil, errBLS12381InvalidInputLength
}
var err error
var p0 *bls12381.G1Affine

// Decode G1 point
if p0, err = decodePointG1(input[:128]); err != nil {
return nil, err
}

// Fast subgroup check
if !p0.IsInSubGroup() {
return nil, errBLS12381G1PointSubgroup
}

// Decode scalar value
e := new(big.Int).SetBytes(input[128:])

// Compute r = e * p_0
r := new(bls12381.G1Affine)
r.ScalarMultiplication(p0, e)

// Encode the G1 point into 128 bytes
return encodePointG1(r), nil
}

// bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile.
type bls12381G1MultiExp struct{}

Expand All @@ -787,10 +746,10 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
}
// Lookup discount value for G1 point, scalar value pair length
var discount uint64
if dLen := len(params.Bls12381MultiExpDiscountTable); k < dLen {
discount = params.Bls12381MultiExpDiscountTable[k-1]
if dLen := len(params.Bls12381MSMDiscountTableG1); k < dLen {
discount = params.Bls12381MSMDiscountTableG1[k-1]
} else {
discount = params.Bls12381MultiExpDiscountTable[dLen-1]
discount = params.Bls12381MSMDiscountTableG1[dLen-1]
}
// Calculate gas and return the result
return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000
Expand Down Expand Up @@ -868,45 +827,6 @@ func (c *bls12381G2Add) Run(input []byte) ([]byte, error) {
return encodePointG2(r), nil
}

// bls12381G2Mul implements EIP-2537 G2Mul precompile.
type bls12381G2Mul struct{}

// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 {
return params.Bls12381G2MulGas
}

func (c *bls12381G2Mul) Run(input []byte) ([]byte, error) {
// Implements EIP-2537 G2MUL precompile logic.
// > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes).
// > Output is an encoding of multiplication operation result - single G2 point (`256` bytes).
if len(input) != 288 {
return nil, errBLS12381InvalidInputLength
}
var err error
var p0 *bls12381.G2Affine

// Decode G2 point
if p0, err = decodePointG2(input[:256]); err != nil {
return nil, err
}

// Fast subgroup check
if !p0.IsInSubGroup() {
return nil, errBLS12381G2PointSubgroup
}

// Decode scalar value
e := new(big.Int).SetBytes(input[256:])

// Compute r = e * p_0
r := new(bls12381.G2Affine)
r.ScalarMultiplication(p0, e)

// Encode the G2 point into 256 bytes
return encodePointG2(r), nil
}

// bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile.
type bls12381G2MultiExp struct{}

Expand All @@ -920,10 +840,10 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
}
// Lookup discount value for G2 point, scalar value pair length
var discount uint64
if dLen := len(params.Bls12381MultiExpDiscountTable); k < dLen {
discount = params.Bls12381MultiExpDiscountTable[k-1]
if dLen := len(params.Bls12381MSMDiscountTableG2); k < dLen {
discount = params.Bls12381MSMDiscountTableG2[k-1]
} else {
discount = params.Bls12381MultiExpDiscountTable[dLen-1]
discount = params.Bls12381MSMDiscountTableG2[dLen-1]
}
// Calculate gas and return the result
return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000
Expand Down
34 changes: 1 addition & 33 deletions core/vm/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,8 @@ var allPrecompiles = map[libcommon.Address]PrecompiledContract{
libcommon.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
libcommon.BytesToAddress([]byte{9}): &blake2F{},
libcommon.BytesToAddress([]byte{10}): &bls12381G1Add{},
libcommon.BytesToAddress([]byte{11}): &bls12381G1Mul{},
libcommon.BytesToAddress([]byte{12}): &bls12381G1MultiExp{},
libcommon.BytesToAddress([]byte{13}): &bls12381G2Add{},
libcommon.BytesToAddress([]byte{14}): &bls12381G2Mul{},
libcommon.BytesToAddress([]byte{15}): &bls12381G2MultiExp{},
libcommon.BytesToAddress([]byte{16}): &bls12381Pairing{},
libcommon.BytesToAddress([]byte{17}): &bls12381MapFpToG1{},
Expand Down Expand Up @@ -313,10 +311,8 @@ func benchJson(name, addr string, b *testing.B) {
}

func TestPrecompiledBLS12381G1Add(t *testing.T) { testJson("blsG1Add", "0a", t) }
func TestPrecompiledBLS12381G1Mul(t *testing.T) { testJson("blsG1Mul", "0b", t) }
func TestPrecompiledBLS12381G1MultiExp(t *testing.T) { testJson("blsG1MultiExp", "0c", t) }
func TestPrecompiledBLS12381G2Add(t *testing.T) { testJson("blsG2Add", "0d", t) }
func TestPrecompiledBLS12381G2Mul(t *testing.T) { testJson("blsG2Mul", "0e", t) }
func TestPrecompiledBLS12381G2MultiExp(t *testing.T) { testJson("blsG2MultiExp", "0f", t) }
func TestPrecompiledBLS12381Pairing(t *testing.T) { testJson("blsPairing", "10", t) }
func TestPrecompiledBLS12381MapG1(t *testing.T) { testJson("blsMapG1", "11", t) }
Expand All @@ -327,48 +323,20 @@ func BenchmarkPrecompiledBLS12381G1Add(b *testing.B) { benchJson("blsG1Add"
func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B) { benchJson("blsG1Mul", "0b", b) }
func BenchmarkPrecompiledBLS12381G1MultiExp(b *testing.B) { benchJson("blsG1MultiExp", "0c", b) }
func BenchmarkPrecompiledBLS12381G2Add(b *testing.B) { benchJson("blsG2Add", "0d", b) }
func BenchmarkPrecompiledBLS12381G2Mul(b *testing.B) { benchJson("blsG2Mul", "0e", b) }
func BenchmarkPrecompiledBLS12381G2MultiExp(b *testing.B) { benchJson("blsG2MultiExp", "0f", b) }
func BenchmarkPrecompiledBLS12381Pairing(b *testing.B) { benchJson("blsPairing", "10", b) }
func BenchmarkPrecompiledBLS12381MapG1(b *testing.B) { benchJson("blsMapG1", "11", b) }
func BenchmarkPrecompiledBLS12381MapG2(b *testing.B) { benchJson("blsMapG2", "12", b) }

// Failure tests
func TestPrecompiledBLS12381G1AddFail(t *testing.T) { testJsonFail("blsG1Add", "0a", t) }
func TestPrecompiledBLS12381G1MulFail(t *testing.T) { testJsonFail("blsG1Mul", "0b", t) }
func TestPrecompiledBLS12381G1MultiExpFail(t *testing.T) { testJsonFail("blsG1MultiExp", "0c", t) }
func TestPrecompiledBLS12381G2AddFail(t *testing.T) { testJsonFail("blsG2Add", "0d", t) }
func TestPrecompiledBLS12381G2MulFail(t *testing.T) { testJsonFail("blsG2Mul", "0e", t) }
func TestPrecompiledBLS12381G2MultiExpFail(t *testing.T) { testJsonFail("blsG2MultiExp", "0f", t) }
func TestPrecompiledBLS12381PairingFail(t *testing.T) { testJsonFail("blsPairing", "10", t) }
func TestPrecompiledBLS12381MapG1Fail(t *testing.T) { testJsonFail("blsMapG1", "11", t) }
func TestPrecompiledBLS12381MapG2Fail(t *testing.T) { testJsonFail("blsMapG2", "12", t) }

// Tests from https://github.com/ethereum/EIPs/tree/master/assets/eip-2537
func TestPrecompiledBLS12381G1AddEip(t *testing.T) { testJson("blsG1Add-eip", "0a", t) }
func TestPrecompiledBLS12381G1MulEip(t *testing.T) { testJson("blsG1Mul-eip", "0b", t) }
func TestPrecompiledBLS12381G1MultiExpEip(t *testing.T) { testJson("blsG1MultiExp-eip", "0c", t) }
func TestPrecompiledBLS12381G2AddEip(t *testing.T) { testJson("blsG2Add-eip", "0d", t) }
func TestPrecompiledBLS12381G2MulEip(t *testing.T) { testJson("blsG2Mul-eip", "0e", t) }
func TestPrecompiledBLS12381G2MultiExpEip(t *testing.T) { testJson("blsG2MultiExp-eip", "0f", t) }
func TestPrecompiledBLS12381PairingEip(t *testing.T) { testJson("blsPairing-eip", "10", t) }
func TestPrecompiledBLS12381MapG1Eip(t *testing.T) { testJson("blsMapG1-eip", "11", t) }
func TestPrecompiledBLS12381MapG2Eip(t *testing.T) { testJson("blsMapG2-eip", "12", t) }

func TestPrecompiledBLS12381G1AddFailEip(t *testing.T) { testJsonFail("blsG1Add-eip", "0a", t) }
func TestPrecompiledBLS12381G1MulFailEip(t *testing.T) { testJsonFail("blsG1Mul-eip", "0b", t) }
func TestPrecompiledBLS12381G1MultiExpFailEip(t *testing.T) {
testJsonFail("blsG1MultiExp-eip", "0c", t)
}
func TestPrecompiledBLS12381G2AddFailEip(t *testing.T) { testJsonFail("blsG2Add-eip", "0d", t) }
func TestPrecompiledBLS12381G2MulFailEip(t *testing.T) { testJsonFail("blsG2Mul-eip", "0e", t) }
func TestPrecompiledBLS12381G2MultiExpFailEip(t *testing.T) {
testJsonFail("blsG2MultiExp-eip", "0f", t)
}
func TestPrecompiledBLS12381PairingFailEip(t *testing.T) { testJsonFail("blsPairing-eip", "10", t) }
func TestPrecompiledBLS12381MapG1FailEip(t *testing.T) { testJsonFail("blsMapG1-eip", "11", t) }
func TestPrecompiledBLS12381MapG2FailEip(t *testing.T) { testJsonFail("blsMapG2-eip", "12", t) }

func loadJson(name string) ([]precompiledTest, error) {
data, err := os.ReadFile(fmt.Sprintf("testdata/precompiles/%v.json", name))
if err != nil {
Expand Down Expand Up @@ -439,7 +407,7 @@ func BenchmarkPrecompiledP256Verify(b *testing.B) {
}

func TestPrecompiledP256Verify(t *testing.T) {
t.Parallel()
// t.Parallel()

testJson("p256Verify", "100", t)
}
Loading

0 comments on commit c12b113

Please sign in to comment.