all: replace *2, /2 by Lsh, Rsh; reuse big.Int from constants

This change aims to make more efficient usage of math/big.Int's
operations with constant values such as:

* Multiplying by 2^N: .Lsh(v, N) instead of .Mul(v, big.NewInt(2^N))
* Dividing by 2: .Rsh(v, 1) instead of .Div(v, 2)
* Comparing against 0: .Sign() == 1 instead of .Cmp(big.NewInt(0))
* Adding constant derived values: extracting them into reusable globals
This commit is contained in:
Emmanuel T Odeke 2023-10-28 06:14:42 -07:00
parent 233db64cc1
commit 13f233c0e4
No known key found for this signature in database
GPG key ID: 410DDC670CF9BFD7
7 changed files with 28 additions and 17 deletions

View file

@ -260,7 +260,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
return err return err
} }
// Verify that the block number is parent's +1 // Verify that the block number is parent's +1
if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big1) != 0 {
return consensus.ErrInvalidNumber return consensus.ErrInvalidNumber
} }
if chain.Config().IsShanghai(header.Number, header.Time) { if chain.Config().IsShanghai(header.Number, header.Time) {

View file

@ -206,6 +206,7 @@ var benchBuffer = bytes.NewBuffer(make([]byte, 0, 32000))
func BenchmarkEncodeBlock(b *testing.B) { func BenchmarkEncodeBlock(b *testing.B) {
block := makeBenchBlock() block := makeBenchBlock()
b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {

View file

@ -78,6 +78,8 @@ func TestBloomExtensively(t *testing.T) {
func BenchmarkBloom9(b *testing.B) { func BenchmarkBloom9(b *testing.B) {
test := []byte("testestestest") test := []byte("testestestest")
b.ReportAllocs()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
Bloom9(test) Bloom9(test)
} }
@ -86,6 +88,8 @@ func BenchmarkBloom9(b *testing.B) {
func BenchmarkBloom9Lookup(b *testing.B) { func BenchmarkBloom9Lookup(b *testing.B) {
toTest := []byte("testtest") toTest := []byte("testtest")
bloom := new(Bloom) bloom := new(Bloom)
b.ReportAllocs()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
bloom.Test(toTest) bloom.Test(toTest)
} }

View file

@ -194,7 +194,7 @@ func (s cancunSigner) Sender(tx *Transaction) (common.Address, error) {
V, R, S := tx.RawSignatureValues() V, R, S := tx.RawSignatureValues()
// Blob txs are defined to use 0 and 1 as their recovery // Blob txs are defined to use 0 and 1 as their recovery
// id, add 27 to become equivalent to unprotected Homestead signatures. // id, add 27 to become equivalent to unprotected Homestead signatures.
V = new(big.Int).Add(V, big.NewInt(27)) V = new(big.Int).Add(V, big27)
if tx.ChainId().Cmp(s.chainId) != 0 { if tx.ChainId().Cmp(s.chainId) != 0 {
return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId)
} }
@ -262,7 +262,7 @@ func (s londonSigner) Sender(tx *Transaction) (common.Address, error) {
V, R, S := tx.RawSignatureValues() V, R, S := tx.RawSignatureValues()
// DynamicFee txs are defined to use 0 and 1 as their recovery // DynamicFee txs are defined to use 0 and 1 as their recovery
// id, add 27 to become equivalent to unprotected Homestead signatures. // id, add 27 to become equivalent to unprotected Homestead signatures.
V = new(big.Int).Add(V, big.NewInt(27)) V = new(big.Int).Add(V, big27)
if tx.ChainId().Cmp(s.chainId) != 0 { if tx.ChainId().Cmp(s.chainId) != 0 {
return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId)
} }
@ -335,7 +335,7 @@ func (s eip2930Signer) Sender(tx *Transaction) (common.Address, error) {
case AccessListTxType: case AccessListTxType:
// AL txs are defined to use 0 and 1 as their recovery // AL txs are defined to use 0 and 1 as their recovery
// id, add 27 to become equivalent to unprotected Homestead signatures. // id, add 27 to become equivalent to unprotected Homestead signatures.
V = new(big.Int).Add(V, big.NewInt(27)) V = new(big.Int).Add(V, big27)
default: default:
return common.Address{}, ErrTxTypeNotSupported return common.Address{}, ErrTxTypeNotSupported
} }
@ -403,7 +403,7 @@ func NewEIP155Signer(chainId *big.Int) EIP155Signer {
} }
return EIP155Signer{ return EIP155Signer{
chainId: chainId, chainId: chainId,
chainIdMul: new(big.Int).Mul(chainId, big.NewInt(2)), chainIdMul: new(big.Int).Lsh(chainId, 1), // chainId*2
} }
} }
@ -416,7 +416,11 @@ func (s EIP155Signer) Equal(s2 Signer) bool {
return ok && eip155.chainId.Cmp(s.chainId) == 0 return ok && eip155.chainId.Cmp(s.chainId) == 0
} }
var big8 = big.NewInt(8) var (
big8 = big.NewInt(8)
big27 = big.NewInt(27)
big35 = big.NewInt(35)
)
func (s EIP155Signer) Sender(tx *Transaction) (common.Address, error) { func (s EIP155Signer) Sender(tx *Transaction) (common.Address, error) {
if tx.Type() != LegacyTxType { if tx.Type() != LegacyTxType {
@ -579,6 +583,6 @@ func deriveChainId(v *big.Int) *big.Int {
} }
return new(big.Int).SetUint64((v - 35) / 2) return new(big.Int).SetUint64((v - 35) / 2)
} }
v = new(big.Int).Sub(v, big.NewInt(35)) v = new(big.Int).Sub(v, big35)
return v.Div(v, big.NewInt(2)) return v.Rsh(v, 1) // v/2
} }

View file

@ -104,12 +104,14 @@ func (l *lattice) Multi(scalar *big.Int) []uint8 {
return out return out
} }
var big1 = big.NewInt(1)
// round sets num to num/denom rounded to the nearest integer. // round sets num to num/denom rounded to the nearest integer.
func round(num, denom *big.Int) { func round(num, denom *big.Int) {
r := new(big.Int) r := new(big.Int)
num.DivMod(num, denom, r) num.DivMod(num, denom, r)
if r.Cmp(half) == 1 { if r.Cmp(half) == 1 {
num.Add(num, big.NewInt(1)) num.Add(num, big1)
} }
} }

View file

@ -224,22 +224,22 @@ func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
d.Mul(d, d) //(X1+B)² d.Mul(d, d) //(X1+B)²
d.Sub(d, a) //(X1+B)²-A d.Sub(d, a) //(X1+B)²-A
d.Sub(d, c) //(X1+B)²-A-C d.Sub(d, c) //(X1+B)²-A-C
d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C) d.Lsh(d, 1) //2*((X1+B)²-A-C)
e := new(big.Int).Mul(big.NewInt(3), a) //3*A e := new(big.Int).Mul(big.NewInt(3), a) //3*A
f := new(big.Int).Mul(e, e) //E² f := new(big.Int).Mul(e, e) //E²
x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D x3 := new(big.Int).Lsh(d, 1) //2*D
x3.Sub(f, x3) //F-2*D x3.Sub(f, x3) //F-2*D
x3.Mod(x3, BitCurve.P) x3.Mod(x3, BitCurve.P)
y3 := new(big.Int).Sub(d, x3) //D-X3 y3 := new(big.Int).Sub(d, x3) //D-X3
y3.Mul(e, y3) //E*(D-X3) y3.Mul(e, y3) //E*(D-X3)
y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C y3.Sub(y3, new(big.Int).Lsh(c, 3)) //E*(D-X3)-8*C
y3.Mod(y3, BitCurve.P) y3.Mod(y3, BitCurve.P)
z3 := new(big.Int).Mul(y, z) //Y1*Z1 z3 := new(big.Int).Mul(y, z) //Y1*Z1
z3.Mul(big.NewInt(2), z3) //3*Y1*Z1 z3.Lsh(z3, 1) //3*Y1*Z1
z3.Mod(z3, BitCurve.P) z3.Mod(z3, BitCurve.P)
return x3, y3, z3 return x3, y3, z3

View file

@ -52,7 +52,7 @@ func (db *Database) ValidateTransaction(selector *string, tx *apitypes.SendTxArg
// e.g. https://github.com/ethereum/go-ethereum/issues/16106. // e.g. https://github.com/ethereum/go-ethereum/issues/16106.
if len(data) == 0 { if len(data) == 0 {
// Prevent sending ether into black hole (show stopper) // Prevent sending ether into black hole (show stopper)
if tx.Value.ToInt().Cmp(big.NewInt(0)) > 0 { if tx.Value.ToInt().Sign() == 1 { // Greater than 0
return nil, errors.New("transaction will create a contract with value but empty code") return nil, errors.New("transaction will create a contract with value but empty code")
} }
// No value submitted at least, critically Warn, but don't blow up // No value submitted at least, critically Warn, but don't blow up