diff --git a/common/math/modexp.go b/common/math/modexp.go
deleted file mode 100644
index 02ef755574..0000000000
--- a/common/math/modexp.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-import (
- "math/big"
- "math/bits"
-
- "github.com/XinFinOrg/XDPoSChain/common"
-)
-
-// FastExp is semantically equivalent to x.Exp(x,y, m), but is faster for even
-// modulus.
-func FastExp(x, y, m *big.Int) *big.Int {
- // Split m = m1 × m2 where m1 = 2ⁿ
- n := m.TrailingZeroBits()
- m1 := new(big.Int).Lsh(common.Big1, n)
- mask := new(big.Int).Sub(m1, common.Big1)
- m2 := new(big.Int).Rsh(m, n)
-
- // We want z = x**y mod m.
- // z1 = x**y mod m1 = (x**y mod m) mod m1 = z mod m1
- // z2 = x**y mod m2 = (x**y mod m) mod m2 = z mod m2
- z1 := fastExpPow2(x, y, mask)
- z2 := new(big.Int).Exp(x, y, m2)
-
- // Reconstruct z from z1, z2 using CRT, using algorithm from paper,
- // which uses only a single modInverse.
- // p = (z1 - z2) * m2⁻¹ (mod m1)
- // z = z2 + p * m2
- z := new(big.Int).Set(z2)
-
- // Compute (z1 - z2) mod m1 [m1 == 2**n] into z1.
- z1 = z1.And(z1, mask)
- z2 = z2.And(z2, mask)
- z1 = z1.Sub(z1, z2)
- if z1.Sign() < 0 {
- z1 = z1.Add(z1, m1)
- }
-
- // Reuse z2 for p = z1 * m2inv.
- m2inv := new(big.Int).ModInverse(m2, m1)
- z2 = z2.Mul(z1, m2inv)
- z2 = z2.And(z2, mask)
-
- // Reuse z1 for m2 * p.
- z = z.Add(z, z1.Mul(z2, m2))
- z = z.Rem(z, m)
-
- return z
-}
-
-func fastExpPow2(x, y *big.Int, mask *big.Int) *big.Int {
- z := big.NewInt(1)
- if y.Sign() == 0 {
- return z
- }
- p := new(big.Int).Set(x)
- p = p.And(p, mask)
- if p.Cmp(z) <= 0 { // p <= 1
- return p
- }
- if y.Cmp(mask) > 0 {
- y = new(big.Int).And(y, mask)
- }
- t := new(big.Int)
-
- for _, b := range y.Bits() {
- for i := 0; i < bits.UintSize; i++ {
- if b&1 != 0 {
- z, t = t.Mul(z, p), z
- z = z.And(z, mask)
- }
- p, t = t.Mul(p, p), p
- p = p.And(p, mask)
- b >>= 1
- }
- }
- return z
-}
diff --git a/common/math/modexp_test.go b/common/math/modexp_test.go
new file mode 100644
index 0000000000..bd90076f84
--- /dev/null
+++ b/common/math/modexp_test.go
@@ -0,0 +1,53 @@
+// Copyright 2022 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 .
+
+package math
+
+import (
+ "math/big"
+ "testing"
+
+ big2 "github.com/holiman/big"
+)
+
+// TestFastModexp tests some cases found during fuzzing.
+func TestFastModexp(t *testing.T) {
+ for i, tc := range []struct {
+ base string
+ exp string
+ mod string
+ }{
+ {"0xeffffff900002f00", "0x40000000000000", "0x200"},
+ {"0xf000", "0x4f900b400080000", "0x400000d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9ffffff005aeffd310000000000000000000000000000000000009f9f9f9f0000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000befffa5a5a5fff900002f000040000000000000000000000000000000029d9d9d000000000000009f9f9f00000000000000009f9f9f000000f3a080ab00000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f0000000000002900009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000cf000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000befffff0000c0800000000800000000000000000000000000000002000000000000009f9f9f0000000000000000008000ff000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000befffa5a5a5fff900002f000040000000000000000000000000000000029d9d9d000000000000009f9f9f00000000000000009f9f9f000000f3a080ab00000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f0000000000002900009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f000000000000000000000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000beffffff900002f0000400000c100000000000000000000000000000000000000006160600000000000000000008000ff0000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f00000000000000009f9f0000"},
+ {"5", "1435700818", "72"},
+ {"0xffff", "0x300030003000300030003000300030003000302a3000300030003000300030003000300030003000300030003000300030003030623066307f3030783062303430383064303630343036", "0x300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
+ {"0x3133", "0x667f00000000000000000000000000ff002a000000000000000000000000000000000000000000000000000000000000667fff30783362773057ee756a6c266134643831646230313630", "0x3030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
+ } {
+ var (
+ base, _ = new(big.Int).SetString(tc.base, 0)
+ exp, _ = new(big.Int).SetString(tc.exp, 0)
+ mod, _ = new(big.Int).SetString(tc.mod, 0)
+ base2, _ = new(big2.Int).SetString(tc.base, 0)
+ exp2, _ = new(big2.Int).SetString(tc.exp, 0)
+ mod2, _ = new(big2.Int).SetString(tc.mod, 0)
+ )
+ var a = new(big2.Int).Exp(base2, exp2, mod2).String()
+ var b = new(big.Int).Exp(base, exp, mod).String()
+ if a != b {
+ t.Errorf("test %d: %#x ^ %#x mod %#x \n have %x\n want %x", i, base, exp, mod, a, b)
+ }
+ }
+}
diff --git a/go.mod b/go.mod
index b7baee7256..7e9a4f481d 100644
--- a/go.mod
+++ b/go.mod
@@ -61,6 +61,7 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.3.0 // indirect
+ github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e // indirect
diff --git a/go.sum b/go.sum
index 98d3a63aed..36c3740a1f 100644
--- a/go.sum
+++ b/go.sum
@@ -141,6 +141,8 @@ github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw=
+github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU=
github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o=
github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw=
github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=
diff --git a/tests/fuzzers/modexp/debug/main.go b/tests/fuzzers/modexp/debug/main.go
new file mode 100644
index 0000000000..008e46b192
--- /dev/null
+++ b/tests/fuzzers/modexp/debug/main.go
@@ -0,0 +1,40 @@
+// Copyright 2020 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 .
+
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/XinFinOrg/XDPoSChain/tests/fuzzers/modexp"
+)
+
+func main() {
+ if len(os.Args) != 2 {
+ fmt.Fprintf(os.Stderr, "Usage: debug \n")
+ fmt.Fprintf(os.Stderr, "Example\n")
+ fmt.Fprintf(os.Stderr, " $ debug ../crashers/4bbef6857c733a87ecf6fd8b9e7238f65eb9862a\n")
+ os.Exit(1)
+ }
+ crasher := os.Args[1]
+ data, err := os.ReadFile(crasher)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
+ os.Exit(1)
+ }
+ modexp.Fuzz(data)
+}
diff --git a/tests/fuzzers/modexp/modexp-fuzzer.go b/tests/fuzzers/modexp/modexp-fuzzer.go
index 38e8487d1b..bdbfd86e30 100644
--- a/tests/fuzzers/modexp/modexp-fuzzer.go
+++ b/tests/fuzzers/modexp/modexp-fuzzer.go
@@ -21,8 +21,8 @@ import (
"math/big"
"github.com/XinFinOrg/XDPoSChain/common"
- "github.com/XinFinOrg/XDPoSChain/common/math"
"github.com/XinFinOrg/XDPoSChain/core/vm"
+ big2 "github.com/holiman/big"
)
// The function must return
@@ -55,18 +55,21 @@ func Fuzz(input []byte) int {
input = input[96:]
// Retrieve the operands and execute the exponentiation
var (
- base = new(big.Int).SetBytes(getData(input, 0, baseLen))
- exp = new(big.Int).SetBytes(getData(input, baseLen, expLen))
- mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
+ base = new(big.Int).SetBytes(getData(input, 0, baseLen))
+ exp = new(big.Int).SetBytes(getData(input, baseLen, expLen))
+ mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
+ base2 = new(big2.Int).SetBytes(getData(input, 0, baseLen))
+ exp2 = new(big2.Int).SetBytes(getData(input, baseLen, expLen))
+ mod2 = new(big2.Int).SetBytes(getData(input, baseLen+expLen, modLen))
)
if mod.BitLen() == 0 {
// Modulo 0 is undefined, return zero
return -1
}
- var a = math.FastExp(new(big.Int).Set(base), new(big.Int).Set(exp), new(big.Int).Set(mod))
- var b = base.Exp(base, exp, mod)
- if a.Cmp(b) != 0 {
- panic(fmt.Sprintf("Inequality %x != %x", a, b))
+ var a = new(big2.Int).Exp(base2, exp2, mod2).String()
+ var b = new(big.Int).Exp(base, exp, mod).String()
+ if a != b {
+ panic(fmt.Sprintf("Inequality %#x ^ %#x mod %#x \n have %s\n want %s", base, exp, mod, a, b))
}
return 1
}