pax_global_header00006660000000000000000000000064147246025470014525gustar00rootroot0000000000000052 comment=a17fcfb6f8b0245533928fa96aace2cd4c2e9b18 uint256-1.3.2/000077500000000000000000000000001472460254700127445ustar00rootroot00000000000000uint256-1.3.2/.deepsource.toml000066400000000000000000000002611472460254700160540ustar00rootroot00000000000000version = 1 test_patterns = [ "*/*_test.go", "*_test.go" ] [[analyzers]] name = "go" enabled = true [analyzers.meta] import_paths = ["github.com/holiman/uint256"]uint256-1.3.2/.gitignore000066400000000000000000000000601472460254700147300ustar00rootroot00000000000000/.idea # go output files *.test *.out *.pb.gz uint256-1.3.2/AUTHORS000066400000000000000000000005571472460254700140230ustar00rootroot00000000000000# This is the official list of uint256 authors for copyright purposes. Martin Holst Swende Guillaume Ballet Kurkó Mihály Paweł Bylica Yao Zengzeng Dag Arne Osvik Thanee Charattrakool uint256-1.3.2/COPYING000066400000000000000000000027301472460254700140010ustar00rootroot00000000000000BSD 3-Clause License Copyright 2020 uint256 Authors Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.uint256-1.3.2/README.md000066400000000000000000000200731472460254700142250ustar00rootroot00000000000000# Fixed size 256-bit math library This is a library specialized at replacing the big.Int library for math based on 256-bit types, used by both [go-ethereum](https://github.com/ethereum/go-ethereum) and [erigon](https://github.com/ledgerwatch/erigon). [![Go Reference](https://pkg.go.dev/badge/github.com/holiman/uint256.svg)](https://pkg.go.dev/github.com/holiman/uint256) [![codecov](https://codecov.io/gh/holiman/uint256/branch/master/graph/badge.svg?token=LHs7xL99wQ)](https://codecov.io/gh/holiman/uint256) [![DeepSource](https://deepsource.io/gh/holiman/uint256.svg/?label=active+issues&token=CNJRIm7wXZdOM9xKKH4hXUKd)](https://deepsource.io/gh/holiman/uint256/?ref=repository-badge) ## Benchmarks Current benchmarks, with tests ending with `big` being the standard `big.Int` library, and `uint256` being this library. ### Current status - As of 2020-03-18, `uint256` wins over `math/big` in every single case, often with orders of magnitude. - And as of release `0.1.0`, the `uint256` library is alloc-free. - With the `1.0.0` release, it also has `100%` test coverage. ### Bitwise | benchmark | `u256` time/op | `big` time/op | time diff | `u256` B/op| `big` B/op | B diff| `u256` allocs/op | `big` allocs/op | allocs diff | |--|--|--|--|--|--|--|--|--|--| | And/single | 2.03ns | 8.46ns | `-76.04%` | 0 | 0 | `~` | 0 | 0 | `~`| | Or/single | 2.03ns | 10.98ns | `-81.51%` | 0 | 0 | `~` | 0 | 0 | `~`| | Xor/single | 2.03ns | 12.19ns | `-83.34%` | 0 | 0 | `~` | 0 | 0 | `~`| | Rsh/n_eq_0 | 5.00ns | 48.11ns | `-89.61%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| | Rsh/n_gt_0 | 10.42ns | 48.41ns | `-78.48%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| | Rsh/n_gt_64 | 6.94ns | 52.39ns | `-86.76%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| | Rsh/n_gt_128 | 5.49ns | 44.21ns | `-87.59%` | 0 | 48 | `-100.00%` | 0 | 1 | `-100.00%`| | Rsh/n_gt_192 | 3.43ns | 28.71ns | `-88.04%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| | Lsh/n_eq_0 | 4.89ns | 40.49ns | `-87.92%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| | Lsh/n_gt_0 | 10.14ns | 53.25ns | `-80.96%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| | Lsh/n_gt_64 | 7.50ns | 53.92ns | `-86.08%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| | Lsh/n_gt_128 | 5.39ns | 56.86ns | `-90.52%` | 0 | 96 | `-100.00%` | 0 | 1 | `-100.00%`| | Lsh/n_gt_192 | 3.90ns | 57.61ns | `-93.23%` | 0 | 96 | `-100.00%` | 0 | 1 | `-100.00%`| ### Conversions | benchmark | `u256` time/op | `big` time/op | time diff | `u256` B/op| `big` B/op | B diff| `u256` allocs/op | `big` allocs/op | allocs diff | |--|--|--|--|--|--|--|--|--|--| | FromHexString | 116.70ns | 861.30ns | `-86.45%` | 32 | 88 | `-63.64%` | 1 | 3 | `-66.67%`| | FromDecimalString | 7973.00ns | 32850.00ns | `-75.73%` | 0 | 2464 | `-100.00%` | 0 | 77 | `-100.00%`| | Float64/Float64 | 2366.00ns | 28483.00ns | `-91.69%` | 0 | 23424 | `-100.00%` | 0 | 510 | `-100.00%`| | EncodeHex/large | 95.26ns | 184.30ns | `-48.31%` | 80 | 140 | `-42.86%` | 1 | 2 | `-50.00%`| | Decimal/ToDecimal | 67384.00ns | 83431.00ns | `-19.23%` | 11344 | 31920 | `-64.46%` | 248 | 594 | `-58.25%`| | Decimal/ToPrettyDecimal | 84208.00ns | 123953.00ns | `-32.06%` | 14720 | 61376 | `-76.02%` | 251 | 1100 | `-77.18%`| ### Math | benchmark | `u256` time/op | `big` time/op | time diff | `u256` B/op| `big` B/op | B diff| `u256` allocs/op | `big` allocs/op | allocs diff | |--|--|--|--|--|--|--|--|--|--| | Add/single | 1.99ns | 18.11ns | `-89.02%` | 0 | 0 | `~` | 0 | 0 | `~`| | Sub/single | 2.00ns | 17.19ns | `-88.35%` | 0 | 0 | `~` | 0 | 0 | `~`| | Mul/single | 12.10ns | 57.69ns | `-79.03%` | 0 | 0 | `~` | 0 | 0 | `~`| | SDiv/large | 94.64ns | 642.10ns | `-85.26%` | 0 | 312 | `-100.00%` | 0 | 6 | `-100.00%`| | Sqrt/single | 594.90ns | 1844.00ns | `-67.74%` | 0 | 528 | `-100.00%` | 0 | 7 | `-100.00%`| | Square/single | 12.49ns | 56.10ns | `-77.74%` | 0 | 0 | `~` | 0 | 0 | `~`| | Cmp/single | 4.78ns | 12.79ns | `-62.61%` | 0 | 0 | `~` | 0 | 0 | `~`| | Div/small | 12.91ns | 48.31ns | `-73.28%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| | Div/mod64 | 65.77ns | 111.20ns | `-40.85%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| | Div/mod128 | 93.67ns | 301.40ns | `-68.92%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| | Div/mod192 | 86.52ns | 263.80ns | `-67.20%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| | Div/mod256 | 77.17ns | 252.80ns | `-69.47%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| | AddMod/small | 13.84ns | 48.16ns | `-71.26%` | 0 | 4 | `-100.00%` | 0 | 0 | `~`| | AddMod/mod64 | 22.83ns | 57.58ns | `-60.35%` | 0 | 11 | `-100.00%` | 0 | 0 | `~`| | AddMod/mod128 | 48.31ns | 145.00ns | `-66.68%` | 0 | 12 | `-100.00%` | 0 | 0 | `~`| | AddMod/mod192 | 47.26ns | 160.00ns | `-70.46%` | 0 | 12 | `-100.00%` | 0 | 0 | `~`| | AddMod/mod256 | 14.44ns | 143.20ns | `-89.92%` | 0 | 12 | `-100.00%` | 0 | 0 | `~`| | MulMod/small | 40.81ns | 63.14ns | `-35.37%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| | MulMod/mod64 | 91.66ns | 112.60ns | `-18.60%` | 0 | 48 | `-100.00%` | 0 | 1 | `-100.00%`| | MulMod/mod128 | 136.00ns | 362.70ns | `-62.50%` | 0 | 128 | `-100.00%` | 0 | 2 | `-100.00%`| | MulMod/mod192 | 151.70ns | 421.20ns | `-63.98%` | 0 | 144 | `-100.00%` | 0 | 2 | `-100.00%`| | MulMod/mod256 | 188.80ns | 489.20ns | `-61.41%` | 0 | 176 | `-100.00%` | 0 | 2 | `-100.00%`| | Exp/small | 433.70ns | 7490.00ns | `-94.21%` | 0 | 7392 | `-100.00%` | 0 | 77 | `-100.00%`| | Exp/large | 5145.00ns | 23043.00ns | `-77.67%` | 0 | 18144 | `-100.00%` | 0 | 189 | `-100.00%`| | Mod/mod64 | 70.94ns | 118.90ns | `-40.34%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| | Mod/small | 14.82ns | 46.27ns | `-67.97%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| | Mod/mod128 | 99.58ns | 286.90ns | `-65.29%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| | Mod/mod192 | 95.31ns | 269.30ns | `-64.61%` | 0 | 48 | `-100.00%` | 0 | 1 | `-100.00%`| | Mod/mod256 | 84.13ns | 222.90ns | `-62.26%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| | MulOverflow/single | 27.68ns | 57.52ns | `-51.88%` | 0 | 0 | `~` | 0 | 0 | `~`| | MulDivOverflow/small | 2.83ns | 22.97ns | `-87.69%` | 0 | 0 | `~` | 0 | 0 | `~`| | MulDivOverflow/div64 | 2.85ns | 23.13ns | `-87.66%` | 0 | 0 | `~` | 0 | 0 | `~`| | MulDivOverflow/div128 | 3.14ns | 31.29ns | `-89.96%` | 0 | 2 | `-100.00%` | 0 | 0 | `~`| | MulDivOverflow/div192 | 3.17ns | 30.28ns | `-89.54%` | 0 | 2 | `-100.00%` | 0 | 0 | `~`| | MulDivOverflow/div256 | 3.54ns | 35.56ns | `-90.06%` | 0 | 5 | `-100.00%` | 0 | 0 | `~`| | Lt/small | 3.12ns | 10.43ns | `-70.06%` | 0 | 0 | `~` | 0 | 0 | `~`| | Lt/large | 3.49ns | 10.32ns | `-66.18%` | 0 | 0 | `~` | 0 | 0 | `~`| ### Other | benchmark | `u256` time/op | `u256` B/op| `u256` allocs/op | |--|--|--|--| | SetBytes/generic | 104.30ns | 0 | 0 || | Sub/single/uint256_of | 1.99ns | 0 | 0 || | SetFromBig/overflow | 3.57ns | 0 | 0 || | ToBig/2words | 73.84ns | 64 | 2 || | SetBytes/specific | 45.81ns | 0 | 0 || | ScanScientific | 674.10ns | 0 | 0 || | SetFromBig/4words | 3.82ns | 0 | 0 || | ToBig/4words | 68.82ns | 64 | 2 || | RLPEncoding | 11917.00ns | 11911 | 255 || | SetFromBig/1word | 2.99ns | 0 | 0 || | SetFromBig/3words | 4.12ns | 0 | 0 || | ToBig/3words | 70.12ns | 64 | 2 || | ToBig/1word | 75.38ns | 64 | 2 || | MulMod/mod256/uint256r | 77.11ns | 0 | 0 || | HashTreeRoot | 11.27ns | 0 | 0 || | SetFromBig/2words | 3.90ns | 0 | 0 || ## Helping out If you're interested in low-level algorithms and/or doing optimizations for shaving off nanoseconds, then this is certainly for you! ### Implementation work Choose an operation, and optimize the s**t out of it! A few rules, though, to help your PR get approved: - Do not optimize for 'best-case'/'most common case' at the expense of worst-case. - We'll hold off on go assembly for a while, until the algos and interfaces are finished in a 'good enough' first version. After that, it's assembly time. ### Doing benchmarks To do a simple benchmark for everything, do ``` go test -run - -bench . -benchmem ``` To see the difference between a branch and master, for a particular benchmark, do ``` git checkout master go test -run - -bench Benchmark_Lsh -benchmem -count=10 > old.txt git checkout opt_branch go test -run - -bench Benchmark_Lsh -benchmem -count=10 > new.txt benchstat old.txt new.txt ``` uint256-1.3.2/benchmarks_test.go000066400000000000000000001025571472460254700164610ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "math/big" "math/rand" "testing" ) const numSamples = 1024 var ( int32Samples [numSamples]Int int32SamplesLt [numSamples]Int int64Samples [numSamples]Int int64SamplesLt [numSamples]Int int128Samples [numSamples]Int int128SamplesLt [numSamples]Int int192Samples [numSamples]Int int192SamplesLt [numSamples]Int int256Samples [numSamples]Int int256SamplesLt [numSamples]Int // int256SamplesLt[i] <= int256Samples[i] big32Samples [numSamples]big.Int big32SamplesLt [numSamples]big.Int big64Samples [numSamples]big.Int big64SamplesLt [numSamples]big.Int big128Samples [numSamples]big.Int big128SamplesLt [numSamples]big.Int big192Samples [numSamples]big.Int big192SamplesLt [numSamples]big.Int big256Samples [numSamples]big.Int big256SamplesLt [numSamples]big.Int // big256SamplesLt[i] <= big256Samples[i] _ = initSamples() ) func initSamples() bool { rnd := rand.New(rand.NewSource(0)) // newRandInt creates new Int with so many highly likely non-zero random words. newRandInt := func(numWords int) Int { var z Int for i := 0; i < numWords; i++ { z[i] = rnd.Uint64() } return z } for i := 0; i < numSamples; i++ { x32g := rnd.Uint32() x32l := rnd.Uint32() if x32g < x32l { x32g, x32l = x32l, x32g } int32Samples[i].SetUint64(uint64(x32g)) big32Samples[i] = *int32Samples[i].ToBig() int32SamplesLt[i].SetUint64(uint64(x32l)) big32SamplesLt[i] = *int32SamplesLt[i].ToBig() l := newRandInt(1) g := newRandInt(1) if g.Lt(&l) { g, l = l, g } if g[0] == 0 { g[0]++ } int64Samples[i] = g big64Samples[i] = *int64Samples[i].ToBig() int64SamplesLt[i] = l big64SamplesLt[i] = *int64SamplesLt[i].ToBig() l = newRandInt(2) g = newRandInt(2) if g.Lt(&l) { g, l = l, g } if g[1] == 0 { g[1]++ } int128Samples[i] = g big128Samples[i] = *int128Samples[i].ToBig() int128SamplesLt[i] = l big128SamplesLt[i] = *int128SamplesLt[i].ToBig() l = newRandInt(3) g = newRandInt(3) if g.Lt(&l) { g, l = l, g } if g[2] == 0 { g[2]++ } int192Samples[i] = g big192Samples[i] = *int192Samples[i].ToBig() int192SamplesLt[i] = l big192SamplesLt[i] = *int192SamplesLt[i].ToBig() l = newRandInt(4) g = newRandInt(4) if g.Lt(&l) { g, l = l, g } if g[3] == 0 { g[3]++ } int256Samples[i] = g big256Samples[i] = *int256Samples[i].ToBig() int256SamplesLt[i] = l big256SamplesLt[i] = *int256SamplesLt[i].ToBig() } return true } func benchmark_Add_Bit(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) f, _ := FromBig(b1) f2, _ := FromBig(b2) bench.ResetTimer() for i := 0; i < bench.N; i++ { f.Add(f, f2) } } func benchmark_Add_Big(bench *testing.B) { b := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) bench.ResetTimer() for i := 0; i < bench.N; i++ { b.Add(b, b2) } } func BenchmarkAdd(bench *testing.B) { bench.Run("single/big", benchmark_Add_Big) bench.Run("single/uint256", benchmark_Add_Bit) } func benchmark_SubOverflow_Bit(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) f, _ := FromBig(b1) f2, _ := FromBig(b2) bench.ResetTimer() for i := 0; i < bench.N; i++ { f.SubOverflow(f, f2) } } func benchmark_Sub_Bit(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) f, _ := FromBig(b1) f2, _ := FromBig(b2) bench.ResetTimer() for i := 0; i < bench.N; i++ { f.Sub(f, f2) } } func benchmark_Sub_Big(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) bench.ResetTimer() for i := 0; i < bench.N; i++ { b1.Sub(b1, b2) } } func BenchmarkSub(bench *testing.B) { bench.Run("single/big", benchmark_Sub_Big) bench.Run("single/uint256", benchmark_Sub_Bit) bench.Run("single/uint256_of", benchmark_SubOverflow_Bit) } func BenchmarkMul(bench *testing.B) { benchmarkUint256 := func(bench *testing.B) { a := big.NewInt(0).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b := big.NewInt(0).SetBytes(hex2Bytes("f123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) fa, _ := FromBig(a) fb, _ := FromBig(b) result := new(Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { result.Mul(fa, fb) } } benchmarkBig := func(bench *testing.B) { a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b := new(big.Int).SetBytes(hex2Bytes("f123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { bigU256(result.Mul(a, b)) } } bench.Run("single/uint256", benchmarkUint256) bench.Run("single/big", benchmarkBig) } func BenchmarkMulOverflow(bench *testing.B) { benchmarkUint256 := func(bench *testing.B) { a := big.NewInt(0).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b := big.NewInt(0).SetBytes(hex2Bytes("f123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) fa, _ := FromBig(a) fb, _ := FromBig(b) result := new(Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { result.MulOverflow(fa, fb) } } benchmarkBig := func(bench *testing.B) { a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b := new(big.Int).SetBytes(hex2Bytes("f123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { bigU256(result.Mul(a, b)) } } bench.Run("single/uint256", benchmarkUint256) bench.Run("single/big", benchmarkBig) } func BenchmarkSquare(bench *testing.B) { benchmarkUint256 := func(bench *testing.B) { a := new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) result := new(Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { result.Set(a).squared() } } benchmarkBig := func(bench *testing.B) { a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { bigU256(result.Mul(a, a)) } } bench.Run("single/uint256", benchmarkUint256) bench.Run("single/big", benchmarkBig) } func BenchmarkSqrt(bench *testing.B) { benchmarkUint256 := func(bench *testing.B) { bench.ReportAllocs() a := new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) result := new(Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { result.Sqrt(a) } } benchmarkBig := func(bench *testing.B) { bench.ReportAllocs() a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { result.Sqrt(a) } } bench.Run("single/uint256", benchmarkUint256) bench.Run("single/big", benchmarkBig) } func benchmark_And_Big(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) bench.ResetTimer() for i := 0; i < bench.N; i++ { b1.And(b1, b2) } } func benchmark_And_Bit(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) f, _ := FromBig(b1) f2, _ := FromBig(b2) bench.ResetTimer() for i := 0; i < bench.N; i++ { f.And(f, f2) } } func BenchmarkAnd(bench *testing.B) { bench.Run("single/big", benchmark_And_Big) bench.Run("single/uint256", benchmark_And_Bit) } func benchmark_Or_Big(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) bench.ResetTimer() for i := 0; i < bench.N; i++ { b1.Or(b1, b2) } } func benchmark_Or_Bit(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) f, _ := FromBig(b1) f2, _ := FromBig(b2) bench.ResetTimer() for i := 0; i < bench.N; i++ { f.Or(f, f2) } } func BenchmarkOr(bench *testing.B) { bench.Run("single/big", benchmark_Or_Big) bench.Run("single/uint256", benchmark_Or_Bit) } func benchmark_Xor_Big(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) bench.ResetTimer() for i := 0; i < bench.N; i++ { b1.Xor(b1, b2) } } func benchmark_Xor_Bit(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) f, _ := FromBig(b1) f2, _ := FromBig(b2) bench.ResetTimer() for i := 0; i < bench.N; i++ { f.Xor(f, f2) } } func BenchmarkXor(bench *testing.B) { bench.Run("single/big", benchmark_Xor_Big) bench.Run("single/uint256", benchmark_Xor_Bit) } func benchmark_Cmp_Big(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) bench.ResetTimer() for i := 0; i < bench.N; i++ { b1.Cmp(b2) b2.Cmp(b1) } } func benchmark_Cmp_Bit(bench *testing.B) { b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) f, _ := FromBig(b1) f2, _ := FromBig(b2) bench.ResetTimer() for i := 0; i < bench.N; i++ { f.Cmp(f2) f2.Cmp(f) } } func BenchmarkCmp(bench *testing.B) { bench.Run("single/big", benchmark_Cmp_Big) bench.Run("single/uint256", benchmark_Cmp_Bit) } func BenchmarkCmpBig(bench *testing.B) { // This bench tests where the Cmp is non-equal bench.Run("nonequal", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { x := &big256Samples[i%len(big256Samples)] z := &int256Samples[len(int256Samples)-(i%len(int256Samples))-1] _ = z.CmpBig(x) } }) bench.Run("equal", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { x := &big256Samples[i%len(big256Samples)] z := &int256Samples[i%len(big256Samples)] if z.CmpBig(x) != 0 { b.Fatal("test error") } } }) } func BenchmarkLt(b *testing.B) { benchmarkUint256 := func(b *testing.B, samples *[numSamples]Int) (flag bool) { var x Int for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { y := samples[i] flag = x.Lt(&y) x = y } } return } benchmarkBig := func(b *testing.B, samples *[numSamples]big.Int) (flag bool) { var x big.Int for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { y := samples[i] flag = x.Cmp(&y) < 0 x = y } } return } b.Run("large/uint256", func(b *testing.B) { benchmarkUint256(b, &int256Samples) }) b.Run("large/big", func(b *testing.B) { benchmarkBig(b, &big256Samples) }) b.Run("small/uint256", func(b *testing.B) { benchmarkUint256(b, &int64Samples) }) b.Run("small/big", func(b *testing.B) { benchmarkBig(b, &big64Samples) }) } func benchmark_Lsh_Big(n uint, bench *testing.B) { original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) bench.ResetTimer() for i := 0; i < bench.N; i++ { b1 := big.NewInt(0) b1.Lsh(original, n) } } func benchmark_Lsh_Big_N_EQ_0(bench *testing.B) { benchmark_Lsh_Big(0, bench) } func benchmark_Lsh_Big_N_GT_192(bench *testing.B) { benchmark_Lsh_Big(193, bench) } func benchmark_Lsh_Big_N_GT_128(bench *testing.B) { benchmark_Lsh_Big(129, bench) } func benchmark_Lsh_Big_N_GT_64(bench *testing.B) { benchmark_Lsh_Big(65, bench) } func benchmark_Lsh_Big_N_GT_0(bench *testing.B) { benchmark_Lsh_Big(1, bench) } func benchmark_Lsh_Bit(n uint, bench *testing.B) { original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) f2, _ := FromBig(original) bench.ResetTimer() for i := 0; i < bench.N; i++ { f1 := new(Int) f1.Lsh(f2, n) } } func benchmark_Lsh_Bit_N_EQ_0(bench *testing.B) { benchmark_Lsh_Bit(0, bench) } func benchmark_Lsh_Bit_N_GT_192(bench *testing.B) { benchmark_Lsh_Bit(193, bench) } func benchmark_Lsh_Bit_N_GT_128(bench *testing.B) { benchmark_Lsh_Bit(129, bench) } func benchmark_Lsh_Bit_N_GT_64(bench *testing.B) { benchmark_Lsh_Bit(65, bench) } func benchmark_Lsh_Bit_N_GT_0(bench *testing.B) { benchmark_Lsh_Bit(1, bench) } func BenchmarkLsh(bench *testing.B) { bench.Run("n_eq_0/big", benchmark_Lsh_Big_N_EQ_0) bench.Run("n_gt_192/big", benchmark_Lsh_Big_N_GT_192) bench.Run("n_gt_128/big", benchmark_Lsh_Big_N_GT_128) bench.Run("n_gt_64/big", benchmark_Lsh_Big_N_GT_64) bench.Run("n_gt_0/big", benchmark_Lsh_Big_N_GT_0) bench.Run("n_eq_0/uint256", benchmark_Lsh_Bit_N_EQ_0) bench.Run("n_gt_192/uint256", benchmark_Lsh_Bit_N_GT_192) bench.Run("n_gt_128/uint256", benchmark_Lsh_Bit_N_GT_128) bench.Run("n_gt_64/uint256", benchmark_Lsh_Bit_N_GT_64) bench.Run("n_gt_0/uint256", benchmark_Lsh_Bit_N_GT_0) } func benchmark_Rsh_Big(n uint, bench *testing.B) { original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) bench.ResetTimer() for i := 0; i < bench.N; i++ { b1 := big.NewInt(0) b1.Rsh(original, n) } } func benchmark_Rsh_Big_N_EQ_0(bench *testing.B) { benchmark_Rsh_Big(0, bench) } func benchmark_Rsh_Big_N_GT_192(bench *testing.B) { benchmark_Rsh_Big(193, bench) } func benchmark_Rsh_Big_N_GT_128(bench *testing.B) { benchmark_Rsh_Big(129, bench) } func benchmark_Rsh_Big_N_GT_64(bench *testing.B) { benchmark_Rsh_Big(65, bench) } func benchmark_Rsh_Big_N_GT_0(bench *testing.B) { benchmark_Rsh_Big(1, bench) } func benchmark_Rsh_Bit(n uint, bench *testing.B) { original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) f2, _ := FromBig(original) bench.ResetTimer() for i := 0; i < bench.N; i++ { f1 := new(Int) f1.Rsh(f2, n) } } func benchmark_Rsh_Bit_N_EQ_0(bench *testing.B) { benchmark_Rsh_Bit(0, bench) } func benchmark_Rsh_Bit_N_GT_192(bench *testing.B) { benchmark_Rsh_Bit(193, bench) } func benchmark_Rsh_Bit_N_GT_128(bench *testing.B) { benchmark_Rsh_Bit(129, bench) } func benchmark_Rsh_Bit_N_GT_64(bench *testing.B) { benchmark_Rsh_Bit(65, bench) } func benchmark_Rsh_Bit_N_GT_0(bench *testing.B) { benchmark_Rsh_Bit(1, bench) } func BenchmarkRsh(bench *testing.B) { bench.Run("n_eq_0/big", benchmark_Rsh_Big_N_EQ_0) bench.Run("n_gt_192/big", benchmark_Rsh_Big_N_GT_192) bench.Run("n_gt_128/big", benchmark_Rsh_Big_N_GT_128) bench.Run("n_gt_64/big", benchmark_Rsh_Big_N_GT_64) bench.Run("n_gt_0/big", benchmark_Rsh_Big_N_GT_0) bench.Run("n_eq_0/uint256", benchmark_Rsh_Bit_N_EQ_0) bench.Run("n_gt_192/uint256", benchmark_Rsh_Bit_N_GT_192) bench.Run("n_gt_128/uint256", benchmark_Rsh_Bit_N_GT_128) bench.Run("n_gt_64/uint256", benchmark_Rsh_Bit_N_GT_64) bench.Run("n_gt_0/uint256", benchmark_Rsh_Bit_N_GT_0) } // bigExp implements exponentiation by squaring. // The result is truncated to 256 bits. func bigExp(result, base, exponent *big.Int) *big.Int { result.SetUint64(1) for _, word := range exponent.Bits() { for i := 0; i < wordBits; i++ { if word&1 == 1 { bigU256(result.Mul(result, base)) } bigU256(base.Mul(base, base)) word >>= 1 } } return result } func benchmark_Exp_Big(bench *testing.B, x, y string) { orig := big.NewInt(0).SetBytes(hex2Bytes(x)) base := big.NewInt(0).SetBytes(hex2Bytes(x)) exp := big.NewInt(0).SetBytes(hex2Bytes(y)) result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { bigExp(result, base, exp) base.Set(orig) } } func benchmark_Exp_U256(bench *testing.B, x, y string) { var ( base = big.NewInt(0).SetBytes(hex2Bytes(x)) exp = big.NewInt(0).SetBytes(hex2Bytes(y)) f_base, _ = FromBig(base) f_orig, _ = FromBig(base) f_exp, _ = FromBig(exp) f_res Int ) bench.ResetTimer() for i := 0; i < bench.N; i++ { f_res.Exp(f_base, f_exp) f_base.Set(f_orig) } } func BenchmarkExp(bench *testing.B) { { // Large values base := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" exp := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" bench.Run("large/big", func(b *testing.B) { benchmark_Exp_Big(b, base, exp) }) bench.Run("large/uint256", func(b *testing.B) { benchmark_Exp_U256(b, base, exp) }) } { // Smaller exponent base := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" exp := "8abcdef" bench.Run("small/big", func(b *testing.B) { benchmark_Exp_Big(b, base, exp) }) bench.Run("small/uint256", func(b *testing.B) { benchmark_Exp_U256(b, base, exp) }) } { // Even base (and very small exponent) base := "ABCDEF090807060504030201fffffffffffffffffffffffffffffffffffffffe" exp := "ff" bench.Run("even/big", func(b *testing.B) { benchmark_Exp_Big(b, base, exp) }) bench.Run("even/uint256", func(b *testing.B) { benchmark_Exp_U256(b, base, exp) }) } } func BenchmarkDiv(b *testing.B) { benchmarkDivUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { var sink Int for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { sink.Div(&xSamples[i], &modSamples[i]) } } } benchmarkDivBig := func(b *testing.B, xSamples, modSamples *[numSamples]big.Int) { var sink big.Int for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { sink.Div(&xSamples[i], &modSamples[i]) } } } b.Run("small/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int32Samples, &int32SamplesLt) }) b.Run("mod64/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int64Samples) }) b.Run("mod128/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int128Samples) }) b.Run("mod192/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int192Samples) }) b.Run("mod256/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int256SamplesLt) }) b.Run("small/big", func(b *testing.B) { benchmarkDivBig(b, &big32Samples, &big32SamplesLt) }) b.Run("mod64/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big64Samples) }) b.Run("mod128/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big128Samples) }) b.Run("mod192/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big192Samples) }) b.Run("mod256/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big256SamplesLt) }) } func BenchmarkMod(b *testing.B) { benchmarkModUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { var sink Int for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { sink.Mod(&xSamples[i], &modSamples[i]) } } } benchmarkModBig := func(b *testing.B, xSamples, modSamples *[numSamples]big.Int) { var sink big.Int for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { sink.Mod(&xSamples[i], &modSamples[i]) } } } b.Run("small/uint256", func(b *testing.B) { benchmarkModUint256(b, &int32Samples, &int32SamplesLt) }) b.Run("mod64/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int64Samples) }) b.Run("mod128/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int128Samples) }) b.Run("mod192/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int192Samples) }) b.Run("mod256/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int256SamplesLt) }) b.Run("small/big", func(b *testing.B) { benchmarkModBig(b, &big32Samples, &big32SamplesLt) }) b.Run("mod64/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big64Samples) }) b.Run("mod128/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big128Samples) }) b.Run("mod192/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big192Samples) }) b.Run("mod256/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big256SamplesLt) }) } func BenchmarkDivMod(b *testing.B) { benchmarkDivModUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { var sink, mod Int for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { sink.DivMod(&xSamples[i], &modSamples[i], &mod) } } } benchmarkDivModBig := func(b *testing.B, xSamples, modSamples *[numSamples]big.Int) { var sink, mod big.Int for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { sink.DivMod(&xSamples[i], &modSamples[i], &mod) } } } b.Run("small/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int32Samples, &int32SamplesLt) }) b.Run("mod64/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int64Samples) }) b.Run("mod128/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int128Samples) }) b.Run("mod192/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int192Samples) }) b.Run("mod256/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int256SamplesLt) }) b.Run("small/big", func(b *testing.B) { benchmarkDivModBig(b, &big32Samples, &big32SamplesLt) }) b.Run("mod64/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big64Samples) }) b.Run("mod128/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big128Samples) }) b.Run("mod192/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big192Samples) }) b.Run("mod256/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big256SamplesLt) }) } func BenchmarkAddMod(b *testing.B) { benchmarkAddModUint256 := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { iter := (b.N + numSamples - 1) / numSamples for j := 0; j < numSamples; j++ { var x Int y := factorsSamples[j] for i := 0; i < iter; i++ { x.AddMod(&x, &y, &modSamples[j]) } } } benchmarkAddModBig := func(b *testing.B, factorsSamples, modSamples *[numSamples]big.Int) { iter := (b.N + numSamples - 1) / numSamples for j := 0; j < numSamples; j++ { var x big.Int y := factorsSamples[j] for i := 0; i < iter; i++ { x.Add(&x, &y) x.Mod(&x, &modSamples[j]) } } } b.Run("small/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int32SamplesLt, &int32Samples) }) b.Run("mod64/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int64SamplesLt, &int64Samples) }) b.Run("mod128/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int128SamplesLt, &int128Samples) }) b.Run("mod192/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int192SamplesLt, &int192Samples) }) b.Run("mod256/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int256SamplesLt, &int256Samples) }) b.Run("small/big", func(b *testing.B) { benchmarkAddModBig(b, &big32SamplesLt, &big32Samples) }) b.Run("mod64/big", func(b *testing.B) { benchmarkAddModBig(b, &big64SamplesLt, &big64Samples) }) b.Run("mod128/big", func(b *testing.B) { benchmarkAddModBig(b, &big128SamplesLt, &big128Samples) }) b.Run("mod192/big", func(b *testing.B) { benchmarkAddModBig(b, &big192SamplesLt, &big192Samples) }) b.Run("mod256/big", func(b *testing.B) { benchmarkAddModBig(b, &big256SamplesLt, &big256Samples) }) } func BenchmarkMulMod(b *testing.B) { benchmarkMulModUint256R := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { iter := (b.N + numSamples - 1) / numSamples var mu [numSamples][5]uint64 for i := 0; i < numSamples; i++ { mu[i] = Reciprocal(&modSamples[i]) } b.ResetTimer() for j := 0; j < numSamples; j++ { x := factorsSamples[j] for i := 0; i < iter; i++ { x.MulModWithReciprocal(&x, &factorsSamples[j], &modSamples[j], &mu[j]) } } } benchmarkMulModUint256 := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { iter := (b.N + numSamples - 1) / numSamples for j := 0; j < numSamples; j++ { x := factorsSamples[j] for i := 0; i < iter; i++ { x.MulMod(&x, &factorsSamples[j], &modSamples[j]) } } } benchmarkMulModBig := func(b *testing.B, factorsSamples, modSamples *[numSamples]big.Int) { iter := (b.N + numSamples - 1) / numSamples for j := 0; j < numSamples; j++ { x := factorsSamples[j] for i := 0; i < iter; i++ { x.Mul(&x, &factorsSamples[j]) x.Mod(&x, &modSamples[j]) } } } b.Run("small/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int32SamplesLt, &int32Samples) }) b.Run("mod64/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int64SamplesLt, &int64Samples) }) b.Run("mod128/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int128SamplesLt, &int128Samples) }) b.Run("mod192/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int192SamplesLt, &int192Samples) }) b.Run("mod256/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int256SamplesLt, &int256Samples) }) b.Run("mod256/uint256r", func(b *testing.B) { benchmarkMulModUint256R(b, &int256SamplesLt, &int256Samples) }) b.Run("small/big", func(b *testing.B) { benchmarkMulModBig(b, &big32SamplesLt, &big32Samples) }) b.Run("mod64/big", func(b *testing.B) { benchmarkMulModBig(b, &big64SamplesLt, &big64Samples) }) b.Run("mod128/big", func(b *testing.B) { benchmarkMulModBig(b, &big128SamplesLt, &big128Samples) }) b.Run("mod192/big", func(b *testing.B) { benchmarkMulModBig(b, &big192SamplesLt, &big192Samples) }) b.Run("mod256/big", func(b *testing.B) { benchmarkMulModBig(b, &big256SamplesLt, &big256Samples) }) } func benchmark_SdivLarge_Big(bench *testing.B) { a := new(big.Int).SetBytes(hex2Bytes("800fffffffffffffffffffffffffd1e870eec79504c60144cc7f5fc2bad1e611")) b := new(big.Int).SetBytes(hex2Bytes("ff3f9014f20db29ae04af2c2d265de17")) bench.ResetTimer() for i := 0; i < bench.N; i++ { bigU256(bigSDiv(new(big.Int), a, b)) } } func benchmark_SdivLarge_Bit(bench *testing.B) { a := big.NewInt(0).SetBytes(hex2Bytes("800fffffffffffffffffffffffffd1e870eec79504c60144cc7f5fc2bad1e611")) b := big.NewInt(0).SetBytes(hex2Bytes("ff3f9014f20db29ae04af2c2d265de17")) fa, _ := FromBig(a) fb, _ := FromBig(b) bench.ResetTimer() for i := 0; i < bench.N; i++ { f := new(Int) f.SDiv(fa, fb) } } func BenchmarkSDiv(bench *testing.B) { bench.Run("large/big", benchmark_SdivLarge_Big) bench.Run("large/uint256", benchmark_SdivLarge_Bit) } func BenchmarkEncodeHex(b *testing.B) { hexEncodeU256 := func(b *testing.B, samples *[numSamples]Int) { b.ReportAllocs() for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { samples[i].Hex() } } } hexEncodeBig := func(b *testing.B, samples *[numSamples]big.Int) { b.ReportAllocs() for j := 0; j < b.N; j += numSamples { for i := 0; i < numSamples; i++ { // We're being nice to big.Int here, because this method // does not add the 0x-prefix -- so an extra alloc is needed to get // the same result. We still win the benchmark though... samples[i].Text(16) } } } b.Run("large/uint256", func(b *testing.B) { hexEncodeU256(b, &int256Samples) }) b.Run("large/big", func(b *testing.B) { hexEncodeBig(b, &big256Samples) }) } func BenchmarkFromHexString(b *testing.B) { var hexStrings []string for _, z := range &int256Samples { hexStrings = append(hexStrings, (&z).Hex()) } b.Run("uint256", func(b *testing.B) { b.ReportAllocs() for j := 0; j < b.N; j++ { i := j % numSamples if _, err := FromHex(hexStrings[i]); err != nil { b.Fatalf("%v: %v", err, string(hexStrings[i])) } } }) b.Run("big", func(b *testing.B) { b.ReportAllocs() for j := 0; j < b.N; j++ { i := j % numSamples if _, ok := big.NewInt(0).SetString(hexStrings[i], 0); !ok { b.Fatalf("Error on %v", string(hexStrings[i])) } } }) } func BenchmarkMulDivOverflow(b *testing.B) { benchmarkUint256 := func(b *testing.B, factorsSamples, muldivSamples *[numSamples]Int) { iter := (b.N + numSamples - 1) / numSamples for j := 0; j < numSamples; j++ { x := factorsSamples[j] for i := 0; i < iter; i++ { res := new(Int) res.MulDivOverflow(&x, &x, &muldivSamples[j]) } } } benchmarkBig := func(b *testing.B, factorsSamples, muldivSamples *[numSamples]big.Int) { iter := (b.N + numSamples - 1) / numSamples for j := 0; j < numSamples; j++ { x := factorsSamples[j] for i := 0; i < iter; i++ { res := new(big.Int) res.Mul(&x, &x) res.Div(res, &muldivSamples[j]) } } } b.Run("small/uint256", func(b *testing.B) { benchmarkUint256(b, &int32SamplesLt, &int32Samples) }) b.Run("div64/uint256", func(b *testing.B) { benchmarkUint256(b, &int64SamplesLt, &int64Samples) }) b.Run("div128/uint256", func(b *testing.B) { benchmarkUint256(b, &int128SamplesLt, &int128Samples) }) b.Run("div192/uint256", func(b *testing.B) { benchmarkUint256(b, &int192SamplesLt, &int192Samples) }) b.Run("div256/uint256", func(b *testing.B) { benchmarkUint256(b, &int256SamplesLt, &int256Samples) }) b.Run("small/big", func(b *testing.B) { benchmarkBig(b, &big32SamplesLt, &big32Samples) }) b.Run("div64/big", func(b *testing.B) { benchmarkBig(b, &big64SamplesLt, &big64Samples) }) b.Run("div128/big", func(b *testing.B) { benchmarkBig(b, &big128SamplesLt, &big128Samples) }) b.Run("div192/big", func(b *testing.B) { benchmarkBig(b, &big192SamplesLt, &big192Samples) }) b.Run("div256/big", func(b *testing.B) { benchmarkBig(b, &big256SamplesLt, &big256Samples) }) } func BenchmarkHashTreeRoot(b *testing.B) { var ( z = &Int{1, 2, 3, 4} exp = [32]byte{1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0} ) b.ReportAllocs() for i := 0; i < b.N; i++ { r, err := z.HashTreeRoot() if err != nil { b.Fatal(err) } if r != exp { b.Fatalf("have %v want %v", r, exp) } } } func BenchmarkSet(bench *testing.B) { benchmarkUint256 := func(bench *testing.B) { a := new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) result := new(Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { result.Set(a) } } benchmarkBig := func(bench *testing.B) { a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) result := new(big.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { result.Set(a) } } bench.Run("single/uint256", benchmarkUint256) bench.Run("single/big", benchmarkBig) } func BenchmarkByte(bench *testing.B) { var ( a = new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) num = NewInt(0) result = new(Int) ) bench.ResetTimer() for i := 0; i < bench.N; i++ { for ii := uint64(0); ii < 32; ii++ { result.Set(a) num.SetUint64(ii) _ = result.Byte(num) } } } func BenchmarkExtendSign(b *testing.B) { a, err := FromHex("0xf123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9") if err != nil { b.Fatal(err) } result := new(Int) n := NewInt(0) b.ResetTimer() for i := uint64(0); i < uint64(b.N); i++ { n.SetUint64(i % 33) result.ExtendSign(a, n) } } func BenchmarkWriteTo(b *testing.B) { fa, err := FromHex("0x1100030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") if err != nil { b.Fatal(err) } b.Run("fixed-20", func(b *testing.B) { dest := [20]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} for i := 0; i < b.N; i++ { fa.WriteToArray20(&dest) } _ = (string(dest[:])) // Prevent the compiler from optimizing away the op }) b.Run("fixed-32", func(b *testing.B) { dest := [32]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} for i := 0; i < b.N; i++ { fa.WriteToArray32(&dest) } _ = (string(dest[:])) // Prevent the compiler from optimizing away the op }) b.Run("slice", func(b *testing.B) { dest := make([]byte, 64) for i := 0; i < b.N; i++ { fa.WriteToSlice(dest) } _ = (string(dest[:])) // Prevent the compiler from optimizing away the op }) b.Run("put256", func(b *testing.B) { dest := make([]byte, 64) for i := 0; i < b.N; i++ { fa.PutUint256(dest) } _ = (string(dest[:])) // Prevent the compiler from optimizing away the op }) } uint256-1.3.2/binary_test.go000066400000000000000000000204231472460254700156170ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "fmt" "math/big" "testing" ) type opDualArgFunc func(*Int, *Int, *Int) *Int type bigDualArgFunc func(*big.Int, *big.Int, *big.Int) *big.Int type opCmpArgFunc func(*Int, *Int) bool type bigCmpArgFunc func(*big.Int, *big.Int) bool type binaryOpEntry struct { name string u256Fn opDualArgFunc bigFn bigDualArgFunc } func lookupBinary(name string) binaryOpEntry { for _, tc := range binaryOpFuncs { if tc.name == name { return tc } } panic(fmt.Sprintf("%v not found", name)) } var binaryOpFuncs = []binaryOpEntry{ {"Add", (*Int).Add, (*big.Int).Add}, {"Sub", (*Int).Sub, (*big.Int).Sub}, {"Mul", (*Int).Mul, (*big.Int).Mul}, {"Div", (*Int).Div, bigDiv}, {"Mod", (*Int).Mod, bigMod}, {"SDiv", (*Int).SDiv, bigSDiv}, {"SMod", (*Int).SMod, bigSMod}, {"And", (*Int).And, (*big.Int).And}, {"Or", (*Int).Or, (*big.Int).Or}, {"Xor", (*Int).Xor, (*big.Int).Xor}, {"Exp", (*Int).Exp, func(b1, b2, b3 *big.Int) *big.Int { return b1.Exp(b2, b3, bigtt256) }}, {"Lsh", u256Lsh, bigLsh}, {"Rsh", u256Rsh, bigRsh}, {"SRsh", u256SRsh, bigSRsh}, {"DivModDiv", divModDiv, bigDiv}, {"DivModMod", divModMod, bigMod}, {"udivremDiv", udivremDiv, bigDiv}, {"udivremMod", udivremMod, bigMod}, {"ExtendSign", (*Int).ExtendSign, bigExtendSign}, } var cmpOpFuncs = []struct { name string u256Fn opCmpArgFunc bigFn bigCmpArgFunc }{ {"Eq", (*Int).Eq, func(a, b *big.Int) bool { return a.Cmp(b) == 0 }}, {"Lt", (*Int).Lt, func(a, b *big.Int) bool { return a.Cmp(b) < 0 }}, {"Gt", (*Int).Gt, func(a, b *big.Int) bool { return a.Cmp(b) > 0 }}, {"Slt", (*Int).Slt, func(a, b *big.Int) bool { return bigS256(a).Cmp(bigS256(b)) < 0 }}, {"Sgt", (*Int).Sgt, func(a, b *big.Int) bool { return bigS256(a).Cmp(bigS256(b)) > 0 }}, {"CmpEq", func(a, b *Int) bool { return a.Cmp(b) == 0 }, func(a, b *big.Int) bool { return a.Cmp(b) == 0 }}, {"CmpLt", func(a, b *Int) bool { return a.Cmp(b) < 0 }, func(a, b *big.Int) bool { return a.Cmp(b) < 0 }}, {"CmpGt", func(a, b *Int) bool { return a.Cmp(b) > 0 }, func(a, b *big.Int) bool { return a.Cmp(b) > 0 }}, {"LtUint64", func(a, b *Int) bool { return a.LtUint64(b.Uint64()) }, func(a, b *big.Int) bool { return a.Cmp(new(big.Int).SetUint64(b.Uint64())) < 0 }}, {"GtUint64", func(a, b *Int) bool { return a.GtUint64(b.Uint64()) }, func(a, b *big.Int) bool { return a.Cmp(new(big.Int).SetUint64(b.Uint64())) > 0 }}, } func checkBinaryOperation(t *testing.T, opName string, op opDualArgFunc, bigOp bigDualArgFunc, x, y Int) { var ( b1 = x.ToBig() b2 = y.ToBig() f1 = x.Clone() f2 = y.Clone() operation = fmt.Sprintf("op: %v ( %v, %v ) ", opName, x.Hex(), y.Hex()) want, _ = FromBig(bigOp(new(big.Int), b1, b2)) have = op(new(Int), f1, f2) ) // Compare result with big.Int. if !have.Eq(want) { t.Fatalf("%v\nwant : %#x\nhave : %#x\n", operation, want, have) } // Check if arguments are unmodified. if !f1.Eq(x.Clone()) { t.Fatalf("%v\nfirst argument had been modified: %x", operation, f1) } if !f2.Eq(y.Clone()) { t.Fatalf("%v\nsecond argument had been modified: %x", operation, f2) } // Check if reusing args as result works correctly. have = op(f1, f1, y.Clone()) if have != f1 { t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f1) } if !have.Eq(want) { t.Fatalf("%v\non argument reuse x.op(x,y)\nwant : %#x\nhave : %#x\n", operation, want, have) } have = op(f2, x.Clone(), f2) if have != f2 { t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f2) } if !have.Eq(want) { t.Fatalf("%v\n on argument reuse x.op(y,x)\nwant : %#x\nhave : %#x\n", operation, want, have) } } func TestBinaryOperations(t *testing.T) { for _, tc := range binaryOpFuncs { for _, inputs := range binTestCases { f1 := MustFromHex(inputs[0]) f2 := MustFromHex(inputs[1]) checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) } } } func Test10KRandomBinaryOperations(t *testing.T) { for _, tc := range binaryOpFuncs { for i := 0; i < 10000; i++ { f1 := randNum() f2 := randNum() checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) } } } func FuzzBinaryOperations(f *testing.F) { f.Fuzz(func(t *testing.T, x0, x1, x2, x3, y0, y1, y2, y3 uint64) { x := Int{x0, x1, x2, x3} y := Int{y0, y1, y2, y3} for _, tc := range binaryOpFuncs { checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, x, y) } }) } func u256Rsh(z, x, y *Int) *Int { return z.Rsh(x, uint(y.Uint64()&0x1FF)) } func bigRsh(z, x, y *big.Int) *big.Int { return z.Rsh(x, uint(y.Uint64()&0x1FF)) } func u256Lsh(z, x, y *Int) *Int { return z.Lsh(x, uint(y.Uint64()&0x1FF)) } func u256SRsh(z, x, y *Int) *Int { return z.SRsh(x, uint(y.Uint64()&0x1FF)) } func bigLsh(z, x, y *big.Int) *big.Int { return z.Lsh(x, uint(y.Uint64()&0x1FF)) } func bigSRsh(z, x, y *big.Int) *big.Int { return z.Rsh(bigS256(x), uint(y.Uint64()&0x1FF)) } func bigExtendSign(result, num, byteNum *big.Int) *big.Int { if byteNum.Cmp(big.NewInt(31)) >= 0 { return result.Set(num) } bit := uint(byteNum.Uint64()*8 + 7) mask := byteNum.Lsh(big.NewInt(1), bit) mask.Sub(mask, big.NewInt(1)) if num.Bit(int(bit)) > 0 { result.Or(num, mask.Not(mask)) } else { result.And(num, mask) } return result } // bigDiv implements uint256/EVM compatible division for big.Int: returns 0 when dividing by 0 func bigDiv(z, x, y *big.Int) *big.Int { if y.Sign() == 0 { return z.SetUint64(0) } return z.Div(x, y) } // bigMod implements uint256/EVM compatible mod for big.Int: returns 0 when dividing by 0 func bigMod(z, x, y *big.Int) *big.Int { if y.Sign() == 0 { return z.SetUint64(0) } return z.Mod(x, y) } // bigSDiv implements EVM-compatible SDIV operation on big.Int func bigSDiv(result, x, y *big.Int) *big.Int { if y.Sign() == 0 { return result.SetUint64(0) } sx := bigS256(x) sy := bigS256(y) n := new(big.Int) if sx.Sign() == sy.Sign() { n.SetInt64(1) } else { n.SetInt64(-1) } result.Div(sx.Abs(sx), sy.Abs(sy)) result.Mul(result, n) return result } // bigSMod implements EVM-compatible SMOD operation on big.Int func bigSMod(result, x, y *big.Int) *big.Int { if y.Sign() == 0 { return result.SetUint64(0) } sx := bigS256(x) sy := bigS256(y) neg := sx.Sign() < 0 result.Mod(sx.Abs(sx), sy.Abs(sy)) if neg { result.Neg(result) } return bigU256(result) } // divModDiv wraps DivMod and returns quotient only func divModDiv(z, x, y *Int) *Int { var m Int z.DivMod(x, y, &m) return z } // divModMod wraps DivMod and returns modulus only func divModMod(z, x, y *Int) *Int { new(Int).DivMod(x, y, z) return z } // udivremDiv wraps udivrem and returns quotient func udivremDiv(z, x, y *Int) *Int { var quot Int if !y.IsZero() { udivrem(quot[:], x[:], y, nil) } return z.Set(") } // udivremMod wraps udivrem and returns remainder func udivremMod(z, x, y *Int) *Int { if y.IsZero() { return z.Clear() } var quot, rem Int udivrem(quot[:], x[:], y, &rem) return z.Set(&rem) } func checkCompareOperation(t *testing.T, opName string, op opCmpArgFunc, bigOp bigCmpArgFunc, x, y Int) { var ( f1orig = x.Clone() f2orig = y.Clone() b1 = x.ToBig() b2 = y.ToBig() f1 = new(Int).Set(f1orig) f2 = new(Int).Set(f2orig) operation = fmt.Sprintf("op: %v ( %v, %v ) ", opName, x.Hex(), y.Hex()) want = bigOp(b1, b2) have = op(f1, f2) ) // Compare result with big.Int. if have != want { t.Fatalf("%v\nwant : %v\nhave : %v\n", operation, want, have) } // Check if arguments are unmodified. if !f1.Eq(f1orig) { t.Fatalf("%v\nfirst argument had been modified: %x", operation, f1) } if !f2.Eq(f2orig) { t.Fatalf("%v\nsecond argument had been modified: %x", operation, f2) } } func TestCompareOperations(t *testing.T) { for _, tc := range cmpOpFuncs { for _, inputs := range binTestCases { f1 := MustFromHex(inputs[0]) f2 := MustFromHex(inputs[1]) checkCompareOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) } } } func FuzzCompareOperations(f *testing.F) { f.Fuzz(func(t *testing.T, x0, x1, x2, x3, y0, y1, y2, y3 uint64) { x := Int{x0, x1, x2, x3} y := Int{y0, y1, y2, y3} for _, tc := range cmpOpFuncs { checkCompareOperation(t, tc.name, tc.u256Fn, tc.bigFn, x, y) } }) } uint256-1.3.2/circle.yml000066400000000000000000000064641472460254700147420ustar00rootroot00000000000000version: 2.1 commands: test: parameters: arch: default: "amd64" description: The target architecture. type: enum enum: ["amd64", "386"] steps: - run: name: "Test (<>)" command: | export GOARCH=<> go version go env go test -v -coverprofile=coverage-<>.txt -covermode=count jobs: go123: docker: - image: cimg/go:1.23 steps: - run: name: "Install tools" command: | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.61.0 - checkout - run: name: "Lint" command: golangci-lint run - test: arch: "amd64" - test: arch: "386" - run: name: "Codecov upload" command: bash <(curl -s https://codecov.io/bash) - restore_cache: keys: - corpus-v3 - run: name: "Fuzzing" command: | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzBinaryOperations -fuzztime 20s GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzCompareOperations -fuzztime 20s GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzTernaryOperations -fuzztime 20s GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzBase10StringCompare -fuzztime 10s GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzDecimal -fuzztime 10s GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzFloat64 -fuzztime 10s GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzLog10 -fuzztime 10s GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzSetString -fuzztime 10s - save_cache: key: corpus-v3-{{ epoch }} paths: - corpus-v3 - run: name: "Benchmark" command: go test -run=- -bench=. -benchmem - run: name: "Build tests for PPC64" command: | GOARCH=ppc64 go test -c mv uint256.test uint256.test.ppc64 - persist_to_workspace: root: . paths: - uint256.test.* bigendian: docker: - image: cimg/base:current steps: - run: name: "Install QEMU" command: sudo apt-get -q update && sudo apt-get -qy install qemu-user-static --no-install-recommends - attach_workspace: at: . - run: name: "Test (PPC64 emulation)" command: qemu-ppc64-static uint256.test.ppc64 -test.v go122: docker: - image: cimg/go:1.22 steps: - checkout - test go121: docker: - image: cimg/go:1.21 steps: - checkout - test go120: docker: - image: cimg/go:1.20 steps: - checkout - test go119: docker: - image: cimg/go:1.19 steps: - checkout - test workflows: version: 2 uint256: jobs: - go119 - go120 - go121 - go122 - go123: requires: - go122 - bigendian: requires: - go123 uint256-1.3.2/codecov.yml000066400000000000000000000001601472460254700151060ustar00rootroot00000000000000codecov: require_ci_to_pass: no coverage: status: project: no patch: no comment: layout: "diff" uint256-1.3.2/conversion.go000066400000000000000000000647301472460254700154720ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "database/sql" "database/sql/driver" "encoding" "encoding/binary" "encoding/json" "errors" "fmt" "io" "math" "math/big" "math/bits" "strings" ) const ( maxWords = 256 / bits.UintSize // number of big.Words in 256-bit // The constants below work as compile-time checks: in case evaluated to // negative value it cannot be assigned to uint type and compilation fails. // These particular expressions check if maxWords either 4 or 8 matching // 32-bit and 64-bit architectures. _ uint = -(maxWords & (maxWords - 1)) // maxWords is power of two. _ uint = -(maxWords & ^(4 | 8)) // maxWords is 4 or 8. ) // Compile time interface checks var ( _ driver.Valuer = (*Int)(nil) _ sql.Scanner = (*Int)(nil) _ encoding.TextMarshaler = (*Int)(nil) _ encoding.TextUnmarshaler = (*Int)(nil) _ json.Marshaler = (*Int)(nil) _ json.Unmarshaler = (*Int)(nil) ) // ToBig returns a big.Int version of z. // Return `nil` if z is nil func (z *Int) ToBig() *big.Int { if z == nil { return nil } var b *big.Int z.IntoBig(&b) return b } // IntoBig sets a provided big.Int to the value of z. // Sets `nil` if z is nil (thus the double pointer). func (z *Int) IntoBig(b **big.Int) { if z == nil { *b = nil return } if *b == nil { *b = new(big.Int) } switch maxWords { // Compile-time check. case 4: // 64-bit architectures. if words := (*b).Bits(); cap(words) >= 4 { // Enough underlying space to set all the uint256 data words = words[:4] words[0] = big.Word(z[0]) words[1] = big.Word(z[1]) words[2] = big.Word(z[2]) words[3] = big.Word(z[3]) // Feed it back to normalize (up or down within the big.Int) (*b).SetBits(words) } else { // Not enough space to set all the words, have to allocate words := [4]big.Word{big.Word(z[0]), big.Word(z[1]), big.Word(z[2]), big.Word(z[3])} (*b).SetBits(words[:]) } case 8: // 32-bit architectures. if words := (*b).Bits(); cap(words) >= 8 { // Enough underlying space to set all the uint256 data words = words[:8] words[0], words[1] = big.Word(z[0]), big.Word(z[0]>>32) words[2], words[3] = big.Word(z[1]), big.Word(z[1]>>32) words[4], words[5] = big.Word(z[2]), big.Word(z[2]>>32) words[6], words[7] = big.Word(z[3]), big.Word(z[3]>>32) // Feed it back to normalize (up or down within the big.Int) (*b).SetBits(words) } else { // Not enough space to set all the words, have to allocate words := [8]big.Word{ big.Word(z[0]), big.Word(z[0] >> 32), big.Word(z[1]), big.Word(z[1] >> 32), big.Word(z[2]), big.Word(z[2] >> 32), big.Word(z[3]), big.Word(z[3] >> 32), } (*b).SetBits(words[:]) } } } // FromBig is a convenience-constructor from big.Int. // Returns a new Int and whether overflow occurred. // OBS: If b is `nil`, this method returns `nil, false` func FromBig(b *big.Int) (*Int, bool) { if b == nil { return nil, false } z := &Int{} overflow := z.SetFromBig(b) return z, overflow } // MustFromBig is a convenience-constructor from big.Int. // Returns a new Int and panics if overflow occurred. // OBS: If b is `nil`, this method does _not_ panic, but // instead returns `nil` func MustFromBig(b *big.Int) *Int { if b == nil { return nil } z := &Int{} if z.SetFromBig(b) { panic("overflow") } return z } // Float64 returns the float64 value nearest to x. // // Note: The `big.Float` version of `Float64` also returns an 'Accuracy', indicating // whether the value was too small or too large to be represented by a // `float64`. However, the `uint256` type is unable to represent values // out of scope (|x| < math.SmallestNonzeroFloat64 or |x| > math.MaxFloat64), // therefore this method does not return any accuracy. func (z *Int) Float64() float64 { if z.IsUint64() { return float64(z.Uint64()) } // See [1] for a detailed walkthrough of IEEE 754 conversion // // 1: https://www.wikihow.com/Convert-a-Number-from-Decimal-to-IEEE-754-Floating-Point-Representation bitlen := uint64(z.BitLen()) // Normalize the number, by shifting it so that the MSB is shifted out. y := new(Int).Lsh(z, uint(1+256-bitlen)) // The number with the leading 1 shifted out is the fraction. fraction := y[3] // The exp is calculated from the number of shifts, adjusted with the bias. // double-precision uses 1023 as bias biased_exp := 1023 + bitlen - 1 // The IEEE 754 double-precision layout is as follows: // 1 sign bit (we don't bother with this, since it's always zero for uints) // 11 exponent bits // 52 fraction bits // -------- // 64 bits return math.Float64frombits(biased_exp<<52 | fraction>>12) } // SetFromHex sets z from the given string, interpreted as a hexadecimal number. // OBS! This method is _not_ strictly identical to the (*big.Int).SetString(..., 16) method. // Notable differences: // - This method _require_ "0x" or "0X" prefix. // - This method does not accept zero-prefixed hex, e.g. "0x0001" // - This method does not accept underscore input, e.g. "100_000", // - This method does not accept negative zero as valid, e.g "-0x0", // - (this method does not accept any negative input as valid) func (z *Int) SetFromHex(hex string) error { return z.fromHex(hex) } // fromHex is the internal implementation of parsing a hex-string. func (z *Int) fromHex(hex string) error { if err := checkNumberS(hex); err != nil { return err } if len(hex) > 66 { return ErrBig256Range } z.Clear() end := len(hex) for i := 0; i < 4; i++ { start := end - 16 if start < 2 { start = 2 } for ri := start; ri < end; ri++ { nib := bintable[hex[ri]] if nib == badNibble { return ErrSyntax } z[i] = z[i] << 4 z[i] += uint64(nib) } end = start } return nil } // FromHex is a convenience-constructor to create an Int from // a hexadecimal string. The string is required to be '0x'-prefixed // Numbers larger than 256 bits are not accepted. func FromHex(hex string) (*Int, error) { var z Int if err := z.fromHex(hex); err != nil { return nil, err } return &z, nil } // MustFromHex is a convenience-constructor to create an Int from // a hexadecimal string. // Returns a new Int and panics if any error occurred. func MustFromHex(hex string) *Int { var z Int if err := z.fromHex(hex); err != nil { panic(err) } return &z } // UnmarshalText implements encoding.TextUnmarshaler. This method // can unmarshal either hexadecimal or decimal. // - For hexadecimal, the input _must_ be prefixed with 0x or 0X func (z *Int) UnmarshalText(input []byte) error { if len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') { return z.fromHex(string(input)) } return z.SetFromDecimal(string(input)) } // SetFromBig converts a big.Int to Int and sets the value to z. // TODO: Ensure we have sufficient testing, esp for negative bigints. func (z *Int) SetFromBig(b *big.Int) bool { z.Clear() words := b.Bits() overflow := len(words) > maxWords switch maxWords { // Compile-time check. case 4: // 64-bit architectures. if len(words) > 0 { z[0] = uint64(words[0]) if len(words) > 1 { z[1] = uint64(words[1]) if len(words) > 2 { z[2] = uint64(words[2]) if len(words) > 3 { z[3] = uint64(words[3]) } } } } case 8: // 32-bit architectures. numWords := len(words) if overflow { numWords = maxWords } for i := 0; i < numWords; i++ { if i%2 == 0 { z[i/2] = uint64(words[i]) } else { z[i/2] |= uint64(words[i]) << 32 } } } if b.Sign() == -1 { z.Neg(z) } return overflow } // Format implements fmt.Formatter. It accepts the formats // 'b' (binary), 'o' (octal with 0 prefix), 'O' (octal with 0o prefix), // 'd' (decimal), 'x' (lowercase hexadecimal), and // 'X' (uppercase hexadecimal). // Also supported are the full suite of package fmt's format // flags for integral types, including '+' and ' ' for sign // control, '#' for leading zero in octal and for hexadecimal, // a leading "0x" or "0X" for "%#x" and "%#X" respectively, // specification of minimum digits precision, output field // width, space or zero padding, and '-' for left or right // justification. func (z *Int) Format(s fmt.State, ch rune) { z.ToBig().Format(s, ch) } // SetBytes8 is identical to SetBytes(in[:8]), but panics is input is too short func (z *Int) SetBytes8(in []byte) *Int { _ = in[7] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2], z[1] = 0, 0, 0 z[0] = binary.BigEndian.Uint64(in[0:8]) return z } // SetBytes16 is identical to SetBytes(in[:16]), but panics is input is too short func (z *Int) SetBytes16(in []byte) *Int { _ = in[15] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2] = 0, 0 z[1] = binary.BigEndian.Uint64(in[0:8]) z[0] = binary.BigEndian.Uint64(in[8:16]) return z } // SetBytes16 is identical to SetBytes(in[:24]), but panics is input is too short func (z *Int) SetBytes24(in []byte) *Int { _ = in[23] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = 0 z[2] = binary.BigEndian.Uint64(in[0:8]) z[1] = binary.BigEndian.Uint64(in[8:16]) z[0] = binary.BigEndian.Uint64(in[16:24]) return z } func (z *Int) SetBytes32(in []byte) *Int { _ = in[31] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = binary.BigEndian.Uint64(in[0:8]) z[2] = binary.BigEndian.Uint64(in[8:16]) z[1] = binary.BigEndian.Uint64(in[16:24]) z[0] = binary.BigEndian.Uint64(in[24:32]) return z } func (z *Int) SetBytes1(in []byte) *Int { z[3], z[2], z[1] = 0, 0, 0 z[0] = uint64(in[0]) return z } func (z *Int) SetBytes9(in []byte) *Int { _ = in[8] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2] = 0, 0 z[1] = uint64(in[0]) z[0] = binary.BigEndian.Uint64(in[1:9]) return z } func (z *Int) SetBytes17(in []byte) *Int { _ = in[16] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = 0 z[2] = uint64(in[0]) z[1] = binary.BigEndian.Uint64(in[1:9]) z[0] = binary.BigEndian.Uint64(in[9:17]) return z } func (z *Int) SetBytes25(in []byte) *Int { _ = in[24] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = uint64(in[0]) z[2] = binary.BigEndian.Uint64(in[1:9]) z[1] = binary.BigEndian.Uint64(in[9:17]) z[0] = binary.BigEndian.Uint64(in[17:25]) return z } func (z *Int) SetBytes2(in []byte) *Int { _ = in[1] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2], z[1] = 0, 0, 0 z[0] = uint64(binary.BigEndian.Uint16(in[0:2])) return z } func (z *Int) SetBytes10(in []byte) *Int { _ = in[9] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2] = 0, 0 z[1] = uint64(binary.BigEndian.Uint16(in[0:2])) z[0] = binary.BigEndian.Uint64(in[2:10]) return z } func (z *Int) SetBytes18(in []byte) *Int { _ = in[17] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = 0 z[2] = uint64(binary.BigEndian.Uint16(in[0:2])) z[1] = binary.BigEndian.Uint64(in[2:10]) z[0] = binary.BigEndian.Uint64(in[10:18]) return z } func (z *Int) SetBytes26(in []byte) *Int { _ = in[25] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = uint64(binary.BigEndian.Uint16(in[0:2])) z[2] = binary.BigEndian.Uint64(in[2:10]) z[1] = binary.BigEndian.Uint64(in[10:18]) z[0] = binary.BigEndian.Uint64(in[18:26]) return z } func (z *Int) SetBytes3(in []byte) *Int { _ = in[2] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2], z[1] = 0, 0, 0 z[0] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16 return z } func (z *Int) SetBytes11(in []byte) *Int { _ = in[10] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2] = 0, 0 z[1] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16 z[0] = binary.BigEndian.Uint64(in[3:11]) return z } func (z *Int) SetBytes19(in []byte) *Int { _ = in[18] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = 0 z[2] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16 z[1] = binary.BigEndian.Uint64(in[3:11]) z[0] = binary.BigEndian.Uint64(in[11:19]) return z } func (z *Int) SetBytes27(in []byte) *Int { _ = in[26] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16 z[2] = binary.BigEndian.Uint64(in[3:11]) z[1] = binary.BigEndian.Uint64(in[11:19]) z[0] = binary.BigEndian.Uint64(in[19:27]) return z } func (z *Int) SetBytes4(in []byte) *Int { _ = in[3] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2], z[1] = 0, 0, 0 z[0] = uint64(binary.BigEndian.Uint32(in[0:4])) return z } func (z *Int) SetBytes12(in []byte) *Int { _ = in[11] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2] = 0, 0 z[1] = uint64(binary.BigEndian.Uint32(in[0:4])) z[0] = binary.BigEndian.Uint64(in[4:12]) return z } func (z *Int) SetBytes20(in []byte) *Int { _ = in[19] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = 0 z[2] = uint64(binary.BigEndian.Uint32(in[0:4])) z[1] = binary.BigEndian.Uint64(in[4:12]) z[0] = binary.BigEndian.Uint64(in[12:20]) return z } func (z *Int) SetBytes28(in []byte) *Int { _ = in[27] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = uint64(binary.BigEndian.Uint32(in[0:4])) z[2] = binary.BigEndian.Uint64(in[4:12]) z[1] = binary.BigEndian.Uint64(in[12:20]) z[0] = binary.BigEndian.Uint64(in[20:28]) return z } func (z *Int) SetBytes5(in []byte) *Int { _ = in[4] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2], z[1] = 0, 0, 0 z[0] = bigEndianUint40(in[0:5]) return z } func (z *Int) SetBytes13(in []byte) *Int { _ = in[12] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2] = 0, 0 z[1] = bigEndianUint40(in[0:5]) z[0] = binary.BigEndian.Uint64(in[5:13]) return z } func (z *Int) SetBytes21(in []byte) *Int { _ = in[20] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = 0 z[2] = bigEndianUint40(in[0:5]) z[1] = binary.BigEndian.Uint64(in[5:13]) z[0] = binary.BigEndian.Uint64(in[13:21]) return z } func (z *Int) SetBytes29(in []byte) *Int { _ = in[28] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = bigEndianUint40(in[0:5]) z[2] = binary.BigEndian.Uint64(in[5:13]) z[1] = binary.BigEndian.Uint64(in[13:21]) z[0] = binary.BigEndian.Uint64(in[21:29]) return z } func (z *Int) SetBytes6(in []byte) *Int { _ = in[5] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2], z[1] = 0, 0, 0 z[0] = bigEndianUint48(in[0:6]) return z } func (z *Int) SetBytes14(in []byte) *Int { _ = in[13] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2] = 0, 0 z[1] = bigEndianUint48(in[0:6]) z[0] = binary.BigEndian.Uint64(in[6:14]) return z } func (z *Int) SetBytes22(in []byte) *Int { _ = in[21] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = 0 z[2] = bigEndianUint48(in[0:6]) z[1] = binary.BigEndian.Uint64(in[6:14]) z[0] = binary.BigEndian.Uint64(in[14:22]) return z } func (z *Int) SetBytes30(in []byte) *Int { _ = in[29] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = bigEndianUint48(in[0:6]) z[2] = binary.BigEndian.Uint64(in[6:14]) z[1] = binary.BigEndian.Uint64(in[14:22]) z[0] = binary.BigEndian.Uint64(in[22:30]) return z } func (z *Int) SetBytes7(in []byte) *Int { _ = in[6] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2], z[1] = 0, 0, 0 z[0] = bigEndianUint56(in[0:7]) return z } func (z *Int) SetBytes15(in []byte) *Int { _ = in[14] // bounds check hint to compiler; see golang.org/issue/14808 z[3], z[2] = 0, 0 z[1] = bigEndianUint56(in[0:7]) z[0] = binary.BigEndian.Uint64(in[7:15]) return z } func (z *Int) SetBytes23(in []byte) *Int { _ = in[22] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = 0 z[2] = bigEndianUint56(in[0:7]) z[1] = binary.BigEndian.Uint64(in[7:15]) z[0] = binary.BigEndian.Uint64(in[15:23]) return z } func (z *Int) SetBytes31(in []byte) *Int { _ = in[30] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = bigEndianUint56(in[0:7]) z[2] = binary.BigEndian.Uint64(in[7:15]) z[1] = binary.BigEndian.Uint64(in[15:23]) z[0] = binary.BigEndian.Uint64(in[23:31]) return z } // Utility methods that are "missing" among the bigEndian.UintXX methods. func bigEndianUint40(b []byte) uint64 { _ = b[4] // bounds check hint to compiler; see golang.org/issue/14808 return uint64(b[4]) | uint64(b[3])<<8 | uint64(b[2])<<16 | uint64(b[1])<<24 | uint64(b[0])<<32 } func bigEndianUint48(b []byte) uint64 { _ = b[5] // bounds check hint to compiler; see golang.org/issue/14808 return uint64(b[5]) | uint64(b[4])<<8 | uint64(b[3])<<16 | uint64(b[2])<<24 | uint64(b[1])<<32 | uint64(b[0])<<40 } func bigEndianUint56(b []byte) uint64 { _ = b[6] // bounds check hint to compiler; see golang.org/issue/14808 return uint64(b[6]) | uint64(b[5])<<8 | uint64(b[4])<<16 | uint64(b[3])<<24 | uint64(b[2])<<32 | uint64(b[1])<<40 | uint64(b[0])<<48 } // MarshalSSZAppend _almost_ implements the fastssz.Marshaler (see below) interface. // Originally, this method was named `MarshalSSZTo`, and ostensibly implemented the interface. // However, it was noted (https://github.com/holiman/uint256/issues/170) that the // actual implementation did not match the intended semantics of the interface: it // inserted the data instead of appending. // // Therefore, the `MarshalSSZTo` has been removed: to force users into making a choice: // - Use `MarshalSSZAppend`: this is the method that appends to the destination buffer, // and returns a potentially newly allocated buffer. This method will become `MarshalSSZTo` // in some future release. // - Or use `MarshalSSZInto`: this is the original method which places the data into // the destination buffer, without ever reallocating. // // fastssz.Marshaler interface: // // https://github.com/ferranbt/fastssz/blob/main/interface.go#L4 // type Marshaler interface { // MarshalSSZTo(dst []byte) ([]byte, error) // MarshalSSZ() ([]byte, error) // SizeSSZ() int // } func (z *Int) MarshalSSZAppend(dst []byte) ([]byte, error) { dst = binary.LittleEndian.AppendUint64(dst, z[0]) dst = binary.LittleEndian.AppendUint64(dst, z[1]) dst = binary.LittleEndian.AppendUint64(dst, z[2]) dst = binary.LittleEndian.AppendUint64(dst, z[3]) return dst, nil } // MarshalSSZInto is the first attempt to implement the fastssz.Marshaler interface, // but which does not obey the intended semantics. See MarshalSSZAppend and // - https://github.com/holiman/uint256/pull/171 // - https://github.com/holiman/uint256/issues/170 // @deprecated func (z *Int) MarshalSSZInto(dst []byte) ([]byte, error) { if len(dst) < 32 { return nil, fmt.Errorf("%w: have %d, want %d bytes", ErrBadBufferLength, len(dst), 32) } binary.LittleEndian.PutUint64(dst[0:8], z[0]) binary.LittleEndian.PutUint64(dst[8:16], z[1]) binary.LittleEndian.PutUint64(dst[16:24], z[2]) binary.LittleEndian.PutUint64(dst[24:32], z[3]) return dst[32:], nil } // MarshalSSZ implements the fastssz.Marshaler interface and returns the integer // marshalled into a newly allocated byte slice. func (z *Int) MarshalSSZ() ([]byte, error) { blob, _ := z.MarshalSSZAppend(make([]byte, 0, 32)) // ignore error, cannot fail, surely have 32 byte space in blob return blob, nil } // SizeSSZ implements the fastssz.Marshaler interface and returns the byte size // of the 256 bit int. func (*Int) SizeSSZ() int { return 32 } // UnmarshalSSZ implements the fastssz.Unmarshaler interface and parses an encoded // integer into the local struct. func (z *Int) UnmarshalSSZ(buf []byte) error { if len(buf) != 32 { return fmt.Errorf("%w: have %d, want %d bytes", ErrBadEncodedLength, len(buf), 32) } z[0] = binary.LittleEndian.Uint64(buf[0:8]) z[1] = binary.LittleEndian.Uint64(buf[8:16]) z[2] = binary.LittleEndian.Uint64(buf[16:24]) z[3] = binary.LittleEndian.Uint64(buf[24:32]) return nil } // HashTreeRoot implements the fastssz.HashRoot interface's non-dependent part. func (z *Int) HashTreeRoot() ([32]byte, error) { b, _ := z.MarshalSSZAppend(make([]byte, 0, 32)) // ignore error, cannot fail var hash [32]byte copy(hash[:], b) return hash, nil } // EncodeRLP implements the rlp.Encoder interface from go-ethereum // and writes the RLP encoding of z to w. func (z *Int) EncodeRLP(w io.Writer) error { if z == nil { _, err := w.Write([]byte{0x80}) return err } nBits := z.BitLen() if nBits == 0 { _, err := w.Write([]byte{0x80}) return err } if nBits <= 7 { _, err := w.Write([]byte{byte(z[0])}) return err } nBytes := byte((nBits + 7) / 8) var b [33]byte binary.BigEndian.PutUint64(b[1:9], z[3]) binary.BigEndian.PutUint64(b[9:17], z[2]) binary.BigEndian.PutUint64(b[17:25], z[1]) binary.BigEndian.PutUint64(b[25:33], z[0]) b[32-nBytes] = 0x80 + nBytes _, err := w.Write(b[32-nBytes:]) return err } // MarshalText implements encoding.TextMarshaler // MarshalText marshals using the decimal representation (compatible with big.Int) func (z *Int) MarshalText() ([]byte, error) { return []byte(z.Dec()), nil } // MarshalJSON implements json.Marshaler. // MarshalJSON marshals using the 'decimal string' representation. This is _not_ compatible // with big.Int: big.Int marshals into JSON 'native' numeric format. // // The JSON native format is, on some platforms, (e.g. javascript), limited to 53-bit large // integer space. Thus, U256 uses string-format, which is not compatible with // big.int (big.Int refuses to unmarshal a string representation). func (z *Int) MarshalJSON() ([]byte, error) { return []byte(`"` + z.Dec() + `"`), nil } // UnmarshalJSON implements json.Unmarshaler. UnmarshalJSON accepts either // - Quoted string: either hexadecimal OR decimal // - Not quoted string: only decimal func (z *Int) UnmarshalJSON(input []byte) error { if len(input) < 2 || input[0] != '"' || input[len(input)-1] != '"' { // if not quoted, it must be decimal return z.SetFromDecimal(string(input)) } return z.UnmarshalText(input[1 : len(input)-1]) } // String returns the decimal encoding of b. func (z *Int) String() string { return z.Dec() } const ( hextable = "0123456789abcdef" bintable = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x01\x02\x03\x04\x05\x06\a\b\t\xff\xff\xff\xff\xff\xff\xff\n\v\f\r\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\n\v\f\r\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" badNibble = 0xff ) // Hex encodes z in 0x-prefixed hexadecimal form. func (z *Int) Hex() string { // This implementation is not optimal, it allocates a full // 66-byte output buffer which it fills. It could instead allocate a smaller // buffer, and omit the final crop-stage. output := make([]byte, 66) nibbles := (z.BitLen() + 3) / 4 // nibbles [0,64] if nibbles == 0 { nibbles = 1 } // Start with the most significant zWord := (nibbles - 1) / 16 for i := zWord; i >= 0; i-- { off := (3 - i) * 16 output[off+2] = hextable[byte(z[i]>>60)&0xf] output[off+3] = hextable[byte(z[i]>>56)&0xf] output[off+4] = hextable[byte(z[i]>>52)&0xf] output[off+5] = hextable[byte(z[i]>>48)&0xf] output[off+6] = hextable[byte(z[i]>>44)&0xf] output[off+7] = hextable[byte(z[i]>>40)&0xf] output[off+8] = hextable[byte(z[i]>>36)&0xf] output[off+9] = hextable[byte(z[i]>>32)&0xf] output[off+10] = hextable[byte(z[i]>>28)&0xf] output[off+11] = hextable[byte(z[i]>>24)&0xf] output[off+12] = hextable[byte(z[i]>>20)&0xf] output[off+13] = hextable[byte(z[i]>>16)&0xf] output[off+14] = hextable[byte(z[i]>>12)&0xf] output[off+15] = hextable[byte(z[i]>>8)&0xf] output[off+16] = hextable[byte(z[i]>>4)&0xf] output[off+17] = hextable[byte(z[i]&0xF)&0xf] } output[64-nibbles] = '0' output[65-nibbles] = 'x' return string(output[64-nibbles:]) } // Scan implements the database/sql Scanner interface. // It decodes a string, because that is what postgres uses for its numeric type func (dst *Int) Scan(src interface{}) error { if src == nil { dst.Clear() return nil } switch src := src.(type) { case string: return dst.scanScientificFromString(src) case []byte: return dst.scanScientificFromString(string(src)) } return errors.New("unsupported type") } func (dst *Int) scanScientificFromString(src string) error { if len(src) == 0 { dst.Clear() return nil } idx := strings.IndexByte(src, 'e') if idx == -1 { return dst.SetFromDecimal(src) } if err := dst.SetFromDecimal(src[:idx]); err != nil { return err } if src[(idx+1):] == "0" { return nil } exp := new(Int) if err := exp.SetFromDecimal(src[(idx + 1):]); err != nil { return err } if exp.GtUint64(77) { // 10**78 is larger than 2**256 return ErrBig256Range } exp.Exp(NewInt(10), exp) if _, overflow := dst.MulOverflow(dst, exp); overflow { return ErrBig256Range } return nil } // Value implements the database/sql/driver Valuer interface. // It encodes a base 10 string. // In Postgres, this will work with both integer and the Numeric/Decimal types // In MariaDB/MySQL, this will work with the Numeric/Decimal types up to 65 digits, however any more and you should use either VarChar or Char(79) // In SqLite, use TEXT func (src *Int) Value() (driver.Value, error) { return src.Dec(), nil } var ( ErrEmptyString = errors.New("empty hex string") ErrSyntax = errors.New("invalid hex string") ErrMissingPrefix = errors.New("hex string without 0x prefix") ErrEmptyNumber = errors.New("hex string \"0x\"") ErrLeadingZero = errors.New("hex number with leading zero digits") ErrBig256Range = errors.New("hex number > 256 bits") ErrBadBufferLength = errors.New("bad ssz buffer length") ErrBadEncodedLength = errors.New("bad ssz encoded length") ) func checkNumberS(input string) error { l := len(input) if l == 0 { return ErrEmptyString } if l < 2 || input[0] != '0' || (input[1] != 'x' && input[1] != 'X') { return ErrMissingPrefix } if l == 2 { return ErrEmptyNumber } if len(input) > 3 && input[2] == '0' { return ErrLeadingZero } return nil } uint256-1.3.2/conversion_fuzz_test.go000066400000000000000000000020631472460254700175760ustar00rootroot00000000000000package uint256 import ( "fmt" "math/big" "testing" ) func testSetFromDecForFuzzing(tc string) error { a := new(Int).SetAllOne() err := a.SetFromDecimal(tc) // If input is negative, we should eror if len(tc) > 0 && tc[0] == '-' { if err == nil { return fmt.Errorf("want error on negative input") } return nil } // Need to compare with big.Int bigA, ok := big.NewInt(0).SetString(tc, 10) if !ok { if err == nil { return fmt.Errorf("want error") } return nil // both agree that input is bad } if bigA.BitLen() > 256 { if err == nil { return fmt.Errorf("want error (bitlen > 256)") } return nil } want := bigA.String() have := a.Dec() if want != have { return fmt.Errorf("want %v, have %v", want, have) } if _, err := a.Value(); err != nil { return fmt.Errorf("fail to Value() %s, got err %s", tc, err) } return nil } func FuzzSetString(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { if len(data) > 512 { return } if err := testSetFromDecForFuzzing(string(data)); err != nil { t.Fatal(err) } }) } uint256-1.3.2/conversion_test.go000066400000000000000000002274271472460254700165350ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "bufio" "bytes" "encoding/json" "errors" "fmt" "math/big" "testing" ) var ( _ fmt.Formatter = &Int{} // Test if Int supports Formatter interface. ) func TestFromBig(t *testing.T) { var a *big.Int b, o := FromBig(a) if o { t.Fatalf("nil conversion overflowed! big.Int %x", b) } if b != nil { t.Fatalf("got %x, exp %v", b, nil) } b2 := MustFromBig(a) if b2 != nil { t.Fatalf("got %x, exp %v", b2, nil) } a = new(big.Int) b, o = FromBig(a) if o { t.Fatalf("conversion overflowed! big.Int %x", a.Bytes()) } if exp, got := a.Bytes(), b.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } b2 = MustFromBig(a) if exp, got := a.Bytes(), b2.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } a = big.NewInt(1) b, o = FromBig(a) if o { t.Fatalf("conversion overflowed! big.Int %x", a.Bytes()) } if exp, got := a.Bytes(), b.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } b2 = MustFromBig(a) if exp, got := a.Bytes(), b2.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } a = big.NewInt(0x1000000000000000) b, o = FromBig(a) if o { t.Fatalf("conversion overflowed! big.Int %x", a.Bytes()) } if exp, got := a.Bytes(), b.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } b2 = MustFromBig(a) if exp, got := a.Bytes(), b2.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } a = big.NewInt(0x1234) b, o = FromBig(a) if o { t.Fatalf("conversion overflowed! big.Int %x", a.Bytes()) } if exp, got := a.Bytes(), b.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } b2 = MustFromBig(a) if exp, got := a.Bytes(), b2.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } a = big.NewInt(1) a.Lsh(a, 256) b, o = FromBig(a) if !o { t.Fatalf("expected overflow") } if !b.Eq(new(Int)) { t.Fatalf("got %x exp 0", b.Bytes()) } if !causesPanic(func() { MustFromBig(a) }) { t.Fatalf("expected overflow") } a.Sub(a, big.NewInt(1)) b, o = FromBig(a) if o { t.Fatalf("conversion overflowed! big.Int %x", a.Bytes()) } if exp, got := a.Bytes(), b.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } b2 = MustFromBig(a) if exp, got := a.Bytes(), b2.Bytes(); !bytes.Equal(got, exp) { t.Fatalf("got %x exp %x", got, exp) } } func TestScanScientific(t *testing.T) { intsub1 := new(Int) _ = intsub1.fromDecimal(twoPow256Sub1) cases := []struct { in string exp *Int err string }{ { in: "", exp: new(Int), }, { in: "e30", err: "EOF", }, { in: "30e", err: "EOF", }, { in: twoPow256Sub1 + "e", err: "EOF", }, { in: "14e30", exp: new(Int).Mul(NewInt(14), new(Int).Exp(NewInt(10), NewInt(30))), }, { // 0xdd15fe86affad800000000000000000000000000000000000000000000000000 in: "1e77", exp: new(Int).Mul(NewInt(1), new(Int).Exp(NewInt(10), NewInt(77))), }, { // 0x8a2dbf142dfcc8000000000000000000000000000000000000000000000000000 in: "1e78", err: ErrBig256Range.Error(), }, { in: "1455522523e31", exp: new(Int).Mul(NewInt(1455522523), new(Int).Exp(NewInt(10), NewInt(31))), }, { in: twoPow256Sub1 + "e0", exp: intsub1, }, { in: "1e25352", err: ErrBig256Range.Error(), }, { in: "1213128763127863781263781263781263781263781263871263871268371268371263781627836128736128736127836127836127863781e0", err: ErrBig256Range.Error(), }, { in: twoPow256Sub1 + "e1", err: ErrBig256Range.Error(), }, { in: "1e253e52", err: `strconv.ParseUint: parsing "253e52": invalid syntax`, }, { in: "1e00000000000000000", exp: NewInt(1), }, } for tc, v := range cases { have := "" i := new(Int) if err := i.Scan(v.in); err != nil { have = err.Error() } if want := v.err; have != want { t.Fatalf("test %d: wrong error, have '%s', want '%s'", tc, have, want) } if len(v.err) > 0 { continue } if !v.exp.Eq(i) { t.Fatalf("test %d: got %#x exp %#x", tc, i, v.exp) } } } func TestFromBigOverflow(t *testing.T) { // Test overflow with error returns b := new(big.Int).SetBytes(hex2Bytes("ababee444444444444ffcc333333333333ddaa222222222222bb8811111111111199")) _, o := FromBig(b) if !o { t.Errorf("expected overflow, got %v", o) } // Test overflow with panic (recovery is a bit unwieldy) if !causesPanic(func() { MustFromBig(b) }) { t.Fatalf("expected overflow") } // Test no overflow b = new(big.Int).SetBytes(hex2Bytes("ee444444444444ffcc333333333333ddaa222222222222bb8811111111111199")) _, o = FromBig(b) if o { t.Errorf("expected no overflow, got %v", o) } MustFromBig(b) b = new(big.Int).SetBytes(hex2Bytes("ee444444444444ffcc333333333333ddaa222222222222bb8811111111111199")) b.Neg(b) _, o = FromBig(b) if o { t.Errorf("expected no overflow, got %v", o) } MustFromBig(b) } func TestToBig(t *testing.T) { var uint256Nil *Int if bigNil := uint256Nil.ToBig(); bigNil != nil { t.Errorf("want big.Int , have %x", bigNil) } if bigZero := new(Int).ToBig(); bigZero.Cmp(new(big.Int)) != 0 { t.Errorf("expected big.Int 0, got %x", bigZero) } for i := uint(0); i < 256; i++ { f := new(Int).SetUint64(1) f.Lsh(f, i) b := f.ToBig() expected := big.NewInt(1) expected.Lsh(expected, i) if b.Cmp(expected) != 0 { t.Fatalf("expected %x, got %x", expected, b) } } } func TestIntoBig(t *testing.T) { var uint256Nil *Int bigNil := new(big.Int) if uint256Nil.IntoBig(&bigNil); bigNil != nil { t.Errorf("want big.Int , have %x", bigNil) } var bigZero *big.Int if new(Int).IntoBig(&bigZero); bigZero.Cmp(new(big.Int)) != 0 { t.Errorf("expected big.Int 0, got %x", bigZero) } var b *big.Int for i := uint(0); i < 256; i++ { f := new(Int).SetUint64(1) f.Lsh(f, i) f.IntoBig(&b) expected := big.NewInt(1) expected.Lsh(expected, i) if b.Cmp(expected) != 0 { t.Fatalf("expected %x, got %x", expected, b) } } } func BenchmarkScanScientific(b *testing.B) { intsub1 := new(Int) _ = intsub1.fromDecimal(twoPow256Sub1) cases := []struct { in string exp *Int err string }{ { in: "14e30", exp: new(Int).Mul(NewInt(14), new(Int).Exp(NewInt(10), NewInt(30))), }, { in: "1455522523e31", exp: new(Int).Mul(NewInt(1455522523), new(Int).Exp(NewInt(10), NewInt(31))), }, { in: twoPow256Sub1 + "e0", exp: intsub1, }, { in: "1e00000000000000000", exp: NewInt(1), }, } i := new(Int) b.ResetTimer() for idx := 0; idx < b.N; idx++ { for _, v := range cases { _ = i.Scan(v.in) } } } func benchSetFromBig(bench *testing.B, b *big.Int) Int { var f Int for i := 0; i < bench.N; i++ { f.SetFromBig(b) } return f } func BenchmarkSetFromBig(bench *testing.B) { param1 := big.NewInt(0xff) bench.Run("1word", func(bench *testing.B) { benchSetFromBig(bench, param1) }) param2 := new(big.Int).Lsh(param1, 64) bench.Run("2words", func(bench *testing.B) { benchSetFromBig(bench, param2) }) param3 := new(big.Int).Lsh(param2, 64) bench.Run("3words", func(bench *testing.B) { benchSetFromBig(bench, param3) }) param4 := new(big.Int).Lsh(param3, 64) bench.Run("4words", func(bench *testing.B) { benchSetFromBig(bench, param4) }) param5 := new(big.Int).Lsh(param4, 64) bench.Run("overflow", func(bench *testing.B) { benchSetFromBig(bench, param5) }) } func benchToBig(bench *testing.B, f *Int) *big.Int { var b *big.Int for i := 0; i < bench.N; i++ { b = f.ToBig() } return b } func BenchmarkToBig(bench *testing.B) { param1 := new(Int).SetUint64(0xff) bench.Run("1word", func(bench *testing.B) { benchToBig(bench, param1) }) param2 := new(Int).Lsh(param1, 64) bench.Run("2words", func(bench *testing.B) { benchToBig(bench, param2) }) param3 := new(Int).Lsh(param2, 64) bench.Run("3words", func(bench *testing.B) { benchToBig(bench, param3) }) param4 := new(Int).Lsh(param3, 64) bench.Run("4words", func(bench *testing.B) { benchToBig(bench, param4) }) } func benchIntoBig(bench *testing.B, f *Int) *big.Int { var b *big.Int for i := 0; i < bench.N; i++ { f.IntoBig(&b) } return b } func BenchmarkIntoBig(bench *testing.B) { param1 := new(Int).SetUint64(0xff) bench.Run("1word", func(bench *testing.B) { benchIntoBig(bench, param1) }) param2 := new(Int).Lsh(param1, 64) bench.Run("2words", func(bench *testing.B) { benchIntoBig(bench, param2) }) param3 := new(Int).Lsh(param2, 64) bench.Run("3words", func(bench *testing.B) { benchIntoBig(bench, param3) }) param4 := new(Int).Lsh(param3, 64) bench.Run("4words", func(bench *testing.B) { benchIntoBig(bench, param4) }) } func TestFormat(t *testing.T) { testCases := []string{ "0", "1", "ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221100", } for i := 0; i < len(testCases); i++ { expected := testCases[i] b, _ := new(big.Int).SetString(expected, 16) f, o := FromBig(b) if o { t.Fatalf("too big test case %s", expected) } s := fmt.Sprintf("%x", f) if s != expected { t.Errorf("Invalid format conversion to hex: %s, expected %s", s, expected) } } } // TestSetBytes tests all setbyte-methods from 0 to overlong, // - verifies that all non-set bits are properly cleared // - verifies that overlong input is correctly cropped func TestSetBytes(t *testing.T) { for i := 0; i < 35; i++ { buf := hex2Bytes("aaaa12131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031bbbb") exp, _ := FromBig(new(big.Int).SetBytes(buf[0:i])) z := new(Int).SetAllOne().SetBytes(buf[0:i]) if !z.Eq(exp) { t.Errorf("testcase %d: exp %x, got %x", i, exp, z) } } // nil check exp, _ := FromBig(new(big.Int).SetBytes(nil)) z := new(Int).SetAllOne().SetBytes(nil) if !z.Eq(exp) { t.Errorf("nil-test : exp %x, got %x", exp, z) } } func BenchmarkSetBytes(b *testing.B) { val := new(Int) bytearr := hex2Bytes("12131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031") b.Run("generic", func(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { val.SetBytes(bytearr[:1]) val.SetBytes(bytearr[:2]) val.SetBytes(bytearr[:3]) val.SetBytes(bytearr[:4]) val.SetBytes(bytearr[:5]) val.SetBytes(bytearr[:6]) val.SetBytes(bytearr[:7]) val.SetBytes(bytearr[:8]) val.SetBytes(bytearr[:9]) val.SetBytes(bytearr[:10]) val.SetBytes(bytearr[:11]) val.SetBytes(bytearr[:12]) val.SetBytes(bytearr[:13]) val.SetBytes(bytearr[:14]) val.SetBytes(bytearr[:15]) val.SetBytes(bytearr[:16]) val.SetBytes(bytearr[:17]) val.SetBytes(bytearr[:18]) val.SetBytes(bytearr[:19]) val.SetBytes(bytearr[:20]) val.SetBytes(bytearr[:21]) val.SetBytes(bytearr[:22]) val.SetBytes(bytearr[:23]) val.SetBytes(bytearr[:24]) val.SetBytes(bytearr[:25]) val.SetBytes(bytearr[:26]) val.SetBytes(bytearr[:27]) val.SetBytes(bytearr[:28]) val.SetBytes(bytearr[:29]) val.SetBytes(bytearr[:30]) val.SetBytes(bytearr[:31]) val.SetBytes(bytearr[:32]) } }) b.Run("specific", func(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { val.SetBytes1(bytearr) val.SetBytes2(bytearr) val.SetBytes3(bytearr) val.SetBytes4(bytearr) val.SetBytes5(bytearr) val.SetBytes6(bytearr) val.SetBytes7(bytearr) val.SetBytes8(bytearr) val.SetBytes9(bytearr) val.SetBytes10(bytearr) val.SetBytes11(bytearr) val.SetBytes12(bytearr) val.SetBytes13(bytearr) val.SetBytes14(bytearr) val.SetBytes15(bytearr) val.SetBytes16(bytearr) val.SetBytes17(bytearr) val.SetBytes18(bytearr) val.SetBytes19(bytearr) val.SetBytes20(bytearr) val.SetBytes21(bytearr) val.SetBytes22(bytearr) val.SetBytes23(bytearr) val.SetBytes24(bytearr) val.SetBytes25(bytearr) val.SetBytes26(bytearr) val.SetBytes27(bytearr) val.SetBytes28(bytearr) val.SetBytes29(bytearr) val.SetBytes30(bytearr) val.SetBytes31(bytearr) val.SetBytes32(bytearr) } }) } func TestSSZEncodeDecodeHash(t *testing.T) { type testcase struct { val string exp string } for i, tt := range []testcase{ {"", "0000000000000000000000000000000000000000000000000000000000000000"}, {"01", "0100000000000000000000000000000000000000000000000000000000000000"}, {"02", "0200000000000000000000000000000000000000000000000000000000000000"}, {"04", "0400000000000000000000000000000000000000000000000000000000000000"}, {"08", "0800000000000000000000000000000000000000000000000000000000000000"}, {"10", "1000000000000000000000000000000000000000000000000000000000000000"}, {"20", "2000000000000000000000000000000000000000000000000000000000000000"}, {"40", "4000000000000000000000000000000000000000000000000000000000000000"}, {"80", "8000000000000000000000000000000000000000000000000000000000000000"}, {"0100", "0001000000000000000000000000000000000000000000000000000000000000"}, {"0200", "0002000000000000000000000000000000000000000000000000000000000000"}, {"0400", "0004000000000000000000000000000000000000000000000000000000000000"}, {"0800", "0008000000000000000000000000000000000000000000000000000000000000"}, {"1000", "0010000000000000000000000000000000000000000000000000000000000000"}, {"2000", "0020000000000000000000000000000000000000000000000000000000000000"}, {"4000", "0040000000000000000000000000000000000000000000000000000000000000"}, {"8000", "0080000000000000000000000000000000000000000000000000000000000000"}, {"010000", "0000010000000000000000000000000000000000000000000000000000000000"}, {"020000", "0000020000000000000000000000000000000000000000000000000000000000"}, {"040000", "0000040000000000000000000000000000000000000000000000000000000000"}, {"080000", "0000080000000000000000000000000000000000000000000000000000000000"}, {"100000", "0000100000000000000000000000000000000000000000000000000000000000"}, {"200000", "0000200000000000000000000000000000000000000000000000000000000000"}, {"400000", "0000400000000000000000000000000000000000000000000000000000000000"}, {"800000", "0000800000000000000000000000000000000000000000000000000000000000"}, {"01000000", "0000000100000000000000000000000000000000000000000000000000000000"}, {"02000000", "0000000200000000000000000000000000000000000000000000000000000000"}, {"04000000", "0000000400000000000000000000000000000000000000000000000000000000"}, {"08000000", "0000000800000000000000000000000000000000000000000000000000000000"}, {"10000000", "0000001000000000000000000000000000000000000000000000000000000000"}, {"20000000", "0000002000000000000000000000000000000000000000000000000000000000"}, {"40000000", "0000004000000000000000000000000000000000000000000000000000000000"}, {"80000000", "0000008000000000000000000000000000000000000000000000000000000000"}, {"0100000000", "0000000001000000000000000000000000000000000000000000000000000000"}, {"0200000000", "0000000002000000000000000000000000000000000000000000000000000000"}, {"0400000000", "0000000004000000000000000000000000000000000000000000000000000000"}, {"0800000000", "0000000008000000000000000000000000000000000000000000000000000000"}, {"1000000000", "0000000010000000000000000000000000000000000000000000000000000000"}, {"2000000000", "0000000020000000000000000000000000000000000000000000000000000000"}, {"4000000000", "0000000040000000000000000000000000000000000000000000000000000000"}, {"8000000000", "0000000080000000000000000000000000000000000000000000000000000000"}, {"010000000000", "0000000000010000000000000000000000000000000000000000000000000000"}, {"020000000000", "0000000000020000000000000000000000000000000000000000000000000000"}, {"040000000000", "0000000000040000000000000000000000000000000000000000000000000000"}, {"080000000000", "0000000000080000000000000000000000000000000000000000000000000000"}, {"100000000000", "0000000000100000000000000000000000000000000000000000000000000000"}, {"200000000000", "0000000000200000000000000000000000000000000000000000000000000000"}, {"400000000000", "0000000000400000000000000000000000000000000000000000000000000000"}, {"800000000000", "0000000000800000000000000000000000000000000000000000000000000000"}, {"01000000000000", "0000000000000100000000000000000000000000000000000000000000000000"}, {"02000000000000", "0000000000000200000000000000000000000000000000000000000000000000"}, {"04000000000000", "0000000000000400000000000000000000000000000000000000000000000000"}, {"08000000000000", "0000000000000800000000000000000000000000000000000000000000000000"}, {"10000000000000", "0000000000001000000000000000000000000000000000000000000000000000"}, {"20000000000000", "0000000000002000000000000000000000000000000000000000000000000000"}, {"40000000000000", "0000000000004000000000000000000000000000000000000000000000000000"}, {"80000000000000", "0000000000008000000000000000000000000000000000000000000000000000"}, {"0100000000000000", "0000000000000001000000000000000000000000000000000000000000000000"}, {"0200000000000000", "0000000000000002000000000000000000000000000000000000000000000000"}, {"0400000000000000", "0000000000000004000000000000000000000000000000000000000000000000"}, {"0800000000000000", "0000000000000008000000000000000000000000000000000000000000000000"}, {"1000000000000000", "0000000000000010000000000000000000000000000000000000000000000000"}, {"2000000000000000", "0000000000000020000000000000000000000000000000000000000000000000"}, {"4000000000000000", "0000000000000040000000000000000000000000000000000000000000000000"}, {"8000000000000000", "0000000000000080000000000000000000000000000000000000000000000000"}, {"010000000000000000", "0000000000000000010000000000000000000000000000000000000000000000"}, {"020000000000000000", "0000000000000000020000000000000000000000000000000000000000000000"}, {"040000000000000000", "0000000000000000040000000000000000000000000000000000000000000000"}, {"080000000000000000", "0000000000000000080000000000000000000000000000000000000000000000"}, {"100000000000000000", "0000000000000000100000000000000000000000000000000000000000000000"}, {"200000000000000000", "0000000000000000200000000000000000000000000000000000000000000000"}, {"400000000000000000", "0000000000000000400000000000000000000000000000000000000000000000"}, {"800000000000000000", "0000000000000000800000000000000000000000000000000000000000000000"}, {"01000000000000000000", "0000000000000000000100000000000000000000000000000000000000000000"}, {"02000000000000000000", "0000000000000000000200000000000000000000000000000000000000000000"}, {"04000000000000000000", "0000000000000000000400000000000000000000000000000000000000000000"}, {"08000000000000000000", "0000000000000000000800000000000000000000000000000000000000000000"}, {"10000000000000000000", "0000000000000000001000000000000000000000000000000000000000000000"}, {"20000000000000000000", "0000000000000000002000000000000000000000000000000000000000000000"}, {"40000000000000000000", "0000000000000000004000000000000000000000000000000000000000000000"}, {"80000000000000000000", "0000000000000000008000000000000000000000000000000000000000000000"}, {"0100000000000000000000", "0000000000000000000001000000000000000000000000000000000000000000"}, {"0200000000000000000000", "0000000000000000000002000000000000000000000000000000000000000000"}, {"0400000000000000000000", "0000000000000000000004000000000000000000000000000000000000000000"}, {"0800000000000000000000", "0000000000000000000008000000000000000000000000000000000000000000"}, {"1000000000000000000000", "0000000000000000000010000000000000000000000000000000000000000000"}, {"2000000000000000000000", "0000000000000000000020000000000000000000000000000000000000000000"}, {"4000000000000000000000", "0000000000000000000040000000000000000000000000000000000000000000"}, {"8000000000000000000000", "0000000000000000000080000000000000000000000000000000000000000000"}, {"010000000000000000000000", "0000000000000000000000010000000000000000000000000000000000000000"}, {"020000000000000000000000", "0000000000000000000000020000000000000000000000000000000000000000"}, {"040000000000000000000000", "0000000000000000000000040000000000000000000000000000000000000000"}, {"080000000000000000000000", "0000000000000000000000080000000000000000000000000000000000000000"}, {"100000000000000000000000", "0000000000000000000000100000000000000000000000000000000000000000"}, {"200000000000000000000000", "0000000000000000000000200000000000000000000000000000000000000000"}, {"400000000000000000000000", "0000000000000000000000400000000000000000000000000000000000000000"}, {"800000000000000000000000", "0000000000000000000000800000000000000000000000000000000000000000"}, {"01000000000000000000000000", "0000000000000000000000000100000000000000000000000000000000000000"}, {"02000000000000000000000000", "0000000000000000000000000200000000000000000000000000000000000000"}, {"04000000000000000000000000", "0000000000000000000000000400000000000000000000000000000000000000"}, {"08000000000000000000000000", "0000000000000000000000000800000000000000000000000000000000000000"}, {"10000000000000000000000000", "0000000000000000000000001000000000000000000000000000000000000000"}, {"20000000000000000000000000", "0000000000000000000000002000000000000000000000000000000000000000"}, {"40000000000000000000000000", "0000000000000000000000004000000000000000000000000000000000000000"}, {"80000000000000000000000000", "0000000000000000000000008000000000000000000000000000000000000000"}, {"0100000000000000000000000000", "0000000000000000000000000001000000000000000000000000000000000000"}, {"0200000000000000000000000000", "0000000000000000000000000002000000000000000000000000000000000000"}, {"0400000000000000000000000000", "0000000000000000000000000004000000000000000000000000000000000000"}, {"0800000000000000000000000000", "0000000000000000000000000008000000000000000000000000000000000000"}, {"1000000000000000000000000000", "0000000000000000000000000010000000000000000000000000000000000000"}, {"2000000000000000000000000000", "0000000000000000000000000020000000000000000000000000000000000000"}, {"4000000000000000000000000000", "0000000000000000000000000040000000000000000000000000000000000000"}, {"8000000000000000000000000000", "0000000000000000000000000080000000000000000000000000000000000000"}, {"010000000000000000000000000000", "0000000000000000000000000000010000000000000000000000000000000000"}, {"020000000000000000000000000000", "0000000000000000000000000000020000000000000000000000000000000000"}, {"040000000000000000000000000000", "0000000000000000000000000000040000000000000000000000000000000000"}, {"080000000000000000000000000000", "0000000000000000000000000000080000000000000000000000000000000000"}, {"100000000000000000000000000000", "0000000000000000000000000000100000000000000000000000000000000000"}, {"200000000000000000000000000000", "0000000000000000000000000000200000000000000000000000000000000000"}, {"400000000000000000000000000000", "0000000000000000000000000000400000000000000000000000000000000000"}, {"800000000000000000000000000000", "0000000000000000000000000000800000000000000000000000000000000000"}, {"01000000000000000000000000000000", "0000000000000000000000000000000100000000000000000000000000000000"}, {"02000000000000000000000000000000", "0000000000000000000000000000000200000000000000000000000000000000"}, {"04000000000000000000000000000000", "0000000000000000000000000000000400000000000000000000000000000000"}, {"08000000000000000000000000000000", "0000000000000000000000000000000800000000000000000000000000000000"}, {"10000000000000000000000000000000", "0000000000000000000000000000001000000000000000000000000000000000"}, {"20000000000000000000000000000000", "0000000000000000000000000000002000000000000000000000000000000000"}, {"40000000000000000000000000000000", "0000000000000000000000000000004000000000000000000000000000000000"}, {"80000000000000000000000000000000", "0000000000000000000000000000008000000000000000000000000000000000"}, {"0100000000000000000000000000000000", "0000000000000000000000000000000001000000000000000000000000000000"}, {"0200000000000000000000000000000000", "0000000000000000000000000000000002000000000000000000000000000000"}, {"0400000000000000000000000000000000", "0000000000000000000000000000000004000000000000000000000000000000"}, {"0800000000000000000000000000000000", "0000000000000000000000000000000008000000000000000000000000000000"}, {"1000000000000000000000000000000000", "0000000000000000000000000000000010000000000000000000000000000000"}, {"2000000000000000000000000000000000", "0000000000000000000000000000000020000000000000000000000000000000"}, {"4000000000000000000000000000000000", "0000000000000000000000000000000040000000000000000000000000000000"}, {"8000000000000000000000000000000000", "0000000000000000000000000000000080000000000000000000000000000000"}, {"010000000000000000000000000000000000", "0000000000000000000000000000000000010000000000000000000000000000"}, {"020000000000000000000000000000000000", "0000000000000000000000000000000000020000000000000000000000000000"}, {"040000000000000000000000000000000000", "0000000000000000000000000000000000040000000000000000000000000000"}, {"080000000000000000000000000000000000", "0000000000000000000000000000000000080000000000000000000000000000"}, {"100000000000000000000000000000000000", "0000000000000000000000000000000000100000000000000000000000000000"}, {"200000000000000000000000000000000000", "0000000000000000000000000000000000200000000000000000000000000000"}, {"400000000000000000000000000000000000", "0000000000000000000000000000000000400000000000000000000000000000"}, {"800000000000000000000000000000000000", "0000000000000000000000000000000000800000000000000000000000000000"}, {"01000000000000000000000000000000000000", "0000000000000000000000000000000000000100000000000000000000000000"}, {"02000000000000000000000000000000000000", "0000000000000000000000000000000000000200000000000000000000000000"}, {"04000000000000000000000000000000000000", "0000000000000000000000000000000000000400000000000000000000000000"}, {"08000000000000000000000000000000000000", "0000000000000000000000000000000000000800000000000000000000000000"}, {"10000000000000000000000000000000000000", "0000000000000000000000000000000000001000000000000000000000000000"}, {"20000000000000000000000000000000000000", "0000000000000000000000000000000000002000000000000000000000000000"}, {"40000000000000000000000000000000000000", "0000000000000000000000000000000000004000000000000000000000000000"}, {"80000000000000000000000000000000000000", "0000000000000000000000000000000000008000000000000000000000000000"}, {"0100000000000000000000000000000000000000", "0000000000000000000000000000000000000001000000000000000000000000"}, {"0200000000000000000000000000000000000000", "0000000000000000000000000000000000000002000000000000000000000000"}, {"0400000000000000000000000000000000000000", "0000000000000000000000000000000000000004000000000000000000000000"}, {"0800000000000000000000000000000000000000", "0000000000000000000000000000000000000008000000000000000000000000"}, {"1000000000000000000000000000000000000000", "0000000000000000000000000000000000000010000000000000000000000000"}, {"2000000000000000000000000000000000000000", "0000000000000000000000000000000000000020000000000000000000000000"}, {"4000000000000000000000000000000000000000", "0000000000000000000000000000000000000040000000000000000000000000"}, {"8000000000000000000000000000000000000000", "0000000000000000000000000000000000000080000000000000000000000000"}, {"010000000000000000000000000000000000000000", "0000000000000000000000000000000000000000010000000000000000000000"}, {"020000000000000000000000000000000000000000", "0000000000000000000000000000000000000000020000000000000000000000"}, {"040000000000000000000000000000000000000000", "0000000000000000000000000000000000000000040000000000000000000000"}, {"080000000000000000000000000000000000000000", "0000000000000000000000000000000000000000080000000000000000000000"}, {"100000000000000000000000000000000000000000", "0000000000000000000000000000000000000000100000000000000000000000"}, {"200000000000000000000000000000000000000000", "0000000000000000000000000000000000000000200000000000000000000000"}, {"400000000000000000000000000000000000000000", "0000000000000000000000000000000000000000400000000000000000000000"}, {"800000000000000000000000000000000000000000", "0000000000000000000000000000000000000000800000000000000000000000"}, {"01000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000100000000000000000000"}, {"02000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000200000000000000000000"}, {"04000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000400000000000000000000"}, {"08000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000800000000000000000000"}, {"10000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000001000000000000000000000"}, {"20000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000002000000000000000000000"}, {"40000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000004000000000000000000000"}, {"80000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000008000000000000000000000"}, {"0100000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000001000000000000000000"}, {"0200000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000002000000000000000000"}, {"0400000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000004000000000000000000"}, {"0800000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000008000000000000000000"}, {"1000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000010000000000000000000"}, {"2000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000020000000000000000000"}, {"4000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000040000000000000000000"}, {"8000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000080000000000000000000"}, {"010000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000010000000000000000"}, {"020000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000020000000000000000"}, {"040000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000040000000000000000"}, {"080000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000080000000000000000"}, {"100000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000100000000000000000"}, {"200000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000200000000000000000"}, {"400000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000400000000000000000"}, {"800000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000800000000000000000"}, {"01000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000100000000000000"}, {"02000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000200000000000000"}, {"04000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000400000000000000"}, {"08000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000800000000000000"}, {"10000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000001000000000000000"}, {"20000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000002000000000000000"}, {"40000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000004000000000000000"}, {"80000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000008000000000000000"}, {"0100000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000001000000000000"}, {"0200000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000002000000000000"}, {"0400000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000004000000000000"}, {"0800000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000008000000000000"}, {"1000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000010000000000000"}, {"2000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000020000000000000"}, {"4000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000040000000000000"}, {"8000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000080000000000000"}, {"010000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000010000000000"}, {"020000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000020000000000"}, {"040000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000040000000000"}, {"080000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000080000000000"}, {"100000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000100000000000"}, {"200000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000200000000000"}, {"400000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000400000000000"}, {"800000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000800000000000"}, {"01000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000100000000"}, {"02000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000200000000"}, {"04000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000400000000"}, {"08000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000800000000"}, {"10000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000001000000000"}, {"20000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000002000000000"}, {"40000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000004000000000"}, {"80000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000008000000000"}, {"0100000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000001000000"}, {"0200000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000002000000"}, {"0400000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000004000000"}, {"0800000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000008000000"}, {"1000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000010000000"}, {"2000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000020000000"}, {"4000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000040000000"}, {"8000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000080000000"}, {"010000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000010000"}, {"020000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000020000"}, {"040000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000040000"}, {"080000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000080000"}, {"100000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000100000"}, {"200000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000200000"}, {"400000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000400000"}, {"800000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000800000"}, {"01000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000100"}, {"02000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000200"}, {"04000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000400"}, {"08000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000800"}, {"10000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000001000"}, {"20000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000002000"}, {"40000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000004000"}, {"80000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000008000"}, {"0100000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000001"}, {"0200000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000002"}, {"0400000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000004"}, {"0800000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000008"}, {"1000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000010"}, {"2000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000020"}, {"4000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000040"}, {"8000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000080"}, } { z := new(Int).SetBytes(hex2Bytes(tt.val)) if s := z.SizeSSZ(); s != 32 { t.Errorf("testcase %d, size got: %d, exp: %d", i, s, 32) } b, err := z.MarshalSSZ() if err != nil { t.Fatal(err) } if exp := hex2Bytes(tt.exp); !bytes.Equal(b, exp) { t.Errorf("testcase %d, encoding\nhave: %x\nwant: %x\n", i, b, exp) } z2 := new(Int) if err := z2.UnmarshalSSZ(b); err != nil { t.Fatal(err) } if !z2.Eq(z) { t.Errorf("testcase %d, decoding got:\n%v\nexp:%v\n", i, z2, z) } r, err := z.HashTreeRoot() if err != nil { t.Fatal(err) } if exp := hex2Bytes(tt.exp); !bytes.Equal(r[:], exp) { t.Errorf("testcase %d, hashing\nhave: %x\nwant: %x\n", i, r, exp) } } } func TestSSZEncodeDecodeErrors(t *testing.T) { small := make([]byte, 31) if _, err := new(Int).MarshalSSZInto(small); !errors.Is(err, ErrBadBufferLength) { t.Fatalf("overflow marshal error mismatch: have %v, want %v", err, ErrBadBufferLength) } if err := new(Int).UnmarshalSSZ(small); !errors.Is(err, ErrBadEncodedLength) { t.Fatalf("underflow unmarshal error mismatch: have %v, want %v", err, ErrBadEncodedLength) } large := make([]byte, 33) if _, err := new(Int).MarshalSSZAppend(large); err != nil { t.Fatalf("underflow marshal error mismatch: have %v, want %v", err, nil) } if err := new(Int).UnmarshalSSZ(large); !errors.Is(err, ErrBadEncodedLength) { t.Fatalf("overflow unmarshal error mismatch: have %v, want %v", err, ErrBadEncodedLength) } if _, err := new(Int).MarshalSSZInto(large); err != nil { t.Fatalf("unexpected error: %v", err) } } func TestRLPEncode(t *testing.T) { type testcase struct { val string exp string } for i, tt := range []testcase{ {"", "80"}, {"01", "01"}, {"02", "02"}, {"04", "04"}, {"08", "08"}, {"10", "10"}, {"20", "20"}, {"40", "40"}, {"80", "8180"}, {"0100", "820100"}, {"0200", "820200"}, {"0400", "820400"}, {"0800", "820800"}, {"1000", "821000"}, {"2000", "822000"}, {"4000", "824000"}, {"8000", "828000"}, {"010000", "83010000"}, {"020000", "83020000"}, {"040000", "83040000"}, {"080000", "83080000"}, {"100000", "83100000"}, {"200000", "83200000"}, {"400000", "83400000"}, {"800000", "83800000"}, {"01000000", "8401000000"}, {"02000000", "8402000000"}, {"04000000", "8404000000"}, {"08000000", "8408000000"}, {"10000000", "8410000000"}, {"20000000", "8420000000"}, {"40000000", "8440000000"}, {"80000000", "8480000000"}, {"0100000000", "850100000000"}, {"0200000000", "850200000000"}, {"0400000000", "850400000000"}, {"0800000000", "850800000000"}, {"1000000000", "851000000000"}, {"2000000000", "852000000000"}, {"4000000000", "854000000000"}, {"8000000000", "858000000000"}, {"010000000000", "86010000000000"}, {"020000000000", "86020000000000"}, {"040000000000", "86040000000000"}, {"080000000000", "86080000000000"}, {"100000000000", "86100000000000"}, {"200000000000", "86200000000000"}, {"400000000000", "86400000000000"}, {"800000000000", "86800000000000"}, {"01000000000000", "8701000000000000"}, {"02000000000000", "8702000000000000"}, {"04000000000000", "8704000000000000"}, {"08000000000000", "8708000000000000"}, {"10000000000000", "8710000000000000"}, {"20000000000000", "8720000000000000"}, {"40000000000000", "8740000000000000"}, {"80000000000000", "8780000000000000"}, {"0100000000000000", "880100000000000000"}, {"0200000000000000", "880200000000000000"}, {"0400000000000000", "880400000000000000"}, {"0800000000000000", "880800000000000000"}, {"1000000000000000", "881000000000000000"}, {"2000000000000000", "882000000000000000"}, {"4000000000000000", "884000000000000000"}, {"8000000000000000", "888000000000000000"}, {"010000000000000000", "89010000000000000000"}, {"020000000000000000", "89020000000000000000"}, {"040000000000000000", "89040000000000000000"}, {"080000000000000000", "89080000000000000000"}, {"100000000000000000", "89100000000000000000"}, {"200000000000000000", "89200000000000000000"}, {"400000000000000000", "89400000000000000000"}, {"800000000000000000", "89800000000000000000"}, {"01000000000000000000", "8a01000000000000000000"}, {"02000000000000000000", "8a02000000000000000000"}, {"04000000000000000000", "8a04000000000000000000"}, {"08000000000000000000", "8a08000000000000000000"}, {"10000000000000000000", "8a10000000000000000000"}, {"20000000000000000000", "8a20000000000000000000"}, {"40000000000000000000", "8a40000000000000000000"}, {"80000000000000000000", "8a80000000000000000000"}, {"0100000000000000000000", "8b0100000000000000000000"}, {"0200000000000000000000", "8b0200000000000000000000"}, {"0400000000000000000000", "8b0400000000000000000000"}, {"0800000000000000000000", "8b0800000000000000000000"}, {"1000000000000000000000", "8b1000000000000000000000"}, {"2000000000000000000000", "8b2000000000000000000000"}, {"4000000000000000000000", "8b4000000000000000000000"}, {"8000000000000000000000", "8b8000000000000000000000"}, {"010000000000000000000000", "8c010000000000000000000000"}, {"020000000000000000000000", "8c020000000000000000000000"}, {"040000000000000000000000", "8c040000000000000000000000"}, {"080000000000000000000000", "8c080000000000000000000000"}, {"100000000000000000000000", "8c100000000000000000000000"}, {"200000000000000000000000", "8c200000000000000000000000"}, {"400000000000000000000000", "8c400000000000000000000000"}, {"800000000000000000000000", "8c800000000000000000000000"}, {"01000000000000000000000000", "8d01000000000000000000000000"}, {"02000000000000000000000000", "8d02000000000000000000000000"}, {"04000000000000000000000000", "8d04000000000000000000000000"}, {"08000000000000000000000000", "8d08000000000000000000000000"}, {"10000000000000000000000000", "8d10000000000000000000000000"}, {"20000000000000000000000000", "8d20000000000000000000000000"}, {"40000000000000000000000000", "8d40000000000000000000000000"}, {"80000000000000000000000000", "8d80000000000000000000000000"}, {"0100000000000000000000000000", "8e0100000000000000000000000000"}, {"0200000000000000000000000000", "8e0200000000000000000000000000"}, {"0400000000000000000000000000", "8e0400000000000000000000000000"}, {"0800000000000000000000000000", "8e0800000000000000000000000000"}, {"1000000000000000000000000000", "8e1000000000000000000000000000"}, {"2000000000000000000000000000", "8e2000000000000000000000000000"}, {"4000000000000000000000000000", "8e4000000000000000000000000000"}, {"8000000000000000000000000000", "8e8000000000000000000000000000"}, {"010000000000000000000000000000", "8f010000000000000000000000000000"}, {"020000000000000000000000000000", "8f020000000000000000000000000000"}, {"040000000000000000000000000000", "8f040000000000000000000000000000"}, {"080000000000000000000000000000", "8f080000000000000000000000000000"}, {"100000000000000000000000000000", "8f100000000000000000000000000000"}, {"200000000000000000000000000000", "8f200000000000000000000000000000"}, {"400000000000000000000000000000", "8f400000000000000000000000000000"}, {"800000000000000000000000000000", "8f800000000000000000000000000000"}, {"01000000000000000000000000000000", "9001000000000000000000000000000000"}, {"02000000000000000000000000000000", "9002000000000000000000000000000000"}, {"04000000000000000000000000000000", "9004000000000000000000000000000000"}, {"08000000000000000000000000000000", "9008000000000000000000000000000000"}, {"10000000000000000000000000000000", "9010000000000000000000000000000000"}, {"20000000000000000000000000000000", "9020000000000000000000000000000000"}, {"40000000000000000000000000000000", "9040000000000000000000000000000000"}, {"80000000000000000000000000000000", "9080000000000000000000000000000000"}, {"0100000000000000000000000000000000", "910100000000000000000000000000000000"}, {"0200000000000000000000000000000000", "910200000000000000000000000000000000"}, {"0400000000000000000000000000000000", "910400000000000000000000000000000000"}, {"0800000000000000000000000000000000", "910800000000000000000000000000000000"}, {"1000000000000000000000000000000000", "911000000000000000000000000000000000"}, {"2000000000000000000000000000000000", "912000000000000000000000000000000000"}, {"4000000000000000000000000000000000", "914000000000000000000000000000000000"}, {"8000000000000000000000000000000000", "918000000000000000000000000000000000"}, {"010000000000000000000000000000000000", "92010000000000000000000000000000000000"}, {"020000000000000000000000000000000000", "92020000000000000000000000000000000000"}, {"040000000000000000000000000000000000", "92040000000000000000000000000000000000"}, {"080000000000000000000000000000000000", "92080000000000000000000000000000000000"}, {"100000000000000000000000000000000000", "92100000000000000000000000000000000000"}, {"200000000000000000000000000000000000", "92200000000000000000000000000000000000"}, {"400000000000000000000000000000000000", "92400000000000000000000000000000000000"}, {"800000000000000000000000000000000000", "92800000000000000000000000000000000000"}, {"01000000000000000000000000000000000000", "9301000000000000000000000000000000000000"}, {"02000000000000000000000000000000000000", "9302000000000000000000000000000000000000"}, {"04000000000000000000000000000000000000", "9304000000000000000000000000000000000000"}, {"08000000000000000000000000000000000000", "9308000000000000000000000000000000000000"}, {"10000000000000000000000000000000000000", "9310000000000000000000000000000000000000"}, {"20000000000000000000000000000000000000", "9320000000000000000000000000000000000000"}, {"40000000000000000000000000000000000000", "9340000000000000000000000000000000000000"}, {"80000000000000000000000000000000000000", "9380000000000000000000000000000000000000"}, {"0100000000000000000000000000000000000000", "940100000000000000000000000000000000000000"}, {"0200000000000000000000000000000000000000", "940200000000000000000000000000000000000000"}, {"0400000000000000000000000000000000000000", "940400000000000000000000000000000000000000"}, {"0800000000000000000000000000000000000000", "940800000000000000000000000000000000000000"}, {"1000000000000000000000000000000000000000", "941000000000000000000000000000000000000000"}, {"2000000000000000000000000000000000000000", "942000000000000000000000000000000000000000"}, {"4000000000000000000000000000000000000000", "944000000000000000000000000000000000000000"}, {"8000000000000000000000000000000000000000", "948000000000000000000000000000000000000000"}, {"010000000000000000000000000000000000000000", "95010000000000000000000000000000000000000000"}, {"020000000000000000000000000000000000000000", "95020000000000000000000000000000000000000000"}, {"040000000000000000000000000000000000000000", "95040000000000000000000000000000000000000000"}, {"080000000000000000000000000000000000000000", "95080000000000000000000000000000000000000000"}, {"100000000000000000000000000000000000000000", "95100000000000000000000000000000000000000000"}, {"200000000000000000000000000000000000000000", "95200000000000000000000000000000000000000000"}, {"400000000000000000000000000000000000000000", "95400000000000000000000000000000000000000000"}, {"800000000000000000000000000000000000000000", "95800000000000000000000000000000000000000000"}, {"01000000000000000000000000000000000000000000", "9601000000000000000000000000000000000000000000"}, {"02000000000000000000000000000000000000000000", "9602000000000000000000000000000000000000000000"}, {"04000000000000000000000000000000000000000000", "9604000000000000000000000000000000000000000000"}, {"08000000000000000000000000000000000000000000", "9608000000000000000000000000000000000000000000"}, {"10000000000000000000000000000000000000000000", "9610000000000000000000000000000000000000000000"}, {"20000000000000000000000000000000000000000000", "9620000000000000000000000000000000000000000000"}, {"40000000000000000000000000000000000000000000", "9640000000000000000000000000000000000000000000"}, {"80000000000000000000000000000000000000000000", "9680000000000000000000000000000000000000000000"}, {"0100000000000000000000000000000000000000000000", "970100000000000000000000000000000000000000000000"}, {"0200000000000000000000000000000000000000000000", "970200000000000000000000000000000000000000000000"}, {"0400000000000000000000000000000000000000000000", "970400000000000000000000000000000000000000000000"}, {"0800000000000000000000000000000000000000000000", "970800000000000000000000000000000000000000000000"}, {"1000000000000000000000000000000000000000000000", "971000000000000000000000000000000000000000000000"}, {"2000000000000000000000000000000000000000000000", "972000000000000000000000000000000000000000000000"}, {"4000000000000000000000000000000000000000000000", "974000000000000000000000000000000000000000000000"}, {"8000000000000000000000000000000000000000000000", "978000000000000000000000000000000000000000000000"}, {"010000000000000000000000000000000000000000000000", "98010000000000000000000000000000000000000000000000"}, {"020000000000000000000000000000000000000000000000", "98020000000000000000000000000000000000000000000000"}, {"040000000000000000000000000000000000000000000000", "98040000000000000000000000000000000000000000000000"}, {"080000000000000000000000000000000000000000000000", "98080000000000000000000000000000000000000000000000"}, {"100000000000000000000000000000000000000000000000", "98100000000000000000000000000000000000000000000000"}, {"200000000000000000000000000000000000000000000000", "98200000000000000000000000000000000000000000000000"}, {"400000000000000000000000000000000000000000000000", "98400000000000000000000000000000000000000000000000"}, {"800000000000000000000000000000000000000000000000", "98800000000000000000000000000000000000000000000000"}, {"01000000000000000000000000000000000000000000000000", "9901000000000000000000000000000000000000000000000000"}, {"02000000000000000000000000000000000000000000000000", "9902000000000000000000000000000000000000000000000000"}, {"04000000000000000000000000000000000000000000000000", "9904000000000000000000000000000000000000000000000000"}, {"08000000000000000000000000000000000000000000000000", "9908000000000000000000000000000000000000000000000000"}, {"10000000000000000000000000000000000000000000000000", "9910000000000000000000000000000000000000000000000000"}, {"20000000000000000000000000000000000000000000000000", "9920000000000000000000000000000000000000000000000000"}, {"40000000000000000000000000000000000000000000000000", "9940000000000000000000000000000000000000000000000000"}, {"80000000000000000000000000000000000000000000000000", "9980000000000000000000000000000000000000000000000000"}, {"0100000000000000000000000000000000000000000000000000", "9a0100000000000000000000000000000000000000000000000000"}, {"0200000000000000000000000000000000000000000000000000", "9a0200000000000000000000000000000000000000000000000000"}, {"0400000000000000000000000000000000000000000000000000", "9a0400000000000000000000000000000000000000000000000000"}, {"0800000000000000000000000000000000000000000000000000", "9a0800000000000000000000000000000000000000000000000000"}, {"1000000000000000000000000000000000000000000000000000", "9a1000000000000000000000000000000000000000000000000000"}, {"2000000000000000000000000000000000000000000000000000", "9a2000000000000000000000000000000000000000000000000000"}, {"4000000000000000000000000000000000000000000000000000", "9a4000000000000000000000000000000000000000000000000000"}, {"8000000000000000000000000000000000000000000000000000", "9a8000000000000000000000000000000000000000000000000000"}, {"010000000000000000000000000000000000000000000000000000", "9b010000000000000000000000000000000000000000000000000000"}, {"020000000000000000000000000000000000000000000000000000", "9b020000000000000000000000000000000000000000000000000000"}, {"040000000000000000000000000000000000000000000000000000", "9b040000000000000000000000000000000000000000000000000000"}, {"080000000000000000000000000000000000000000000000000000", "9b080000000000000000000000000000000000000000000000000000"}, {"100000000000000000000000000000000000000000000000000000", "9b100000000000000000000000000000000000000000000000000000"}, {"200000000000000000000000000000000000000000000000000000", "9b200000000000000000000000000000000000000000000000000000"}, {"400000000000000000000000000000000000000000000000000000", "9b400000000000000000000000000000000000000000000000000000"}, {"800000000000000000000000000000000000000000000000000000", "9b800000000000000000000000000000000000000000000000000000"}, {"01000000000000000000000000000000000000000000000000000000", "9c01000000000000000000000000000000000000000000000000000000"}, {"02000000000000000000000000000000000000000000000000000000", "9c02000000000000000000000000000000000000000000000000000000"}, {"04000000000000000000000000000000000000000000000000000000", "9c04000000000000000000000000000000000000000000000000000000"}, {"08000000000000000000000000000000000000000000000000000000", "9c08000000000000000000000000000000000000000000000000000000"}, {"10000000000000000000000000000000000000000000000000000000", "9c10000000000000000000000000000000000000000000000000000000"}, {"20000000000000000000000000000000000000000000000000000000", "9c20000000000000000000000000000000000000000000000000000000"}, {"40000000000000000000000000000000000000000000000000000000", "9c40000000000000000000000000000000000000000000000000000000"}, {"80000000000000000000000000000000000000000000000000000000", "9c80000000000000000000000000000000000000000000000000000000"}, {"0100000000000000000000000000000000000000000000000000000000", "9d0100000000000000000000000000000000000000000000000000000000"}, {"0200000000000000000000000000000000000000000000000000000000", "9d0200000000000000000000000000000000000000000000000000000000"}, {"0400000000000000000000000000000000000000000000000000000000", "9d0400000000000000000000000000000000000000000000000000000000"}, {"0800000000000000000000000000000000000000000000000000000000", "9d0800000000000000000000000000000000000000000000000000000000"}, {"1000000000000000000000000000000000000000000000000000000000", "9d1000000000000000000000000000000000000000000000000000000000"}, {"2000000000000000000000000000000000000000000000000000000000", "9d2000000000000000000000000000000000000000000000000000000000"}, {"4000000000000000000000000000000000000000000000000000000000", "9d4000000000000000000000000000000000000000000000000000000000"}, {"8000000000000000000000000000000000000000000000000000000000", "9d8000000000000000000000000000000000000000000000000000000000"}, {"010000000000000000000000000000000000000000000000000000000000", "9e010000000000000000000000000000000000000000000000000000000000"}, {"020000000000000000000000000000000000000000000000000000000000", "9e020000000000000000000000000000000000000000000000000000000000"}, {"040000000000000000000000000000000000000000000000000000000000", "9e040000000000000000000000000000000000000000000000000000000000"}, {"080000000000000000000000000000000000000000000000000000000000", "9e080000000000000000000000000000000000000000000000000000000000"}, {"100000000000000000000000000000000000000000000000000000000000", "9e100000000000000000000000000000000000000000000000000000000000"}, {"200000000000000000000000000000000000000000000000000000000000", "9e200000000000000000000000000000000000000000000000000000000000"}, {"400000000000000000000000000000000000000000000000000000000000", "9e400000000000000000000000000000000000000000000000000000000000"}, {"800000000000000000000000000000000000000000000000000000000000", "9e800000000000000000000000000000000000000000000000000000000000"}, {"01000000000000000000000000000000000000000000000000000000000000", "9f01000000000000000000000000000000000000000000000000000000000000"}, {"02000000000000000000000000000000000000000000000000000000000000", "9f02000000000000000000000000000000000000000000000000000000000000"}, {"04000000000000000000000000000000000000000000000000000000000000", "9f04000000000000000000000000000000000000000000000000000000000000"}, {"08000000000000000000000000000000000000000000000000000000000000", "9f08000000000000000000000000000000000000000000000000000000000000"}, {"10000000000000000000000000000000000000000000000000000000000000", "9f10000000000000000000000000000000000000000000000000000000000000"}, {"20000000000000000000000000000000000000000000000000000000000000", "9f20000000000000000000000000000000000000000000000000000000000000"}, {"40000000000000000000000000000000000000000000000000000000000000", "9f40000000000000000000000000000000000000000000000000000000000000"}, {"80000000000000000000000000000000000000000000000000000000000000", "9f80000000000000000000000000000000000000000000000000000000000000"}, {"0100000000000000000000000000000000000000000000000000000000000000", "a00100000000000000000000000000000000000000000000000000000000000000"}, {"0200000000000000000000000000000000000000000000000000000000000000", "a00200000000000000000000000000000000000000000000000000000000000000"}, {"0400000000000000000000000000000000000000000000000000000000000000", "a00400000000000000000000000000000000000000000000000000000000000000"}, {"0800000000000000000000000000000000000000000000000000000000000000", "a00800000000000000000000000000000000000000000000000000000000000000"}, {"1000000000000000000000000000000000000000000000000000000000000000", "a01000000000000000000000000000000000000000000000000000000000000000"}, {"2000000000000000000000000000000000000000000000000000000000000000", "a02000000000000000000000000000000000000000000000000000000000000000"}, {"4000000000000000000000000000000000000000000000000000000000000000", "a04000000000000000000000000000000000000000000000000000000000000000"}, {"8000000000000000000000000000000000000000000000000000000000000000", "a08000000000000000000000000000000000000000000000000000000000000000"}, } { z := new(Int).SetBytes(hex2Bytes(tt.val)) var b bytes.Buffer w := bufio.NewWriter(&b) if err := z.EncodeRLP(w); err != nil { t.Fatal(err) } w.Flush() if got, exp := b.Bytes(), hex2Bytes(tt.exp); !bytes.Equal(got, exp) { t.Fatalf("testcase %d got:\n%x\nexp:%x\n", i, got, exp) } } // And test nil { var z *Int var b bytes.Buffer w := bufio.NewWriter(&b) if err := z.EncodeRLP(w); err != nil { t.Fatal(err) } w.Flush() if got, exp := b.Bytes(), hex2Bytes("80"); !bytes.Equal(got, exp) { t.Fatalf("nil-test got:\n%x\nexp:%x\n", got, exp) } } } type nilWriter struct{} func (*nilWriter) Write(p []byte) (n int, err error) { return len(p), nil } // BenchmarkRLPEncoding writes 255 Ints ranging in bitsize from 0-255 in each op func BenchmarkRLPEncoding(b *testing.B) { z := new(Int) devnull := &nilWriter{} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { z.SetUint64(1) for bit := 0; bit < 255; bit++ { _ = z.EncodeRLP(devnull) z.Lsh(z, 1) } } } func referenceBig(s string) *big.Int { b, ok := new(big.Int).SetString(s, 16) if !ok { panic("invalid") } return b } type marshalTest struct { input interface{} want string } type unmarshalTest struct { input string want interface{} wantErr error // if set, decoding must fail on any platform } var ( encodeBigTests = []marshalTest{ {referenceBig("0"), "0x0"}, {referenceBig("1"), "0x1"}, {referenceBig("ff"), "0xff"}, {referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"}, {referenceBig("80a7f2c1bcc396c00"), "0x80a7f2c1bcc396c00"}, } decodeBigTests = []unmarshalTest{ // invalid {input: ``, wantErr: ErrEmptyString}, {input: `0`, wantErr: ErrMissingPrefix}, {input: `0x`, wantErr: ErrEmptyNumber}, {input: `0x01`, wantErr: ErrLeadingZero}, {input: `0xx`, wantErr: ErrSyntax}, {input: `0x1zz01`, wantErr: ErrSyntax}, { input: `0x10000000000000000000000000000000000000000000000000000000000000000`, wantErr: ErrBig256Range, }, // valid {input: `0x0`, want: big.NewInt(0)}, {input: `0x2`, want: big.NewInt(0x2)}, {input: `0x2F2`, want: big.NewInt(0x2f2)}, {input: `0X2F2`, want: big.NewInt(0x2f2)}, {input: `0x1122aaff`, want: big.NewInt(0x1122aaff)}, {input: `0xbBb`, want: big.NewInt(0xbbb)}, {input: `0xfffffffff`, want: big.NewInt(0xfffffffff)}, { input: `0x112233445566778899aabbccddeeff`, want: referenceBig("112233445566778899aabbccddeeff"), }, { input: `0xffffffffffffffffffffffffffffffffffff`, want: referenceBig("ffffffffffffffffffffffffffffffffffff"), }, { input: `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`, want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), }, } ) func checkError(t *testing.T, input string, got, want error) bool { if got == nil { if want != nil { t.Errorf("input %s: got no error, want %q", input, want) return false } return true } if want == nil { t.Errorf("input %s: unexpected error %q", input, got) } else if got.Error() != want.Error() { t.Errorf("input %s: got error %q, want %q", input, got, want) } return false } func TestEncode(t *testing.T) { for _, test := range encodeBigTests { z, _ := FromBig(test.input.(*big.Int)) enc := z.Hex() if enc != test.want { t.Errorf("input %x: wrong encoding %s (exp %s)", test.input, enc, test.want) } } } // causesPanic returns true if panic occurred when executing fn. func causesPanic(fn func()) bool { done := make(chan struct{}) var ok bool go func() { defer func() { ok = recover() != nil done <- struct{}{} }() fn() }() <-done return ok } func TestDecode(t *testing.T) { for _, test := range decodeBigTests { dec, err := FromHex(test.input) if err != nil { if !causesPanic(func() { MustFromHex(test.input) }) { t.Fatalf("expected panic") } } if !checkError(t, test.input, err, test.wantErr) { continue } b := dec.ToBig() if b.Cmp(test.want.(*big.Int)) != 0 { t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) continue } d2 := MustFromHex(test.input) if !d2.Eq(dec) { t.Errorf("input %s: value mismatch: got %x, want %x", test.input, d2, dec) } } // Some remaining json-tests type jsonStruct struct { Foo *Int } var jsonDecoded jsonStruct // This test was previously an "expected error", The U256 behaviour has now // changed, to be compatible with big.Int if err := json.Unmarshal([]byte(`{"Foo":1}`), &jsonDecoded); err != nil { t.Fatalf("Expected no error, have %v", err) } if err := json.Unmarshal([]byte(`{"Foo":0x1}`), &jsonDecoded); err == nil { t.Fatal("Expected error") } if err := json.Unmarshal([]byte(`{"Foo":""}`), &jsonDecoded); err == nil { t.Fatal("Expected error") } if err := json.Unmarshal([]byte(`{"Foo":"0x1"}`), &jsonDecoded); err != nil { t.Fatalf("Expected no error, got %v", err) } else if jsonDecoded.Foo.Uint64() != 1 { t.Fatal("Expected 1") } } func TestEnDecode(t *testing.T) { type jsonStruct struct { Foo *Int } type jsonBigStruct struct { Foo *big.Int } var testSample = func(i int, bigSample big.Int, intSample Int) { // Encoding wantHex := fmt.Sprintf("0x%s", bigSample.Text(16)) wantDec := bigSample.Text(10) if have, want := intSample.Hex(), fmt.Sprintf("0x%s", bigSample.Text(16)); have != want { t.Fatalf("test %d #1, have %v, want %v", i, have, want) } if have, want := intSample.String(), bigSample.String(); have != want { t.Fatalf("test %d String(), have %v, want %v", i, have, want) } { have, _ := intSample.MarshalText() want, _ := bigSample.MarshalText() if !bytes.Equal(have, want) { t.Fatalf("test %d MarshalText, have %q, want %q", i, have, want) } } { have, _ := intSample.MarshalJSON() want := []byte(fmt.Sprintf(`"%s"`, bigSample.Text(10))) if !bytes.Equal(have, want) { t.Fatalf("test %d MarshalJSON, have %q, want %q", i, have, want) } } if have, _ := intSample.Value(); wantDec != have.(string) { t.Fatalf("test %d #4, got %v, exp %v", i, have, wantHex) } if have, want := intSample.Dec(), wantDec; have != want { t.Fatalf("test %d Dec(), have %v, want %v", i, have, want) } { // Json jsonEncoded, err := json.Marshal(&jsonStruct{&intSample}) if err != nil { t.Fatalf("test %d: json encoding err: %v", i, err) } jsonEncodedBig, _ := json.Marshal(&jsonBigStruct{&bigSample}) var jsonDecoded jsonStruct err = json.Unmarshal(jsonEncoded, &jsonDecoded) if err != nil { t.Fatalf("test %d error unmarshaling: %v", i, err) } if jsonDecoded.Foo.Cmp(&intSample) != 0 { t.Fatalf("test %d #8, have %v, want %v", i, jsonDecoded.Foo, intSample) } // See if we can also unmarshal from big.Int's non-string format err = json.Unmarshal(jsonEncodedBig, &jsonDecoded) if err != nil { t.Fatalf("test %d unmarshalling from big.Int err: %v", i, err) } if jsonDecoded.Foo.Cmp(&intSample) != 0 { t.Fatalf("test %d have %v, want %v", i, jsonDecoded.Foo, intSample) } } // Decoding // // FromHex decoded, err := FromHex(wantHex) { if err != nil { t.Fatalf("test %d #9, err: %v", i, err) } if decoded.Cmp(&intSample) != 0 { t.Fatalf("test %d #10, got %v, exp %v", i, decoded, intSample) } } // z.SetFromHex err = decoded.SetFromHex(wantHex) { if err != nil { t.Fatalf("test %d #11, err: %v", i, err) } if decoded.Cmp(&intSample) != 0 { t.Fatalf("test %d #12, got %v, exp %v", i, decoded, intSample) } } // UnmarshalText decoded = new(Int) { if err := decoded.UnmarshalText([]byte(wantHex)); err != nil { t.Fatalf("test %d #13, err: %v", i, err) } if decoded.Cmp(&intSample) != 0 { t.Fatalf("test %d #14, got %v, exp %v", i, decoded, intSample) } } // FromDecimal decoded, err = FromDecimal(wantDec) { if err != nil { t.Fatalf("test %d #15, err: %v", i, err) } if decoded.Cmp(&intSample) != 0 { t.Fatalf("test %d #16, got %v, exp %v", i, decoded, intSample) } } // Scan w string err = decoded.Scan(wantDec) { if err != nil { t.Fatalf("test %d #17, err: %v", i, err) } if decoded.Cmp(&intSample) != 0 { t.Fatalf("test %d #18, got %v, exp %v", i, decoded, intSample) } } // Scan w byte slice err = decoded.Scan([]byte(wantDec)) { if err != nil { t.Fatalf("test %d #19, err: %v", i, err) } if decoded.Cmp(&intSample) != 0 { t.Fatalf("test %d #20, got %v, exp %v", i, decoded, intSample) } } // Scan with neither string nor byte err = decoded.Scan(5) { if err == nil { t.Fatalf("test %d #21, want error", i) } } } for i, bigSample := range big256Samples { intSample := int256Samples[i] testSample(i, bigSample, intSample) } for i, bigSample := range big256SamplesLt { intSample := int256SamplesLt[i] testSample(i, bigSample, intSample) } } func TestMarshallingErrors(t *testing.T) { var check = func(repr string) string { a := new(Int) if err := json.Unmarshal([]byte(repr), a); err != nil { return fmt.Sprintf("error: %v", err.Error()) } return a.String() } for i, tc := range []string{ `0x1000000000000000000000000000000000000000000000000000000000000000`, `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`, `0x10000000000000000000000000000000000000000000000000000000000000000`, `0x10000000000000000000000000000000000000000000000000000000000000001`, `0x111110000000000000000000000000000000000000000000000000000000000000001`, } { reference, ok := new(big.Int).SetString(tc, 0) if !ok { t.Fatalf("test %d: not ok input %q", i, tc) } haveHex := check(fmt.Sprintf(`"%#x"`, reference)) haveDec := check(fmt.Sprintf(`"%#d"`, reference)) if haveHex != haveDec { t.Fatalf("test %d: hex unmarshal != dec unmarshal, \nhex -> %q\ndec -> %q\n", i, haveHex, haveDec) } } } func TestNil(t *testing.T) { a := NewInt(1337) if err := a.Scan(nil); err != nil { t.Fatal(err) } if !a.IsZero() { t.Fatal("want zero") } } func TestDecimal(t *testing.T) { for i := uint(0); i < 255; i++ { a := NewInt(1) a.Lsh(a, i) want := a.ToBig().Text(10) if have := a.Dec(); have != want { t.Errorf("want '%v' have '%v', \n", want, have) } // Op must not modify the original if have := a.Dec(); have != want { t.Errorf("want '%v' have '%v', \n", want, have) } } // test zero-case if have, want := new(Int).Dec(), new(big.Int).Text(10); have != want { t.Errorf("have '%v', want '%v'", have, want) } { // max max, _ := FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") maxb, _ := new(big.Int).SetString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0) if have, want := max.Dec(), maxb.Text(10); have != want { t.Errorf("have '%v', want '%v'", have, want) } } { max, _ := FromDecimal("29999999999999999999") maxb, _ := new(big.Int).SetString("29999999999999999999", 0) if have, want := max.Dec(), maxb.Text(10); have != want { t.Errorf("have '%v', want '%v'", have, want) } } } // prettyFmtBigInt formats n with thousand separators. func prettyFmtBigInt(n *big.Int) string { var ( text = n.String() buf = make([]byte, len(text)+len(text)/3) comma = 0 i = len(buf) - 1 ) for j := len(text) - 1; j >= 0; j, i = j-1, i-1 { c := text[j] switch { case c == '-': buf[i] = c case comma == 3: buf[i] = ',' i-- comma = 0 fallthrough default: buf[i] = c comma++ } } return string(buf[i+1:]) } func TestPrettyDecimal(t *testing.T) { for i := uint(0); i < 255; i++ { a := NewInt(1) a.Lsh(a, i) want := prettyFmtBigInt(a.ToBig()) if have := a.PrettyDec(','); have != want { t.Errorf("%d: have '%v', want '%v'", i, have, want) } // Op must not modify the original if have := a.PrettyDec(','); have != want { t.Errorf("%d: have '%v', want '%v'", i, have, want) } } // test zero-case if have, want := new(Int).PrettyDec(','), prettyFmtBigInt(new(big.Int)); have != want { t.Errorf("have '%v', want '%v'", have, want) } } func FuzzDecimal(f *testing.F) { f.Fuzz(func(t *testing.T, aa, bb, cc, dd uint64) { a := &Int{aa, bb, cc, dd} { // Test Dec() want := a.ToBig().Text(10) if have := a.Dec(); have != want { t.Errorf("want '%v' have '%v', \n", want, have) } // Op must not modify the original if have := a.Dec(); have != want { t.Errorf("want '%v' have '%v', \n", want, have) } } { // Test PrettyDec want := prettyFmtBigInt(a.ToBig()) if have := a.PrettyDec(','); have != want { t.Errorf("have '%v', want '%v'", have, want) } // Op must not modify the original if have := a.PrettyDec(','); have != want { t.Errorf("have '%v', want '%v'", have, want) } } { // Test Hex() want := fmt.Sprintf("%#x", a.ToBig()) if have := a.Hex(); have != want { t.Errorf("want '%v' have '%v', \n", want, have) } // Op must not modify the original if have := a.Hex(); have != want { t.Errorf("want '%v' have '%v', \n", want, have) } } }) } func BenchmarkDecimal(b *testing.B) { var u256Ints []*Int var bigints []*big.Int for i := uint(0); i < 255; i++ { a := NewInt(1) a.Lsh(a, i) u256Ints = append(u256Ints, a) bigints = append(bigints, a.ToBig()) } b.Run("ToDecimal/uint256", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, z := range u256Ints { _ = z.Dec() } } }) b.Run("ToDecimal/big", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, z := range bigints { _ = z.Text(10) } } }) b.Run("ToPrettyDecimal/uint256", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, z := range u256Ints { _ = z.PrettyDec(',') } } }) b.Run("ToPrettyDecimal/big", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, z := range bigints { _ = prettyFmtBigInt(z) } } }) } func testFloat64(t *testing.T, z *Int) { bigF, _ := new(big.Float).SetInt(z.ToBig()).Float64() _ = z.Float64() // Op must not modify the z if have, want := z.Float64(), bigF; have != want { t.Errorf("%s: have %f want %f", z.Hex(), have, want) } } func TestFloat64(t *testing.T) { for i := uint(0); i < 255; i++ { z := NewInt(1) testFloat64(t, z.Lsh(z, i)) } } func FuzzFloat64(f *testing.F) { f.Fuzz(func(t *testing.T, aa, bb, cc, dd uint64) { testFloat64(t, &Int{aa, bb, cc, dd}) }) } func BenchmarkFloat64(b *testing.B) { var u256Ints []*Int var bigints []*big.Int for i := uint(0); i < 255; i++ { a := NewInt(1) a.Lsh(a, i) u256Ints = append(u256Ints, a) bigints = append(bigints, a.ToBig()) } b.Run("Float64/uint256", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, z := range u256Ints { _ = z.Float64() } } }) b.Run("Float64/big", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, z := range bigints { _, _ = new(big.Float).SetInt(z).Float64() } } }) } uint256-1.3.2/decimal.go000066400000000000000000000153321472460254700146750ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "io" "strconv" ) const twoPow256Sub1 = "115792089237316195423570985008687907853269984665640564039457584007913129639935" // Dec returns the decimal representation of z. func (z *Int) Dec() string { if z.IsZero() { return "0" } if z.IsUint64() { return strconv.FormatUint(z.Uint64(), 10) } // The max uint64 value being 18446744073709551615, the largest // power-of-ten below that is 10000000000000000000. // When we do a DivMod using that number, the remainder that we // get back is the lower part of the output. // // The ascii-output of remainder will never exceed 19 bytes (since it will be // below 10000000000000000000). // // Algorithm example using 100 as divisor // // 12345 % 100 = 45 (rem) // 12345 / 100 = 123 (quo) // -> output '45', continue iterate on 123 var ( // out is 98 bytes long: 78 (max size of a string without leading zeroes, // plus slack so we can copy 19 bytes every iteration). // We init it with zeroes, because when strconv appends the ascii representations, // it will omit leading zeroes. out = []byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") divisor = NewInt(10000000000000000000) // 20 digits y = new(Int).Set(z) // copy to avoid modifying z pos = len(out) // position to write to buf = make([]byte, 0, 19) // buffer to write uint64:s to ) for { // Obtain Q and R for divisor var quot, rem Int udivrem(quot[:], y[:], divisor, &rem) y.Set(") // Set Q for next loop // Convert the R to ascii representation buf = strconv.AppendUint(buf[:0], rem.Uint64(), 10) // Copy in the ascii digits copy(out[pos-len(buf):], buf) if y.IsZero() { break } // Move 19 digits left pos -= 19 } // skip leading zeroes by only using the 'used size' of buf return string(out[pos-len(buf):]) } // PrettyDec returns the decimal representation of z, with thousands-separators. func (z *Int) PrettyDec(separator byte) string { if z.IsZero() { return "0" } // See algorithm-description in Dec() // This just also inserts comma while copying byte-for-byte instead // of using copy(). var ( out = []byte("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") divisor = NewInt(10000000000000000000) y = new(Int).Set(z) // copy to avoid modifying z pos = len(out) - 1 // position to write to buf = make([]byte, 0, 19) // buffer to write uint64:s to comma = 0 ) for { var quot, rem Int udivrem(quot[:], y[:], divisor, &rem) y.Set(") // Set Q for next loop buf = strconv.AppendUint(buf[:0], rem.Uint64(), 10) for j := len(buf) - 1; j >= 0; j-- { if comma == 3 { out[pos] = separator pos-- comma = 0 } out[pos] = buf[j] comma++ pos-- } if y.IsZero() { break } // Need to do zero-padding if we have more iterations coming for j := 0; j < 19-len(buf); j++ { if comma == 3 { out[pos] = separator pos-- comma = 0 } comma++ pos-- } } return string(out[pos+1:]) } // FromDecimal is a convenience-constructor to create an Int from a // decimal (base 10) string. Numbers larger than 256 bits are not accepted. func FromDecimal(decimal string) (*Int, error) { var z Int if err := z.SetFromDecimal(decimal); err != nil { return nil, err } return &z, nil } // MustFromDecimal is a convenience-constructor to create an Int from a // decimal (base 10) string. // Returns a new Int and panics if any error occurred. func MustFromDecimal(decimal string) *Int { var z Int if err := z.SetFromDecimal(decimal); err != nil { panic(err) } return &z } // SetFromDecimal sets z from the given string, interpreted as a decimal number. // OBS! This method is _not_ strictly identical to the (*big.Int).SetString(..., 10) method. // Notable differences: // - This method does not accept underscore input, e.g. "100_000", // - This method does not accept negative zero as valid, e.g "-0", // - (this method does not accept any negative input as valid)) func (z *Int) SetFromDecimal(s string) (err error) { // Remove max one leading + if len(s) > 0 && s[0] == '+' { s = s[1:] } // Remove any number of leading zeroes if len(s) > 0 && s[0] == '0' { var i int var c rune for i, c = range s { if c != '0' { break } } s = s[i:] } if len(s) < len(twoPow256Sub1) { return z.fromDecimal(s) } if len(s) == len(twoPow256Sub1) { if s > twoPow256Sub1 { return ErrBig256Range } return z.fromDecimal(s) } return ErrBig256Range } // multipliers holds the values that are needed for fromDecimal var multipliers = [5]*Int{ nil, // represents first round, no multiplication needed {10000000000000000000, 0, 0, 0}, // 10 ^ 19 {687399551400673280, 5421010862427522170, 0, 0}, // 10 ^ 38 {5332261958806667264, 17004971331911604867, 2938735877055718769, 0}, // 10 ^ 57 {0, 8607968719199866880, 532749306367912313, 1593091911132452277}, // 10 ^ 76 } // fromDecimal is a helper function to only ever be called via SetFromDecimal // this function takes a string and chunks it up, calling ParseUint on it up to 5 times // these chunks are then multiplied by the proper power of 10, then added together. // Note: this method assumes that some basic validity-checks have already been performed // on the input 'bs'. See SetFromDecimal. func (z *Int) fromDecimal(bs string) error { // first clear the input z.Clear() // the maximum value of uint64 is 18446744073709551615, which is 20 characters // one less means that a string of 19 9's is always within the uint64 limit var ( num uint64 err error remaining = len(bs) ) if remaining == 0 { return io.EOF } // We proceed in steps of 19 characters (nibbles), from least significant to most significant. // This means that the first (up to) 19 characters do not need to be multiplied. // In the second iteration, our slice of 19 characters needs to be multipleied // by a factor of 10^19. Et cetera. for i, mult := range multipliers { if remaining <= 0 { return nil // Done } else if remaining > 19 { num, err = strconv.ParseUint(bs[remaining-19:remaining], 10, 64) } else { // Final round num, err = strconv.ParseUint(bs, 10, 64) } if err != nil { return err } // add that number to our running total if i == 0 { z.SetUint64(num) } else { base := NewInt(num) z.Add(z, base.Mul(base, mult)) } // Chop off another 19 characters if remaining > 19 { bs = bs[0 : remaining-19] } remaining -= 19 } return nil } uint256-1.3.2/decimal_test.go000066400000000000000000000107221472460254700157320ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "errors" "fmt" "math/big" "testing" ) // Test SetFromDecimal func testSetFromDec(tc string) error { a := new(Int).SetAllOne() err := a.SetFromDecimal(tc) { // Check the FromDecimal too b, err2 := FromDecimal(tc) if (err == nil) != (err2 == nil) { return fmt.Errorf("err != err2: %v %v", err, err2) } // Test the MustFromDecimal too if err != nil { if !causesPanic(func() { MustFromDecimal(tc) }) { return errors.New("expected panic") } } else { MustFromDecimal(tc) // must not manic } if err == nil { if a.Cmp(b) != 0 { return fmt.Errorf("a != b: %v %v", a, b) } } } // If input is negative, we should eror if len(tc) > 0 && tc[0] == '-' { if err == nil { return fmt.Errorf("want error on negative input") } return nil } // Need to compare with big.Int bigA, ok := big.NewInt(0).SetString(tc, 10) if !ok { if err == nil { return fmt.Errorf("want error") } return nil // both agree that input is bad } if bigA.BitLen() > 256 { if err == nil { return fmt.Errorf("want error (bitlen > 256)") } return nil } want := bigA.String() have := a.Dec() if want != have { return fmt.Errorf("want %v, have %v", want, have) } return nil } var cases = []string{ "0000000000000000000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000000000000000097", "-000000000000000000000000000000000000000000000000000000000000000000000000000000", "1157920892373161954235709850086879078532699846656405640394575840079131296399351", "215792089237316195423570985008687907853269984665640564039457584007913129639935", "115792089237316195423570985008687907853269984665640564039457584007913129639935", "15792089237316195423570985008687907853269984665640564039457584007913129639935", "+115792089237316195423570985008687907853269984665640564039457584007913129639935", "115792089237316195423570985008687907853269984665640564039457584007913129639936", "115792089237316195423570985008687907853269984665640564039457584007913129639935", "+0b00000000000000000000000000000000000000000000000000000000000000010", "340282366920938463463374607431768211456", "3402823669209384634633746074317682114561", "+3402823669209384634633746074317682114561", "+-3402823669209384634633746074317682114561", "40282366920938463463374607431768211456", "00000000000000000000000097", "184467440737095516161", "8446744073709551616", "banana", "+0x10", "000", "+000", "010", "0xab", "-10", "01", "ab", "0", "-0", "+0", "", "熊熊熊熊熊熊熊熊", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x10101011010", "熊熊熊熊熊熊熊熊", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x10000000000000000000000000000000000000000000000000000000000000000", "+0x10000000000000000000000000000000000000000000000000000000000000000", "+0x00000000000000000000000000000000000000000000000000000000000000000", "-0x00000000000000000000000000000000000000000000000000000000000000000", } func TestStringScan(t *testing.T) { for i, tc := range cases { if err := testSetFromDec(tc); err != nil { t.Errorf("test %d, input '%s', SetFromDecimal err: %v", i, tc, err) } // TODO testSetFromHex(tc) } } func FuzzBase10StringCompare(f *testing.F) { for _, tc := range cases { f.Add(tc) } f.Fuzz(func(t *testing.T, tc string) { if err := testSetFromDec(tc); err != nil { t.Errorf("input '%s', SetFromDecimal err: %v", tc, err) } // TODO testSetFromHex(tc) }) } func BenchmarkFromDecimalString(b *testing.B) { input := twoPow256Sub1 b.Run("big", func(b *testing.B) { val := new(big.Int) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { for j := 1; j < len(input); j++ { if _, ok := val.SetString(input[:j], 10); !ok { b.Fatalf("Error on %v", string(input[:j])) } } } }) b.Run("uint256", func(b *testing.B) { val := new(Int) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { for j := 1; j < len(input); j++ { if err := val.SetFromDecimal(input[:j]); err != nil { b.Fatalf("%v: %v", err, string(input[:j])) } } } }) } uint256-1.3.2/div.go000066400000000000000000000015141472460254700140560ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import "math/bits" // reciprocal2by1 computes <^d, ^0> / d. func reciprocal2by1(d uint64) uint64 { reciprocal, _ := bits.Div64(^d, ^uint64(0), d) return reciprocal } // udivrem2by1 divides / d and produces both quotient and remainder. // It uses the provided d's reciprocal. // Implementation ported from https://github.com/chfast/intx and is based on // "Improved division by invariant integers", Algorithm 4. func udivrem2by1(uh, ul, d, reciprocal uint64) (quot, rem uint64) { qh, ql := bits.Mul64(reciprocal, uh) ql, carry := bits.Add64(ql, ul, 0) qh, _ = bits.Add64(qh, uh, carry) qh++ r := ul - qh*d if r > ql { qh-- r += d } if r >= d { qh++ r -= d } return qh, r } uint256-1.3.2/go.mod000066400000000000000000000000531472460254700140500ustar00rootroot00000000000000module github.com/holiman/uint256 go 1.19 uint256-1.3.2/mod.go000066400000000000000000000346541472460254700140660ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2021 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "math/bits" ) // Reciprocal computes a 320-bit value representing 1/m // // Notes: // - specialized for m[3] != 0, hence limited to 2^192 <= m < 2^256 // - returns zero if m[3] == 0 // - starts with a 32-bit division, refines with newton-raphson iterations func Reciprocal(m *Int) (mu [5]uint64) { if m[3] == 0 { return mu } s := bits.LeadingZeros64(m[3]) // Replace with leadingZeros(m) for general case p := 255 - s // floor(log_2(m)), m>0 // 0 or a power of 2? // Check if at least one bit is set in m[2], m[1] or m[0], // or at least two bits in m[3] if m[0] | m[1] | m[2] | (m[3] & (m[3]-1)) == 0 { mu[4] = ^uint64(0) >> uint(p & 63) mu[3] = ^uint64(0) mu[2] = ^uint64(0) mu[1] = ^uint64(0) mu[0] = ^uint64(0) return mu } // Maximise division precision by left-aligning divisor var ( y Int // left-aligned copy of m r0 uint32 // estimate of 2^31/y ) y.Lsh(m, uint(s)) // 1/2 < y < 1 // Extract most significant 32 bits yh := uint32(y[3] >> 32) if yh == 0x80000000 { // Avoid overflow in division r0 = 0xffffffff } else { r0, _ = bits.Div32(0x80000000, 0, yh) } // First iteration: 32 -> 64 t1 := uint64(r0) // 2^31/y t1 *= t1 // 2^62/y^2 t1, _ = bits.Mul64(t1, y[3]) // 2^62/y^2 * 2^64/y / 2^64 = 2^62/y r1 := uint64(r0) << 32 // 2^63/y r1 -= t1 // 2^63/y - 2^62/y = 2^62/y r1 *= 2 // 2^63/y if (r1 | (y[3]<<1)) == 0 { r1 = ^uint64(0) } // Second iteration: 64 -> 128 // square: 2^126/y^2 a2h, a2l := bits.Mul64(r1, r1) // multiply by y: e2h:e2l:b2h = 2^126/y^2 * 2^128/y / 2^128 = 2^126/y b2h, _ := bits.Mul64(a2l, y[2]) c2h, c2l := bits.Mul64(a2l, y[3]) d2h, d2l := bits.Mul64(a2h, y[2]) e2h, e2l := bits.Mul64(a2h, y[3]) b2h, c := bits.Add64(b2h, c2l, 0) e2l, c = bits.Add64(e2l, c2h, c) e2h, _ = bits.Add64(e2h, 0, c) _, c = bits.Add64(b2h, d2l, 0) e2l, c = bits.Add64(e2l, d2h, c) e2h, _ = bits.Add64(e2h, 0, c) // subtract: t2h:t2l = 2^127/y - 2^126/y = 2^126/y t2l, b := bits.Sub64( 0, e2l, 0) t2h, _ := bits.Sub64(r1, e2h, b) // double: r2h:r2l = 2^127/y r2l, c := bits.Add64(t2l, t2l, 0) r2h, _ := bits.Add64(t2h, t2h, c) if (r2h | r2l | (y[3]<<1)) == 0 { r2h = ^uint64(0) r2l = ^uint64(0) } // Third iteration: 128 -> 192 // square r2 (keep 256 bits): 2^190/y^2 a3h, a3l := bits.Mul64(r2l, r2l) b3h, b3l := bits.Mul64(r2l, r2h) c3h, c3l := bits.Mul64(r2h, r2h) a3h, c = bits.Add64(a3h, b3l, 0) c3l, c = bits.Add64(c3l, b3h, c) c3h, _ = bits.Add64(c3h, 0, c) a3h, c = bits.Add64(a3h, b3l, 0) c3l, c = bits.Add64(c3l, b3h, c) c3h, _ = bits.Add64(c3h, 0, c) // multiply by y: q = 2^190/y^2 * 2^192/y / 2^192 = 2^190/y x0 := a3l x1 := a3h x2 := c3l x3 := c3h var q0, q1, q2, q3, q4, t0 uint64 q0, _ = bits.Mul64(x2, y[0]) q1, t0 = bits.Mul64(x3, y[0]); q0, c = bits.Add64(q0, t0, 0); q1, _ = bits.Add64(q1, 0, c) t1, _ = bits.Mul64(x1, y[1]); q0, c = bits.Add64(q0, t1, 0) q2, t0 = bits.Mul64(x3, y[1]); q1, c = bits.Add64(q1, t0, c); q2, _ = bits.Add64(q2, 0, c) t1, t0 = bits.Mul64(x2, y[1]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c); q2, _ = bits.Add64(q2, 0, c) t1, t0 = bits.Mul64(x1, y[2]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) q3, t0 = bits.Mul64(x3, y[2]); q2, c = bits.Add64(q2, t0, c); q3, _ = bits.Add64(q3, 0, c) t1, _ = bits.Mul64(x0, y[2]); q0, c = bits.Add64(q0, t1, 0) t1, t0 = bits.Mul64(x2, y[2]); q1, c = bits.Add64(q1, t0, c); q2, c = bits.Add64(q2, t1, c); q3, _ = bits.Add64(q3, 0, c) t1, t0 = bits.Mul64(x1, y[3]); q1, c = bits.Add64(q1, t0, 0); q2, c = bits.Add64(q2, t1, c) q4, t0 = bits.Mul64(x3, y[3]); q3, c = bits.Add64(q3, t0, c); q4, _ = bits.Add64(q4, 0, c) t1, t0 = bits.Mul64(x0, y[3]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) t1, t0 = bits.Mul64(x2, y[3]); q2, c = bits.Add64(q2, t0, c); q3, c = bits.Add64(q3, t1, c); q4, _ = bits.Add64(q4, 0, c) // subtract: t3 = 2^191/y - 2^190/y = 2^190/y _, b = bits.Sub64( 0, q0, 0) _, b = bits.Sub64( 0, q1, b) t3l, b := bits.Sub64( 0, q2, b) t3m, b := bits.Sub64(r2l, q3, b) t3h, _ := bits.Sub64(r2h, q4, b) // double: r3 = 2^191/y r3l, c := bits.Add64(t3l, t3l, 0) r3m, c := bits.Add64(t3m, t3m, c) r3h, _ := bits.Add64(t3h, t3h, c) // Fourth iteration: 192 -> 320 // square r3 a4h, a4l := bits.Mul64(r3l, r3l) b4h, b4l := bits.Mul64(r3l, r3m) c4h, c4l := bits.Mul64(r3l, r3h) d4h, d4l := bits.Mul64(r3m, r3m) e4h, e4l := bits.Mul64(r3m, r3h) f4h, f4l := bits.Mul64(r3h, r3h) b4h, c = bits.Add64(b4h, c4l, 0) e4l, c = bits.Add64(e4l, c4h, c) e4h, _ = bits.Add64(e4h, 0, c) a4h, c = bits.Add64(a4h, b4l, 0) d4l, c = bits.Add64(d4l, b4h, c) d4h, c = bits.Add64(d4h, e4l, c) f4l, c = bits.Add64(f4l, e4h, c) f4h, _ = bits.Add64(f4h, 0, c) a4h, c = bits.Add64(a4h, b4l, 0) d4l, c = bits.Add64(d4l, b4h, c) d4h, c = bits.Add64(d4h, e4l, c) f4l, c = bits.Add64(f4l, e4h, c) f4h, _ = bits.Add64(f4h, 0, c) // multiply by y x1, x0 = bits.Mul64(d4h, y[0]) x3, x2 = bits.Mul64(f4h, y[0]) t1, t0 = bits.Mul64(f4l, y[0]); x1, c = bits.Add64(x1, t0, 0); x2, c = bits.Add64(x2, t1, c) x3, _ = bits.Add64(x3, 0, c) t1, t0 = bits.Mul64(d4h, y[1]); x1, c = bits.Add64(x1, t0, 0); x2, c = bits.Add64(x2, t1, c) x4, t0 := bits.Mul64(f4h, y[1]); x3, c = bits.Add64(x3, t0, c); x4, _ = bits.Add64(x4, 0, c) t1, t0 = bits.Mul64(d4l, y[1]); x0, c = bits.Add64(x0, t0, 0); x1, c = bits.Add64(x1, t1, c) t1, t0 = bits.Mul64(f4l, y[1]); x2, c = bits.Add64(x2, t0, c); x3, c = bits.Add64(x3, t1, c) x4, _ = bits.Add64(x4, 0, c) t1, t0 = bits.Mul64(a4h, y[2]); x0, c = bits.Add64(x0, t0, 0); x1, c = bits.Add64(x1, t1, c) t1, t0 = bits.Mul64(d4h, y[2]); x2, c = bits.Add64(x2, t0, c); x3, c = bits.Add64(x3, t1, c) x5, t0 := bits.Mul64(f4h, y[2]); x4, c = bits.Add64(x4, t0, c); x5, _ = bits.Add64(x5, 0, c) t1, t0 = bits.Mul64(d4l, y[2]); x1, c = bits.Add64(x1, t0, 0); x2, c = bits.Add64(x2, t1, c) t1, t0 = bits.Mul64(f4l, y[2]); x3, c = bits.Add64(x3, t0, c); x4, c = bits.Add64(x4, t1, c) x5, _ = bits.Add64(x5, 0, c) t1, t0 = bits.Mul64(a4h, y[3]); x1, c = bits.Add64(x1, t0, 0); x2, c = bits.Add64(x2, t1, c) t1, t0 = bits.Mul64(d4h, y[3]); x3, c = bits.Add64(x3, t0, c); x4, c = bits.Add64(x4, t1, c) x6, t0 := bits.Mul64(f4h, y[3]); x5, c = bits.Add64(x5, t0, c); x6, _ = bits.Add64(x6, 0, c) t1, t0 = bits.Mul64(a4l, y[3]); x0, c = bits.Add64(x0, t0, 0); x1, c = bits.Add64(x1, t1, c) t1, t0 = bits.Mul64(d4l, y[3]); x2, c = bits.Add64(x2, t0, c); x3, c = bits.Add64(x3, t1, c) t1, t0 = bits.Mul64(f4l, y[3]); x4, c = bits.Add64(x4, t0, c); x5, c = bits.Add64(x5, t1, c) x6, _ = bits.Add64(x6, 0, c) // subtract _, b = bits.Sub64( 0, x0, 0) _, b = bits.Sub64( 0, x1, b) r4l, b := bits.Sub64( 0, x2, b) r4k, b := bits.Sub64( 0, x3, b) r4j, b := bits.Sub64(r3l, x4, b) r4i, b := bits.Sub64(r3m, x5, b) r4h, _ := bits.Sub64(r3h, x6, b) // Multiply candidate for 1/4y by y, with full precision x0 = r4l x1 = r4k x2 = r4j x3 = r4i x4 = r4h q1, q0 = bits.Mul64(x0, y[0]) q3, q2 = bits.Mul64(x2, y[0]) q5, q4 := bits.Mul64(x4, y[0]) t1, t0 = bits.Mul64(x1, y[0]); q1, c = bits.Add64(q1, t0, 0); q2, c = bits.Add64(q2, t1, c) t1, t0 = bits.Mul64(x3, y[0]); q3, c = bits.Add64(q3, t0, c); q4, c = bits.Add64(q4, t1, c); q5, _ = bits.Add64(q5, 0, c) t1, t0 = bits.Mul64(x0, y[1]); q1, c = bits.Add64(q1, t0, 0); q2, c = bits.Add64(q2, t1, c) t1, t0 = bits.Mul64(x2, y[1]); q3, c = bits.Add64(q3, t0, c); q4, c = bits.Add64(q4, t1, c) q6, t0 := bits.Mul64(x4, y[1]); q5, c = bits.Add64(q5, t0, c); q6, _ = bits.Add64(q6, 0, c) t1, t0 = bits.Mul64(x1, y[1]); q2, c = bits.Add64(q2, t0, 0); q3, c = bits.Add64(q3, t1, c) t1, t0 = bits.Mul64(x3, y[1]); q4, c = bits.Add64(q4, t0, c); q5, c = bits.Add64(q5, t1, c); q6, _ = bits.Add64(q6, 0, c) t1, t0 = bits.Mul64(x0, y[2]); q2, c = bits.Add64(q2, t0, 0); q3, c = bits.Add64(q3, t1, c) t1, t0 = bits.Mul64(x2, y[2]); q4, c = bits.Add64(q4, t0, c); q5, c = bits.Add64(q5, t1, c) q7, t0 := bits.Mul64(x4, y[2]); q6, c = bits.Add64(q6, t0, c); q7, _ = bits.Add64(q7, 0, c) t1, t0 = bits.Mul64(x1, y[2]); q3, c = bits.Add64(q3, t0, 0); q4, c = bits.Add64(q4, t1, c) t1, t0 = bits.Mul64(x3, y[2]); q5, c = bits.Add64(q5, t0, c); q6, c = bits.Add64(q6, t1, c); q7, _ = bits.Add64(q7, 0, c) t1, t0 = bits.Mul64(x0, y[3]); q3, c = bits.Add64(q3, t0, 0); q4, c = bits.Add64(q4, t1, c) t1, t0 = bits.Mul64(x2, y[3]); q5, c = bits.Add64(q5, t0, c); q6, c = bits.Add64(q6, t1, c) q8, t0 := bits.Mul64(x4, y[3]); q7, c = bits.Add64(q7, t0, c); q8, _ = bits.Add64(q8, 0, c) t1, t0 = bits.Mul64(x1, y[3]); q4, c = bits.Add64(q4, t0, 0); q5, c = bits.Add64(q5, t1, c) t1, t0 = bits.Mul64(x3, y[3]); q6, c = bits.Add64(q6, t0, c); q7, c = bits.Add64(q7, t1, c); q8, _ = bits.Add64(q8, 0, c) // Final adjustment // subtract q from 1/4 _, b = bits.Sub64(0, q0, 0) _, b = bits.Sub64(0, q1, b) _, b = bits.Sub64(0, q2, b) _, b = bits.Sub64(0, q3, b) _, b = bits.Sub64(0, q4, b) _, b = bits.Sub64(0, q5, b) _, b = bits.Sub64(0, q6, b) _, b = bits.Sub64(0, q7, b) _, b = bits.Sub64(uint64(1) << 62, q8, b) // decrement the result x0, t := bits.Sub64(r4l, 1, 0) x1, t = bits.Sub64(r4k, 0, t) x2, t = bits.Sub64(r4j, 0, t) x3, t = bits.Sub64(r4i, 0, t) x4, _ = bits.Sub64(r4h, 0, t) // commit the decrement if the subtraction underflowed (reciprocal was too large) if b != 0 { r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0 } // Shift to correct bit alignment, truncating excess bits p = (p & 63) - 1 x0, c = bits.Add64(r4l, r4l, 0) x1, c = bits.Add64(r4k, r4k, c) x2, c = bits.Add64(r4j, r4j, c) x3, c = bits.Add64(r4i, r4i, c) x4, _ = bits.Add64(r4h, r4h, c) if p < 0 { r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0 p = 0 // avoid negative shift below } { r := uint(p) // right shift l := uint(64 - r) // left shift x0 = (r4l >> r) | (r4k << l) x1 = (r4k >> r) | (r4j << l) x2 = (r4j >> r) | (r4i << l) x3 = (r4i >> r) | (r4h << l) x4 = (r4h >> r) } if p > 0 { r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0 } mu[0] = r4l mu[1] = r4k mu[2] = r4j mu[3] = r4i mu[4] = r4h return mu } // reduce4 computes the least non-negative residue of x modulo m // // requires a four-word modulus (m[3] != 0) and its inverse (mu) func (z *Int) reduce4(x *[8]uint64, m *Int, mu *[5]uint64) *Int { // NB: Most variable names in the comments match the pseudocode for // Barrett reduction in the Handbook of Applied Cryptography. // q1 = x/2^192 x0 := x[3] x1 := x[4] x2 := x[5] x3 := x[6] x4 := x[7] // q2 = q1 * mu; q3 = q2 / 2^320 var q0, q1, q2, q3, q4, q5, t0, t1, c uint64 q0, _ = bits.Mul64(x3, mu[0]) q1, t0 = bits.Mul64(x4, mu[0]); q0, c = bits.Add64(q0, t0, 0); q1, _ = bits.Add64(q1, 0, c) t1, _ = bits.Mul64(x2, mu[1]); q0, c = bits.Add64(q0, t1, 0) q2, t0 = bits.Mul64(x4, mu[1]); q1, c = bits.Add64(q1, t0, c); q2, _ = bits.Add64(q2, 0, c) t1, t0 = bits.Mul64(x3, mu[1]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c); q2, _ = bits.Add64(q2, 0, c) t1, t0 = bits.Mul64(x2, mu[2]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) q3, t0 = bits.Mul64(x4, mu[2]); q2, c = bits.Add64(q2, t0, c); q3, _ = bits.Add64(q3, 0, c) t1, _ = bits.Mul64(x1, mu[2]); q0, c = bits.Add64(q0, t1, 0) t1, t0 = bits.Mul64(x3, mu[2]); q1, c = bits.Add64(q1, t0, c); q2, c = bits.Add64(q2, t1, c); q3, _ = bits.Add64(q3, 0, c) t1, _ = bits.Mul64(x0, mu[3]); q0, c = bits.Add64(q0, t1, 0) t1, t0 = bits.Mul64(x2, mu[3]); q1, c = bits.Add64(q1, t0, c); q2, c = bits.Add64(q2, t1, c) q4, t0 = bits.Mul64(x4, mu[3]); q3, c = bits.Add64(q3, t0, c); q4, _ = bits.Add64(q4, 0, c) t1, t0 = bits.Mul64(x1, mu[3]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) t1, t0 = bits.Mul64(x3, mu[3]); q2, c = bits.Add64(q2, t0, c); q3, c = bits.Add64(q3, t1, c); q4, _ = bits.Add64(q4, 0, c) t1, t0 = bits.Mul64(x0, mu[4]); _, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) t1, t0 = bits.Mul64(x2, mu[4]); q2, c = bits.Add64(q2, t0, c); q3, c = bits.Add64(q3, t1, c) q5, t0 = bits.Mul64(x4, mu[4]); q4, c = bits.Add64(q4, t0, c); q5, _ = bits.Add64(q5, 0, c) t1, t0 = bits.Mul64(x1, mu[4]); q1, c = bits.Add64(q1, t0, 0); q2, c = bits.Add64(q2, t1, c) t1, t0 = bits.Mul64(x3, mu[4]); q3, c = bits.Add64(q3, t0, c); q4, c = bits.Add64(q4, t1, c); q5, _ = bits.Add64(q5, 0, c) // Drop the fractional part of q3 q0 = q1 q1 = q2 q2 = q3 q3 = q4 q4 = q5 // r1 = x mod 2^320 x0 = x[0] x1 = x[1] x2 = x[2] x3 = x[3] x4 = x[4] // r2 = q3 * m mod 2^320 var r0, r1, r2, r3, r4 uint64 r4, r3 = bits.Mul64(q0, m[3]) _, t0 = bits.Mul64(q1, m[3]); r4, _ = bits.Add64(r4, t0, 0) t1, r2 = bits.Mul64(q0, m[2]); r3, c = bits.Add64(r3, t1, 0) _, t0 = bits.Mul64(q2, m[2]); r4, _ = bits.Add64(r4, t0, c) t1, t0 = bits.Mul64(q1, m[2]); r3, c = bits.Add64(r3, t0, 0); r4, _ = bits.Add64(r4, t1, c) t1, r1 = bits.Mul64(q0, m[1]); r2, c = bits.Add64(r2, t1, 0) t1, t0 = bits.Mul64(q2, m[1]); r3, c = bits.Add64(r3, t0, c); r4, _ = bits.Add64(r4, t1, c) t1, t0 = bits.Mul64(q1, m[1]); r2, c = bits.Add64(r2, t0, 0); r3, c = bits.Add64(r3, t1, c) _, t0 = bits.Mul64(q3, m[1]); r4, _ = bits.Add64(r4, t0, c) t1, r0 = bits.Mul64(q0, m[0]); r1, c = bits.Add64(r1, t1, 0) t1, t0 = bits.Mul64(q2, m[0]); r2, c = bits.Add64(r2, t0, c); r3, c = bits.Add64(r3, t1, c) _, t0 = bits.Mul64(q4, m[0]); r4, _ = bits.Add64(r4, t0, c) t1, t0 = bits.Mul64(q1, m[0]); r1, c = bits.Add64(r1, t0, 0); r2, c = bits.Add64(r2, t1, c) t1, t0 = bits.Mul64(q3, m[0]); r3, c = bits.Add64(r3, t0, c); r4, _ = bits.Add64(r4, t1, c) // r = r1 - r2 var b uint64 r0, b = bits.Sub64(x0, r0, 0) r1, b = bits.Sub64(x1, r1, b) r2, b = bits.Sub64(x2, r2, b) r3, b = bits.Sub64(x3, r3, b) r4, b = bits.Sub64(x4, r4, b) // if r<0 then r+=m if b != 0 { r0, c = bits.Add64(r0, m[0], 0) r1, c = bits.Add64(r1, m[1], c) r2, c = bits.Add64(r2, m[2], c) r3, c = bits.Add64(r3, m[3], c) r4, _ = bits.Add64(r4, 0, c) } // while (r>=m) r-=m for { // q = r - m q0, b = bits.Sub64(r0, m[0], 0) q1, b = bits.Sub64(r1, m[1], b) q2, b = bits.Sub64(r2, m[2], b) q3, b = bits.Sub64(r3, m[3], b) q4, b = bits.Sub64(r4, 0, b) // if borrow break if b != 0 { break } // r = q r4, r3, r2, r1, r0 = q4, q3, q2, q1, q0 } z[3], z[2], z[1], z[0] = r3, r2, r1, r0 return z } uint256-1.3.2/oss-fuzz.sh000066400000000000000000000043551472460254700151070ustar00rootroot00000000000000#!/bin/bash -eu # This sets the -coverpgk for the coverage report when the corpus is executed through go test coverpkg="github.com/holiman/uint256/..." (cd /src/ && git clone https://github.com/holiman/gofuzz-shim.git ) function coverbuild { path=$1 function=$2 fuzzer=$3 tags="" if [[ $# -eq 4 ]]; then tags="-tags $4" fi cd $path fuzzed_package=`pwd | rev | cut -d'/' -f 1 | rev` cp /src/gofuzz-shim/coverage_runner_template.txt ./"${function,,}"_test.go sed -i -e 's/FuzzFunction/'$function'/' ./"${function,,}"_test.go sed -i -e 's/mypackagebeingfuzzed/'$fuzzed_package'/' ./"${function,,}"_test.go sed -i -e 's/TestFuzzCorpus/Test'$function'Corpus/' ./"${function,,}"_test.go cat << DOG > $OUT/$fuzzer #/bin/sh cd $OUT/$path go test -run Test${function}Corpus -v $tags -coverprofile \$1 -coverpkg $coverpkg DOG chmod +x $OUT/$fuzzer #echo "Built script $OUT/$fuzzer" #cat $OUT/$fuzzer cd - } repo=/src/uint256 function compile_fuzzer() { package=$1 function=$2 fuzzer=$3 file=$4 path=$repo echo "Building $fuzzer" cd $path # Install build dependencies go mod tidy go get github.com/holiman/gofuzz-shim/testing if [[ $SANITIZER == *coverage* ]]; then coverbuild $path $function $fuzzer $coverpkg else gofuzz-shim --func $function --package $package -f $file -o $fuzzer.a $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer fi ## Check if there exists a seed corpus file corpusfile="${path}/testdata/${fuzzer}_seed_corpus.zip" if [ -f $corpusfile ] then cp $corpusfile $OUT/ echo "Found seed corpus: $corpusfile" fi cd - } go install github.com/holiman/gofuzz-shim@latest compile_fuzzer github.com/holiman/uint256 FuzzUnaryOperations fuzzUnary $repo/unary_test.go,$repo/shared_test.go compile_fuzzer github.com/holiman/uint256 FuzzBinaryOperations fuzzBinary $repo/binary_test.go,$repo/shared_test.go compile_fuzzer github.com/holiman/uint256 FuzzCompareOperations fuzzCompare $repo/binary_test.go,$repo/shared_test.go compile_fuzzer github.com/holiman/uint256 FuzzTernaryOperations fuzzTernary $repo/ternary_test.go,$repo/shared_test.go compile_fuzzer github.com/holiman/uint256 FuzzSetString fuzzSetString $repo/conversion_fuzz_test.go,$repo/shared_test.go uint256-1.3.2/shared_test.go000066400000000000000000000227111472460254700156030ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2018-2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "crypto/rand" "math/big" ) // This file contains some utilities which the oss-fuzz fuzzer shares with the // regular go-native tests. It is placed in a separate file, becaue the oss-fuzz // clang-based fuzzing infrastructure requires some instrumentation. // During this instrumentation, the file under test (e.g. unary_test.go) is modified, // and the same modification needs to be performed with any other files that // it requires (this file). var ( bigtt256 = new(big.Int).Lsh(big.NewInt(1), 256) bigtt255 = new(big.Int).Lsh(big.NewInt(1), 255) bigtt256m1 = new(big.Int).Sub(bigtt256, big.NewInt(1)) unTestCases = []string{ "0x0", "0x1", "0x8000000000000000", "0x12cbafcee8f60f9f", "0x80000000000000000000000000000000", "0x80000000000000010000000000000000", "0x80000000000000000000000000000001", "0x12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5", "0x8000000000000000000000000000000000000000000000000000000000000000", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", } // A collection of interesting input values for binary operators (especially for division). // No expected results as big.Int can be used as the source of truth. binTestCases = [][2]string{ {"0x0", "0x0"}, {"0x1", "0x0"}, {"0x1", "0x767676767676767676000000767676767676"}, {"0x2", "0x0"}, {"0x2", "0x1"}, {"0x12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5", "0xc76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9"}, {"0x10000000000000000", "0x2"}, {"0x7000000000000000", "0x8000000000000000"}, {"0x8000000000000000", "0x8000000000000000"}, {"0x8000000000000001", "0x8000000000000000"}, {"0x80000000000000010000000000000000", "0x80000000000000000000000000000000"}, {"0x80000000000000000000000000000000", "0x80000000000000000000000000000001"}, {"0x478392145435897052", "0x111"}, {"0x767676767676767676000000767676767676", "0x2900760076761e00020076760000000076767676000000"}, {"0x12121212121212121212121212121212", "0x232323232323232323"}, {"0xfffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00", "0xfffff716b61616160b0b0b2b0b230b000008010d0a2b00"}, {"0x50beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00", "0x2000110000000d0a300e750a000000090a0a"}, {"0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000", "0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a"}, {"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "0x7"}, {"0xf6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0", "0xb368d219438b7f3f"}, {"0x0", "0x10900000000000000000000000000000000000000000000000000"}, {"0x77676767676760000000000000001002e000000000000040000000e000000000", "0xfffc000000000000767676240000000000002b0576047"}, {"0x767676767676000000000076000000000000005600000000000000000000", "0x767676767676000000000076000000760000"}, {"0x8200000000000000000000000000000000000000000000000000000000000000", "0x8200000000000000fe000004000000ffff000000fffff700"}, {"0xdac7fff9ffd9e1322626262626262600", "0xd021262626262626"}, {"0x8000000000000001800000000000000080000000000000008000000000000000", "0x800000000000000080000000000000008000000000000000"}, {"0xe8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000", "0xe8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff"}, {"0xc9700000000000000000023f00c00014ff000000000000000022300805", "0xc9700000000000000000023f00c00014ff002c000000000000223108"}, {"0x40000000fd000000db0000000000000000000000000000000000000000000001", "0x40000000fd000000db0000000000000000000040000000fd000000db000001"}, {"0x40000000fd000000db0000000000000000000000000000000000000000000001", "0x40000000fd000000db0000000000000000000040000000fd000000db0000d3"}, {"0x1f000000000000000000000000000000200000000100000000000000000000", "0x100000000ffffffffffffffff0000000000002e000000"}, {"0x7effffff80000000000000000000000000020000440000000000000000000001", "0x7effffff800000007effffff800000008000ff0000010000"}, {"0x5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001", "0x2ffffffffffffffffffffffffffffffffff000000030000"}, {"0x62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001", "0x2ffffffffffffffffffffffffffffffffff200000000000"}, {"0x7effffff8000000000000000000000000000000000000000d900000000000001", "0x7effffff8000000000000000000000000000000000008001"}, {"0x6400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a", "0x210000000000000022"}, {"0x6d5adef08547abf7eb", "0x13590cab83b779e708b533b0eef3561483ddeefc841f5"}, {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {"0xe8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000", "0xffffffffffffffff7effffff800000007effffff800000008000ff0000010000"}, {"0x1ce97e1ab91a", "0x66aa0a5319bcf5cb4"}, // regression test for udivrem() where len(x) < len(y) } // A collection of interesting input values for ternary operators (addmod, mulmod). ternTestCases = [][3]string{ {"0x0", "0x0", "0x0"}, {"0x1", "0x0", "0x0"}, {"0x1", "0x1", "0x0"}, {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0x0"}, {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0x3", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x2"}, {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x1"}, {"0xffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffe00000000000000000000000000000002"}, {"0xffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffe00000000000000000000000000000001"}, {"0xffffffffffffffffffffffffffff000004020041fffffffffc00000060000020", "0xffffffffffffffffffffffffffffffe6000000ffffffe60000febebeffffffff", "0xffffffffffffffffffe6000000ffffffe60000febebeffffffffffffffffffff"}, {"0xffffffffffffffffffffffffffffffff00ffffe6ff0000000000000060000020", "0xffffffffffffffffffffffffffffffffffe6000000ffff00e60000febebeffff", "0xffffffffffffffffffe6000000ffff00e60000fe0000ffff00e60000febebeff"}, {"0xfffffffffffffffffffffffff600000000005af50100bebe000000004a00be0a", "0xffffffffffffffffffffffffffffeaffdfd9fffffffffffff5f60000000000ff", "0xffffffffffffffffffffffeaffdfd9fffffffffffffff60000000000ffffffff"}, {"0x8000000000000001000000000000000000000000000000000000000000000000", "0x800000000000000100000000000000000000000000000000000000000000000b", "0x8000000000000000000000000000000000000000000000000000000000000000"}, {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000", "0x8000000000000000000000000000000000000000000000000000000000000000"}, {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000"}, {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000000000000000000000100000000000000000000000000000000", "0x8000000000000000000000000000000000000000000000000000000000000001"}, {"0x1", "0x1", "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"}, {"0x1", "0x1", "0x1000000003030303030303030303030303030303030303030303030303030"}, {"0x1", "0x1", "0x4000000000000000130303030303030303030303030303030303030303030"}, {"0x1", "0x1", "0x8000000000000000000000000000000043030303000000000"}, {"0x1", "0x1", "0x8000000000000000000000000000000003030303030303030"}, } ) // bigU256 encodes as a 256 bit two's complement number. This operation is destructive. func bigU256(x *big.Int) *big.Int { return x.And(x, bigtt256m1) } func bigS256(x *big.Int) *big.Int { if x.Cmp(bigtt255) < 0 { return x } return new(big.Int).Sub(x, bigtt256) } func randNum() *Int { //How many bits? 0-256 nbits, _ := rand.Int(rand.Reader, big.NewInt(257)) //Max random value, a 130-bits integer, i.e 2^130 max := new(big.Int) max.Exp(big.NewInt(2), big.NewInt(nbits.Int64()), nil) b, _ := rand.Int(rand.Reader, max) f, _ := FromBig(b) return f } uint256-1.3.2/ternary_test.go000066400000000000000000000101571472460254700160220ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "fmt" "math/big" "testing" ) type opThreeArgFunc func(*Int, *Int, *Int, *Int) *Int type bigThreeArgFunc func(*big.Int, *big.Int, *big.Int, *big.Int) *big.Int var ternaryOpFuncs = []struct { name string u256Fn opThreeArgFunc bigFn bigThreeArgFunc }{ {"AddMod", (*Int).AddMod, bigAddMod}, {"MulMod", (*Int).MulMod, bigMulMod}, {"MulModWithReciprocal", (*Int).mulModWithReciprocalWrapper, bigMulMod}, {"DivModZ", divModZ, bigDivModZ}, {"DivModM", divModM, bigDivModM}, } func checkTernaryOperation(t *testing.T, opName string, op opThreeArgFunc, bigOp bigThreeArgFunc, x, y, z Int) { var ( f1orig = x.Clone() f2orig = y.Clone() f3orig = z.Clone() b1 = x.ToBig() b2 = y.ToBig() b3 = z.ToBig() f1 = new(Int).Set(f1orig) f2 = new(Int).Set(f2orig) f3 = new(Int).Set(f3orig) operation = fmt.Sprintf("op: %v ( %v, %v, %v ) ", opName, x.Hex(), y.Hex(), z.Hex()) want, _ = FromBig(bigOp(new(big.Int), b1, b2, b3)) have = op(new(Int), f1, f2, f3) ) if !have.Eq(want) { t.Fatalf("%v\nwant : %#x\nhave : %#x\n", operation, want, have) } // Check if arguments are unmodified. if !f1.Eq(f1orig) { t.Fatalf("%v\nfirst argument had been modified: %x", operation, f1) } if !f2.Eq(f2orig) { t.Fatalf("%v\nsecond argument had been modified: %x", operation, f2) } if !f3.Eq(f3orig) { if opName != "DivModZ" && opName != "DivModM" { // DivMod takes m as third argument, modifies it, and returns it. That is by design. t.Fatalf("%v\nthird argument had been modified: %x", operation, f3) } } // Check if reusing args as result works correctly. if have = op(f1, f1, f2orig, f3orig); have != f1 { t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f1) } else if !have.Eq(want) { t.Fatalf("%v\non argument reuse x.op(x,y,z)\nwant : %#x\nhave : %#x\n", operation, want, have) } if have = op(f2, f1orig, f2, f3orig); have != f2 { t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f2) } else if !have.Eq(want) { t.Fatalf("%v\non argument reuse y.op(x,y,z)\nwant : %#x\nhave : %#x\n", operation, want, have) } if have = op(f3, f1orig, f2orig, f3); have != f3 { t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f3) } else if !have.Eq(want) { t.Fatalf("%v\non argument reuse z.op(x,y,z)\nwant : %#x\nhave : %#x\n", operation, want, have) } } func TestTernaryOperations(t *testing.T) { for _, tc := range ternaryOpFuncs { for _, inputs := range ternTestCases { f1 := MustFromHex(inputs[0]) f2 := MustFromHex(inputs[1]) f3 := MustFromHex(inputs[2]) t.Run(tc.name, func(t *testing.T) { checkTernaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2, *f3) }) } } } func FuzzTernaryOperations(f *testing.F) { f.Fuzz(func(t *testing.T, x0, x1, x2, x3, y0, y1, y2, y3, z0, z1, z2, z3 uint64) { x := Int{x0, x1, x2, x3} y := Int{y0, y1, y2, y3} z := Int{z0, z1, z2, z3} for _, tc := range ternaryOpFuncs { checkTernaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, x, y, z) } }) } func bigAddMod(result, x, y, mod *big.Int) *big.Int { if mod.Sign() == 0 { return result.SetUint64(0) } return result.Mod(result.Add(x, y), mod) } func bigMulMod(result, x, y, mod *big.Int) *big.Int { if mod.Sign() == 0 { return result.SetUint64(0) } return result.Mod(result.Mul(x, y), mod) } func (z *Int) mulModWithReciprocalWrapper(x, y, mod *Int) *Int { mu := Reciprocal(mod) return z.MulModWithReciprocal(x, y, mod, &mu) } func divModZ(z, x, y, m *Int) *Int { z2, _ := z.DivMod(x, y, m) return z2 } func bigDivModZ(result, x, y, mod *big.Int) *big.Int { if y.Sign() == 0 { return result.SetUint64(0) } z2, _ := result.DivMod(x, y, mod) return z2 } func divModM(z, x, y, m *Int) *Int { _, m2 := z.DivMod(x, y, m) return z.Set(m2) } func bigDivModM(result, x, y, mod *big.Int) *big.Int { if y.Sign() == 0 { return result.SetUint64(0) } _, m2 := result.DivMod(x, y, mod) return result.Set(m2) } uint256-1.3.2/uint256.go000066400000000000000000001101431472460254700145070ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2018-2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause // Package math provides integer math utilities. package uint256 import ( "encoding/binary" "math" "math/big" "math/bits" ) // Int is represented as an array of 4 uint64, in little-endian order, // so that Int[3] is the most significant, and Int[0] is the least significant type Int [4]uint64 // NewInt returns a new initialized Int. func NewInt(val uint64) *Int { z := &Int{} z.SetUint64(val) return z } // SetBytes interprets buf as the bytes of a big-endian unsigned // integer, sets z to that value, and returns z. // If buf is larger than 32 bytes, the last 32 bytes is used. This operation // is semantically equivalent to `FromBig(new(big.Int).SetBytes(buf))` func (z *Int) SetBytes(buf []byte) *Int { switch l := len(buf); l { case 0: z.Clear() case 1: z.SetBytes1(buf) case 2: z.SetBytes2(buf) case 3: z.SetBytes3(buf) case 4: z.SetBytes4(buf) case 5: z.SetBytes5(buf) case 6: z.SetBytes6(buf) case 7: z.SetBytes7(buf) case 8: z.SetBytes8(buf) case 9: z.SetBytes9(buf) case 10: z.SetBytes10(buf) case 11: z.SetBytes11(buf) case 12: z.SetBytes12(buf) case 13: z.SetBytes13(buf) case 14: z.SetBytes14(buf) case 15: z.SetBytes15(buf) case 16: z.SetBytes16(buf) case 17: z.SetBytes17(buf) case 18: z.SetBytes18(buf) case 19: z.SetBytes19(buf) case 20: z.SetBytes20(buf) case 21: z.SetBytes21(buf) case 22: z.SetBytes22(buf) case 23: z.SetBytes23(buf) case 24: z.SetBytes24(buf) case 25: z.SetBytes25(buf) case 26: z.SetBytes26(buf) case 27: z.SetBytes27(buf) case 28: z.SetBytes28(buf) case 29: z.SetBytes29(buf) case 30: z.SetBytes30(buf) case 31: z.SetBytes31(buf) default: z.SetBytes32(buf[l-32:]) } return z } // Bytes32 returns the value of z as a 32-byte big-endian array. func (z *Int) Bytes32() [32]byte { // The PutUint64()s are inlined and we get 4x (load, bswap, store) instructions. var b [32]byte binary.BigEndian.PutUint64(b[0:8], z[3]) binary.BigEndian.PutUint64(b[8:16], z[2]) binary.BigEndian.PutUint64(b[16:24], z[1]) binary.BigEndian.PutUint64(b[24:32], z[0]) return b } // Bytes20 returns the value of z as a 20-byte big-endian array. func (z *Int) Bytes20() [20]byte { var b [20]byte // The PutUint*()s are inlined and we get 3x (load, bswap, store) instructions. binary.BigEndian.PutUint32(b[0:4], uint32(z[2])) binary.BigEndian.PutUint64(b[4:12], z[1]) binary.BigEndian.PutUint64(b[12:20], z[0]) return b } // Bytes returns the value of z as a big-endian byte slice. func (z *Int) Bytes() []byte { b := z.Bytes32() return b[32-z.ByteLen():] } // WriteToSlice writes the content of z into the given byteslice. // If dest is larger than 32 bytes, z will fill the first parts, and leave // the end untouched. // OBS! If dest is smaller than 32 bytes, only the end parts of z will be used // for filling the array, making it useful for filling an Address object func (z *Int) WriteToSlice(dest []byte) { // ensure 32 bytes // A too large buffer. Fill last 32 bytes end := len(dest) - 1 if end > 31 { end = 31 } for i := 0; i <= end; i++ { dest[end-i] = byte(z[i/8] >> uint64(8*(i%8))) } } // PutUint256 writes all 32 bytes of z to the destination slice, including zero-bytes. // If dest is larger than 32 bytes, z will fill the first parts, and leave // the end untouched. // Note: The dest slice must be at least 32 bytes large, otherwise this // method will panic. The method WriteToSlice, which is slower, should be used // if the destination slice is smaller or of unknown size. func (z *Int) PutUint256(dest []byte) { _ = dest[31] binary.BigEndian.PutUint64(dest[0:8], z[3]) binary.BigEndian.PutUint64(dest[8:16], z[2]) binary.BigEndian.PutUint64(dest[16:24], z[1]) binary.BigEndian.PutUint64(dest[24:32], z[0]) } // WriteToArray32 writes all 32 bytes of z to the destination array, including zero-bytes func (z *Int) WriteToArray32(dest *[32]byte) { // The PutUint64()s are inlined and we get 4x (load, bswap, store) instructions. binary.BigEndian.PutUint64(dest[0:8], z[3]) binary.BigEndian.PutUint64(dest[8:16], z[2]) binary.BigEndian.PutUint64(dest[16:24], z[1]) binary.BigEndian.PutUint64(dest[24:32], z[0]) } // WriteToArray20 writes the last 20 bytes of z to the destination array, including zero-bytes func (z *Int) WriteToArray20(dest *[20]byte) { // The PutUint*()s are inlined and we get 3x (load, bswap, store) instructions. binary.BigEndian.PutUint32(dest[0:4], uint32(z[2])) binary.BigEndian.PutUint64(dest[4:12], z[1]) binary.BigEndian.PutUint64(dest[12:20], z[0]) } // Uint64 returns the lower 64-bits of z func (z *Int) Uint64() uint64 { return z[0] } // Uint64WithOverflow returns the lower 64-bits of z and bool whether overflow occurred func (z *Int) Uint64WithOverflow() (uint64, bool) { return z[0], (z[1] | z[2] | z[3]) != 0 } // Clone creates a new Int identical to z func (z *Int) Clone() *Int { return &Int{z[0], z[1], z[2], z[3]} } // Add sets z to the sum x+y func (z *Int) Add(x, y *Int) *Int { var carry uint64 z[0], carry = bits.Add64(x[0], y[0], 0) z[1], carry = bits.Add64(x[1], y[1], carry) z[2], carry = bits.Add64(x[2], y[2], carry) z[3], _ = bits.Add64(x[3], y[3], carry) return z } // AddOverflow sets z to the sum x+y, and returns z and whether overflow occurred func (z *Int) AddOverflow(x, y *Int) (*Int, bool) { var carry uint64 z[0], carry = bits.Add64(x[0], y[0], 0) z[1], carry = bits.Add64(x[1], y[1], carry) z[2], carry = bits.Add64(x[2], y[2], carry) z[3], carry = bits.Add64(x[3], y[3], carry) return z, carry != 0 } // AddMod sets z to the sum ( x+y ) mod m, and returns z. // If m == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) AddMod(x, y, m *Int) *Int { // Fast path for m >= 2^192, with x and y at most slightly bigger than m. // This is always the case when x and y are already reduced modulo such m. if (m[3] != 0) && (x[3] <= m[3]) && (y[3] <= m[3]) { var ( gteC1 uint64 gteC2 uint64 tmpX Int tmpY Int res Int ) // reduce x/y modulo m if they are gte m tmpX[0], gteC1 = bits.Sub64(x[0], m[0], gteC1) tmpX[1], gteC1 = bits.Sub64(x[1], m[1], gteC1) tmpX[2], gteC1 = bits.Sub64(x[2], m[2], gteC1) tmpX[3], gteC1 = bits.Sub64(x[3], m[3], gteC1) tmpY[0], gteC2 = bits.Sub64(y[0], m[0], gteC2) tmpY[1], gteC2 = bits.Sub64(y[1], m[1], gteC2) tmpY[2], gteC2 = bits.Sub64(y[2], m[2], gteC2) tmpY[3], gteC2 = bits.Sub64(y[3], m[3], gteC2) if gteC1 == 0 { x = &tmpX } if gteC2 == 0 { y = &tmpY } var ( c1 uint64 c2 uint64 tmp Int ) res[0], c1 = bits.Add64(x[0], y[0], c1) res[1], c1 = bits.Add64(x[1], y[1], c1) res[2], c1 = bits.Add64(x[2], y[2], c1) res[3], c1 = bits.Add64(x[3], y[3], c1) tmp[0], c2 = bits.Sub64(res[0], m[0], c2) tmp[1], c2 = bits.Sub64(res[1], m[1], c2) tmp[2], c2 = bits.Sub64(res[2], m[2], c2) tmp[3], c2 = bits.Sub64(res[3], m[3], c2) // final sub was unnecessary if c1 == 0 && c2 != 0 { return z.Set(&res) } return z.Set(&tmp) } if m.IsZero() { return z.Clear() } if z == m { // z is an alias for m and will be overwritten by AddOverflow before m is read m = m.Clone() } if _, overflow := z.AddOverflow(x, y); overflow { sum := [5]uint64{z[0], z[1], z[2], z[3], 1} var quot [5]uint64 var rem Int udivrem(quot[:], sum[:], m, &rem) return z.Set(&rem) } return z.Mod(z, m) } // AddUint64 sets z to x + y, where y is a uint64, and returns z func (z *Int) AddUint64(x *Int, y uint64) *Int { var carry uint64 z[0], carry = bits.Add64(x[0], y, 0) z[1], carry = bits.Add64(x[1], 0, carry) z[2], carry = bits.Add64(x[2], 0, carry) z[3], _ = bits.Add64(x[3], 0, carry) return z } // PaddedBytes encodes a Int as a 0-padded byte slice. The length // of the slice is at least n bytes. // Example, z =1, n = 20 => [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] func (z *Int) PaddedBytes(n int) []byte { b := make([]byte, n) for i := 0; i < 32 && i < n; i++ { b[n-1-i] = byte(z[i/8] >> uint64(8*(i%8))) } return b } // SubUint64 set z to the difference x - y, where y is a uint64, and returns z func (z *Int) SubUint64(x *Int, y uint64) *Int { var carry uint64 z[0], carry = bits.Sub64(x[0], y, carry) z[1], carry = bits.Sub64(x[1], 0, carry) z[2], carry = bits.Sub64(x[2], 0, carry) z[3], _ = bits.Sub64(x[3], 0, carry) return z } // SubOverflow sets z to the difference x-y and returns z and true if the operation underflowed func (z *Int) SubOverflow(x, y *Int) (*Int, bool) { var carry uint64 z[0], carry = bits.Sub64(x[0], y[0], 0) z[1], carry = bits.Sub64(x[1], y[1], carry) z[2], carry = bits.Sub64(x[2], y[2], carry) z[3], carry = bits.Sub64(x[3], y[3], carry) return z, carry != 0 } // Sub sets z to the difference x-y func (z *Int) Sub(x, y *Int) *Int { var carry uint64 z[0], carry = bits.Sub64(x[0], y[0], 0) z[1], carry = bits.Sub64(x[1], y[1], carry) z[2], carry = bits.Sub64(x[2], y[2], carry) z[3], _ = bits.Sub64(x[3], y[3], carry) return z } // umulStep computes (hi * 2^64 + lo) = z + (x * y) + carry. func umulStep(z, x, y, carry uint64) (hi, lo uint64) { hi, lo = bits.Mul64(x, y) lo, carry = bits.Add64(lo, carry, 0) hi, _ = bits.Add64(hi, 0, carry) lo, carry = bits.Add64(lo, z, 0) hi, _ = bits.Add64(hi, 0, carry) return hi, lo } // umulHop computes (hi * 2^64 + lo) = z + (x * y) func umulHop(z, x, y uint64) (hi, lo uint64) { hi, lo = bits.Mul64(x, y) lo, carry := bits.Add64(lo, z, 0) hi, _ = bits.Add64(hi, 0, carry) return hi, lo } // umul computes full 256 x 256 -> 512 multiplication. func umul(x, y *Int, res *[8]uint64) { var ( carry, carry4, carry5, carry6 uint64 res1, res2, res3, res4, res5 uint64 ) carry, res[0] = bits.Mul64(x[0], y[0]) carry, res1 = umulHop(carry, x[1], y[0]) carry, res2 = umulHop(carry, x[2], y[0]) carry4, res3 = umulHop(carry, x[3], y[0]) carry, res[1] = umulHop(res1, x[0], y[1]) carry, res2 = umulStep(res2, x[1], y[1], carry) carry, res3 = umulStep(res3, x[2], y[1], carry) carry5, res4 = umulStep(carry4, x[3], y[1], carry) carry, res[2] = umulHop(res2, x[0], y[2]) carry, res3 = umulStep(res3, x[1], y[2], carry) carry, res4 = umulStep(res4, x[2], y[2], carry) carry6, res5 = umulStep(carry5, x[3], y[2], carry) carry, res[3] = umulHop(res3, x[0], y[3]) carry, res[4] = umulStep(res4, x[1], y[3], carry) carry, res[5] = umulStep(res5, x[2], y[3], carry) res[7], res[6] = umulStep(carry6, x[3], y[3], carry) } // Mul sets z to the product x*y func (z *Int) Mul(x, y *Int) *Int { var ( carry0, carry1, carry2 uint64 res1, res2 uint64 x0, x1, x2, x3 = x[0], x[1], x[2], x[3] y0, y1, y2, y3 = y[0], y[1], y[2], y[3] ) carry0, z[0] = bits.Mul64(x0, y0) carry0, res1 = umulHop(carry0, x1, y0) carry0, res2 = umulHop(carry0, x2, y0) carry1, z[1] = umulHop(res1, x0, y1) carry1, res2 = umulStep(res2, x1, y1, carry1) carry2, z[2] = umulHop(res2, x0, y2) z[3] = x3*y0 + x2*y1 + x0*y3 + x1*y2 + carry0 + carry1 + carry2 return z } // MulOverflow sets z to the product x*y, and returns z and whether overflow occurred func (z *Int) MulOverflow(x, y *Int) (*Int, bool) { var p [8]uint64 umul(x, y, &p) copy(z[:], p[:4]) return z, (p[4] | p[5] | p[6] | p[7]) != 0 } func (z *Int) squared() { var ( carry0, carry1, carry2 uint64 res0, res1, res2, res3 uint64 ) carry0, res0 = bits.Mul64(z[0], z[0]) carry0, res1 = umulHop(carry0, z[0], z[1]) carry0, res2 = umulHop(carry0, z[0], z[2]) carry1, res1 = umulHop(res1, z[0], z[1]) carry1, res2 = umulStep(res2, z[1], z[1], carry1) carry2, res2 = umulHop(res2, z[0], z[2]) res3 = 2*(z[0]*z[3]+z[1]*z[2]) + carry0 + carry1 + carry2 z[0], z[1], z[2], z[3] = res0, res1, res2, res3 } // isBitSet returns true if bit n-th is set, where n = 0 is LSB. // The n must be <= 255. func (z *Int) isBitSet(n uint) bool { return (z[n/64] & (1 << (n % 64))) != 0 } // addTo computes x += y. // Requires len(x) >= len(y) > 0. func addTo(x, y []uint64) uint64 { var carry uint64 _ = x[len(y)-1] // bounds check hint to compiler; see golang.org/issue/14808 for i := 0; i < len(y); i++ { x[i], carry = bits.Add64(x[i], y[i], carry) } return carry } // subMulTo computes x -= y * multiplier. // Requires len(x) >= len(y) > 0. func subMulTo(x, y []uint64, multiplier uint64) uint64 { var borrow uint64 _ = x[len(y)-1] // bounds check hint to compiler; see golang.org/issue/14808 for i := 0; i < len(y); i++ { s, carry1 := bits.Sub64(x[i], borrow, 0) ph, pl := bits.Mul64(y[i], multiplier) t, carry2 := bits.Sub64(s, pl, 0) x[i] = t borrow = ph + carry1 + carry2 } return borrow } // udivremBy1 divides u by single normalized word d and produces both quotient and remainder. // The quotient is stored in provided quot. func udivremBy1(quot, u []uint64, d uint64) (rem uint64) { reciprocal := reciprocal2by1(d) rem = u[len(u)-1] // Set the top word as remainder. for j := len(u) - 2; j >= 0; j-- { quot[j], rem = udivrem2by1(rem, u[j], d, reciprocal) } return rem } // udivremKnuth implements the division of u by normalized multiple word d from the Knuth's division algorithm. // The quotient is stored in provided quot - len(u)-len(d) words. // Updates u to contain the remainder - len(d) words. func udivremKnuth(quot, u, d []uint64) { dh := d[len(d)-1] dl := d[len(d)-2] reciprocal := reciprocal2by1(dh) for j := len(u) - len(d) - 1; j >= 0; j-- { u2 := u[j+len(d)] u1 := u[j+len(d)-1] u0 := u[j+len(d)-2] var qhat, rhat uint64 if u2 >= dh { // Division overflows. qhat = ^uint64(0) // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). } else { qhat, rhat = udivrem2by1(u2, u1, dh, reciprocal) ph, pl := bits.Mul64(qhat, dl) if ph > rhat || (ph == rhat && pl > u0) { qhat-- // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). } } // Multiply and subtract. borrow := subMulTo(u[j:], d, qhat) u[j+len(d)] = u2 - borrow if u2 < borrow { // Too much subtracted, add back. qhat-- u[j+len(d)] += addTo(u[j:], d) } quot[j] = qhat // Store quotient digit. } } // udivrem divides u by d and produces both quotient and remainder. // The quotient is stored in provided quot - len(u)-len(d)+1 words. // It loosely follows the Knuth's division algorithm (sometimes referenced as "schoolbook" division) using 64-bit words. // See Knuth, Volume 2, section 4.3.1, Algorithm D. func udivrem(quot, u []uint64, d, rem *Int) { var dLen int for i := len(d) - 1; i >= 0; i-- { if d[i] != 0 { dLen = i + 1 break } } shift := uint(bits.LeadingZeros64(d[dLen-1])) var dnStorage Int dn := dnStorage[:dLen] for i := dLen - 1; i > 0; i-- { dn[i] = (d[i] << shift) | (d[i-1] >> (64 - shift)) } dn[0] = d[0] << shift var uLen int for i := len(u) - 1; i >= 0; i-- { if u[i] != 0 { uLen = i + 1 break } } if uLen < dLen { if rem != nil { copy(rem[:], u) } return } var unStorage [9]uint64 un := unStorage[:uLen+1] un[uLen] = u[uLen-1] >> (64 - shift) for i := uLen - 1; i > 0; i-- { un[i] = (u[i] << shift) | (u[i-1] >> (64 - shift)) } un[0] = u[0] << shift // TODO: Skip the highest word of numerator if not significant. if dLen == 1 { r := udivremBy1(quot, un, dn[0]) if rem != nil { rem.SetUint64(r >> shift) } return } udivremKnuth(quot, un, dn) if rem != nil { for i := 0; i < dLen-1; i++ { rem[i] = (un[i] >> shift) | (un[i+1] << (64 - shift)) } rem[dLen-1] = un[dLen-1] >> shift } } // Div sets z to the quotient x/y for returns z. // If y == 0, z is set to 0 func (z *Int) Div(x, y *Int) *Int { if y.IsZero() || y.Gt(x) { return z.Clear() } if x.Eq(y) { return z.SetOne() } // Shortcut some cases if x.IsUint64() { return z.SetUint64(x.Uint64() / y.Uint64()) } // At this point, we know // x/y ; x > y > 0 var quot Int udivrem(quot[:], x[:], y, nil) return z.Set(") } // Mod sets z to the modulus x%y for y != 0 and returns z. // If y == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) Mod(x, y *Int) *Int { if y.IsZero() || x.Eq(y) { return z.Clear() } if x.Lt(y) { return z.Set(x) } // At this point: // x != 0 // y != 0 // x > y // Shortcut trivial case if x.IsUint64() { return z.SetUint64(x.Uint64() % y.Uint64()) } var quot, rem Int udivrem(quot[:], x[:], y, &rem) return z.Set(&rem) } // DivMod sets z to the quotient x div y and m to the modulus x mod y and returns the pair (z, m) for y != 0. // If y == 0, both z and m are set to 0 (OBS: differs from the big.Int) func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) { if z == m { // We return both z and m as results, if they are aliased, we have to // un-alias them to be able to return separate results. m = new(Int).Set(m) } if y.IsZero() { return z.Clear(), m.Clear() } if x.Eq(y) { return z.SetOne(), m.Clear() } if x.Lt(y) { m.Set(x) return z.Clear(), m } // At this point: // x != 0 // y != 0 // x > y // Shortcut trivial case if x.IsUint64() { x0, y0 := x.Uint64(), y.Uint64() return z.SetUint64(x0 / y0), m.SetUint64(x0 % y0) } var quot, rem Int udivrem(quot[:], x[:], y, &rem) return z.Set("), m.Set(&rem) } // SMod interprets x and y as two's complement signed integers, // sets z to (sign x) * { abs(x) modulus abs(y) } // If y == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) SMod(x, y *Int) *Int { ys := y.Sign() xs := x.Sign() // abs x if xs == -1 { x = new(Int).Neg(x) } // abs y if ys == -1 { y = new(Int).Neg(y) } z.Mod(x, y) if xs == -1 { z.Neg(z) } return z } // MulModWithReciprocal calculates the modulo-m multiplication of x and y // and returns z, using the reciprocal of m provided as the mu parameter. // Use uint256.Reciprocal to calculate mu from m. // If m == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) MulModWithReciprocal(x, y, m *Int, mu *[5]uint64) *Int { if x.IsZero() || y.IsZero() || m.IsZero() { return z.Clear() } var p [8]uint64 umul(x, y, &p) if m[3] != 0 { return z.reduce4(&p, m, mu) } var ( pl Int ph Int ) pl[0], pl[1], pl[2], pl[3] = p[0], p[1], p[2], p[3] ph[0], ph[1], ph[2], ph[3] = p[4], p[5], p[6], p[7] // If the multiplication is within 256 bits use Mod(). if ph.IsZero() { return z.Mod(&pl, m) } var quot [8]uint64 var rem Int udivrem(quot[:], p[:], m, &rem) return z.Set(&rem) } // MulMod calculates the modulo-m multiplication of x and y and // returns z. // If m == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) MulMod(x, y, m *Int) *Int { if x.IsZero() || y.IsZero() || m.IsZero() { return z.Clear() } var p [8]uint64 umul(x, y, &p) if m[3] != 0 { mu := Reciprocal(m) return z.reduce4(&p, m, &mu) } var ( pl Int ph Int ) pl[0], pl[1], pl[2], pl[3] = p[0], p[1], p[2], p[3] ph[0], ph[1], ph[2], ph[3] = p[4], p[5], p[6], p[7] // If the multiplication is within 256 bits use Mod(). if ph.IsZero() { return z.Mod(&pl, m) } var quot [8]uint64 var rem Int udivrem(quot[:], p[:], m, &rem) return z.Set(&rem) } // MulDivOverflow calculates (x*y)/d with full precision, returns z and whether overflow occurred in multiply process (result does not fit to 256-bit). // computes 512-bit multiplication and 512 by 256 division. func (z *Int) MulDivOverflow(x, y, d *Int) (*Int, bool) { if x.IsZero() || y.IsZero() || d.IsZero() { return z.Clear(), false } var p [8]uint64 umul(x, y, &p) var quot [8]uint64 udivrem(quot[:], p[:], d, nil) z[0], z[1], z[2], z[3] = quot[0], quot[1], quot[2], quot[3] return z, (quot[4] | quot[5] | quot[6] | quot[7]) != 0 } // Abs interprets x as a two's complement signed number, // and sets z to the absolute value // // Abs(0) = 0 // Abs(1) = 1 // Abs(2**255) = -2**255 // Abs(2**256-1) = -1 func (z *Int) Abs(x *Int) *Int { if x[3] < 0x8000000000000000 { return z.Set(x) } return z.Sub(new(Int), x) } // Neg returns -x mod 2**256. func (z *Int) Neg(x *Int) *Int { return z.Sub(new(Int), x) } // SDiv interprets n and d as two's complement signed integers, // does a signed division on the two operands and sets z to the result. // If d == 0, z is set to 0 func (z *Int) SDiv(n, d *Int) *Int { if n.Sign() > 0 { if d.Sign() > 0 { // pos / pos z.Div(n, d) return z } else { // pos / neg z.Div(n, new(Int).Neg(d)) return z.Neg(z) } } if d.Sign() < 0 { // neg / neg z.Div(new(Int).Neg(n), new(Int).Neg(d)) return z } // neg / pos z.Div(new(Int).Neg(n), d) return z.Neg(z) } // Sign returns: // // -1 if z < 0 // 0 if z == 0 // +1 if z > 0 // // Where z is interpreted as a two's complement signed number func (z *Int) Sign() int { if z.IsZero() { return 0 } if z[3] < 0x8000000000000000 { return 1 } return -1 } // BitLen returns the number of bits required to represent z func (z *Int) BitLen() int { switch { case z[3] != 0: return 192 + bits.Len64(z[3]) case z[2] != 0: return 128 + bits.Len64(z[2]) case z[1] != 0: return 64 + bits.Len64(z[1]) default: return bits.Len64(z[0]) } } // ByteLen returns the number of bytes required to represent z func (z *Int) ByteLen() int { return (z.BitLen() + 7) / 8 } func (z *Int) lsh64(x *Int) *Int { z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0 return z } func (z *Int) lsh128(x *Int) *Int { z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0 return z } func (z *Int) lsh192(x *Int) *Int { z[3], z[2], z[1], z[0] = x[0], 0, 0, 0 return z } func (z *Int) rsh64(x *Int) *Int { z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1] return z } func (z *Int) rsh128(x *Int) *Int { z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2] return z } func (z *Int) rsh192(x *Int) *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, x[3] return z } func (z *Int) srsh64(x *Int) *Int { z[3], z[2], z[1], z[0] = math.MaxUint64, x[3], x[2], x[1] return z } func (z *Int) srsh128(x *Int) *Int { z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, x[3], x[2] return z } func (z *Int) srsh192(x *Int) *Int { z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, math.MaxUint64, x[3] return z } // Not sets z = ^x and returns z. func (z *Int) Not(x *Int) *Int { z[3], z[2], z[1], z[0] = ^x[3], ^x[2], ^x[1], ^x[0] return z } // Gt returns true if z > x func (z *Int) Gt(x *Int) bool { return x.Lt(z) } // Slt interprets z and x as signed integers, and returns // true if z < x func (z *Int) Slt(x *Int) bool { zSign := z.Sign() xSign := x.Sign() switch { case zSign >= 0 && xSign < 0: return false case zSign < 0 && xSign >= 0: return true default: return z.Lt(x) } } // Sgt interprets z and x as signed integers, and returns // true if z > x func (z *Int) Sgt(x *Int) bool { zSign := z.Sign() xSign := x.Sign() switch { case zSign >= 0 && xSign < 0: return true case zSign < 0 && xSign >= 0: return false default: return z.Gt(x) } } // Lt returns true if z < x func (z *Int) Lt(x *Int) bool { // z < x <=> z - x < 0 i.e. when subtraction overflows. _, carry := bits.Sub64(z[0], x[0], 0) _, carry = bits.Sub64(z[1], x[1], carry) _, carry = bits.Sub64(z[2], x[2], carry) _, carry = bits.Sub64(z[3], x[3], carry) return carry != 0 } // SetUint64 sets z to the value x func (z *Int) SetUint64(x uint64) *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, x return z } // Eq returns true if z == x func (z *Int) Eq(x *Int) bool { return (z[0] == x[0]) && (z[1] == x[1]) && (z[2] == x[2]) && (z[3] == x[3]) } // Cmp compares z and x and returns: // // -1 if z < x // 0 if z == x // +1 if z > x func (z *Int) Cmp(x *Int) (r int) { // z < x <=> z - x < 0 i.e. when subtraction overflows. d0, carry := bits.Sub64(z[0], x[0], 0) d1, carry := bits.Sub64(z[1], x[1], carry) d2, carry := bits.Sub64(z[2], x[2], carry) d3, carry := bits.Sub64(z[3], x[3], carry) if carry == 1 { return -1 } if d0|d1|d2|d3 == 0 { return 0 } return 1 } // CmpUint64 compares z and x and returns: // // -1 if z < x // 0 if z == x // +1 if z > x func (z *Int) CmpUint64(x uint64) int { if z[0] > x || (z[1]|z[2]|z[3]) != 0 { return 1 } if z[0] == x { return 0 } return -1 } // CmpBig compares z and x and returns: // // -1 if z < x // 0 if z == x // +1 if z > x func (z *Int) CmpBig(x *big.Int) (r int) { // If x is negative, it's surely smaller (z > x) if x.Sign() == -1 { return 1 } y := new(Int) if y.SetFromBig(x) { // overflow // z < x return -1 } return z.Cmp(y) } // LtUint64 returns true if z is smaller than n func (z *Int) LtUint64(n uint64) bool { return z[0] < n && (z[1]|z[2]|z[3]) == 0 } // GtUint64 returns true if z is larger than n func (z *Int) GtUint64(n uint64) bool { return z[0] > n || (z[1]|z[2]|z[3]) != 0 } // IsUint64 reports whether z can be represented as a uint64. func (z *Int) IsUint64() bool { return (z[1] | z[2] | z[3]) == 0 } // IsZero returns true if z == 0 func (z *Int) IsZero() bool { return (z[0] | z[1] | z[2] | z[3]) == 0 } // Clear sets z to 0 func (z *Int) Clear() *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, 0 return z } // SetAllOne sets all the bits of z to 1 func (z *Int) SetAllOne() *Int { z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, math.MaxUint64, math.MaxUint64 return z } // SetOne sets z to 1 func (z *Int) SetOne() *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, 1 return z } // Lsh sets z = x << n and returns z. func (z *Int) Lsh(x *Int, n uint) *Int { switch { case n == 0: return z.Set(x) case n >= 192: z.lsh192(x) n -= 192 z[3] <<= n return z case n >= 128: z.lsh128(x) n -= 128 z[3] = (z[3] << n) | (z[2] >> (64 - n)) z[2] <<= n return z case n >= 64: z.lsh64(x) n -= 64 z[3] = (z[3] << n) | (z[2] >> (64 - n)) z[2] = (z[2] << n) | (z[1] >> (64 - n)) z[1] <<= n return z default: z.Set(x) z[3] = (z[3] << n) | (z[2] >> (64 - n)) z[2] = (z[2] << n) | (z[1] >> (64 - n)) z[1] = (z[1] << n) | (z[0] >> (64 - n)) z[0] <<= n return z } } // Rsh sets z = x >> n and returns z. func (z *Int) Rsh(x *Int, n uint) *Int { switch { case n == 0: return z.Set(x) case n >= 192: z.rsh192(x) n -= 192 z[0] >>= n return z case n >= 128: z.rsh128(x) n -= 128 z[0] = (z[0] >> n) | (z[1] << (64 - n)) z[1] >>= n return z case n >= 64: z.rsh64(x) n -= 64 z[0] = (z[0] >> n) | (z[1] << (64 - n)) z[1] = (z[1] >> n) | (z[2] << (64 - n)) z[2] >>= n return z default: z.Set(x) z[0] = (z[0] >> n) | (z[1] << (64 - n)) z[1] = (z[1] >> n) | (z[2] << (64 - n)) z[2] = (z[2] >> n) | (z[3] << (64 - n)) z[3] >>= n return z } } // SRsh (Signed/Arithmetic right shift) // considers z to be a signed integer, during right-shift // and sets z = x >> n and returns z. func (z *Int) SRsh(x *Int, n uint) *Int { // If the MSB is 0, SRsh is same as Rsh. if !x.isBitSet(255) { return z.Rsh(x, n) } var a uint64 = math.MaxUint64 << (64 - n%64) switch { case n == 0: return z.Set(x) case n >= 256: return z.SetAllOne() case n >= 192: z.srsh192(x) n -= 192 z[0] = (z[0] >> n) | a return z case n >= 128: z.srsh128(x) n -= 128 z[0] = (z[0] >> n) | (z[1] << (64 - n)) z[1] = (z[1] >> n) | a return z case n >= 64: z.srsh64(x) n -= 64 z[0] = (z[0] >> n) | (z[1] << (64 - n)) z[1] = (z[1] >> n) | (z[2] << (64 - n)) z[2] = (z[2] >> n) | a return z default: z.Set(x) z[0] = (z[0] >> n) | (z[1] << (64 - n)) z[1] = (z[1] >> n) | (z[2] << (64 - n)) z[2] = (z[2] >> n) | (z[3] << (64 - n)) z[3] = (z[3] >> n) | a return z } } // Set sets z to x and returns z. func (z *Int) Set(x *Int) *Int { z[0], z[1], z[2], z[3] = x[0], x[1], x[2], x[3] return z } // Or sets z = x | y and returns z. func (z *Int) Or(x, y *Int) *Int { z[0] = x[0] | y[0] z[1] = x[1] | y[1] z[2] = x[2] | y[2] z[3] = x[3] | y[3] return z } // And sets z = x & y and returns z. func (z *Int) And(x, y *Int) *Int { z[0] = x[0] & y[0] z[1] = x[1] & y[1] z[2] = x[2] & y[2] z[3] = x[3] & y[3] return z } // Xor sets z = x ^ y and returns z. func (z *Int) Xor(x, y *Int) *Int { z[0] = x[0] ^ y[0] z[1] = x[1] ^ y[1] z[2] = x[2] ^ y[2] z[3] = x[3] ^ y[3] return z } // Byte sets z to the value of the byte at position n, // with z considered as a big-endian 32-byte integer. // if n >= 32, z is set to 0 // Example: z=5, n=31 => 5 func (z *Int) Byte(n *Int) *Int { index, overflow := n.Uint64WithOverflow() if overflow || index >= 32 { return z.Clear() } // in z, z[0] is the least significant number := z[4-1-index/8] offset := (index & 0x7) << 3 // 8 * (index % 8) z[0] = (number >> (56 - offset)) & 0xff z[3], z[2], z[1] = 0, 0, 0 return z } // Exp sets z = base**exponent mod 2**256, and returns z. func (z *Int) Exp(base, exponent *Int) *Int { var ( res = Int{1, 0, 0, 0} multiplier = *base expBitLen = exponent.BitLen() curBit = 0 word = exponent[0] even = base[0]&1 == 0 ) if even && expBitLen > 8 { return z.Clear() } for ; curBit < expBitLen && curBit < 64; curBit++ { if word&1 == 1 { res.Mul(&res, &multiplier) } multiplier.squared() word >>= 1 } if even { // If the base was even, we are finished now return z.Set(&res) } word = exponent[1] for ; curBit < expBitLen && curBit < 128; curBit++ { if word&1 == 1 { res.Mul(&res, &multiplier) } multiplier.squared() word >>= 1 } word = exponent[2] for ; curBit < expBitLen && curBit < 192; curBit++ { if word&1 == 1 { res.Mul(&res, &multiplier) } multiplier.squared() word >>= 1 } word = exponent[3] for ; curBit < expBitLen && curBit < 256; curBit++ { if word&1 == 1 { res.Mul(&res, &multiplier) } multiplier.squared() word >>= 1 } return z.Set(&res) } // ExtendSign extends length of two’s complement signed integer, // sets z to // - x if byteNum > 30 // - x interpreted as a signed number with sign-bit at (byteNum*8+7), extended to the full 256 bits // // and returns z. func (z *Int) ExtendSign(x, byteNum *Int) *Int { // This implementation is based on evmone. See https://github.com/ethereum/evmone/pull/390 if byteNum.GtUint64(30) { return z.Set(x) } e := byteNum.Uint64() z.Set(x) signWordIndex := e >> 3 // Index of the word with the sign bit. signByteIndex := e & 7 // Index of the sign byte in the sign word. signWord := z[signWordIndex] signByteOffset := signByteIndex << 3 signByte := signWord >> signByteOffset // Move sign byte to position 0. // Sign-extend the "sign" byte and move it to the right position. Value bits are zeros. sextByte := uint64(int64(int8(signByte))) sext := sextByte << signByteOffset signMask := uint64(math.MaxUint64 << signByteOffset) value := signWord & ^signMask // Reset extended bytes. z[signWordIndex] = sext | value // Combine the result word. // Produce bits (all zeros or ones) for extended words. This is done by SAR of // the sign-extended byte. Shift by any value 7-63 would work. signEx := uint64(int64(sextByte) >> 8) switch signWordIndex { case 2: z[3] = signEx return z case 1: z[3], z[2] = signEx, signEx return z case 0: z[3], z[2], z[1] = signEx, signEx, signEx return z default: return z } } // Sqrt sets z to ⌊√x⌋, the largest integer such that z² ≤ x, and returns z. func (z *Int) Sqrt(x *Int) *Int { // This implementation of Sqrt is based on big.Int (see math/big/nat.go). if x.IsUint64() { var ( x0 uint64 = x.Uint64() z1 uint64 = 1 << ((bits.Len64(x0) + 1) / 2) z2 uint64 ) if x0 < 2 { return z.SetUint64(x0) } for { z2 = (z1 + x0/z1) >> 1 if z2 >= z1 { return z.SetUint64(z1) } z1 = z2 } } z1 := NewInt(1) z2 := NewInt(0) // Start with value known to be too large and repeat "z = ⌊(z + ⌊x/z⌋)/2⌋" until it stops getting smaller. z1.Lsh(z1, uint(x.BitLen()+1)/2) // must be ≥ √x // We can do the first division outside the loop z2.Rsh(x, uint(x.BitLen()+1)/2) // The first div is equal to a right shift for { z2.Add(z2, z1) // z2 = z2.Rsh(z2, 1) -- the code below does a 1-bit rsh faster z2[0] = (z2[0] >> 1) | z2[1]<<63 z2[1] = (z2[1] >> 1) | z2[2]<<63 z2[2] = (z2[2] >> 1) | z2[3]<<63 z2[3] >>= 1 if !z2.Lt(z1) { return z.Set(z1) } z1.Set(z2) // Next iteration of the loop // z2.Div(x, z1) -- x > MaxUint64, x > z1 > 0 z2.Clear() udivrem(z2[:], x[:], z1, nil) } } var ( // pows64 contains 10^0 ... 10^19 pows64 = [20]uint64{ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, } // pows contain 10 ** 20 ... 10 ** 80 pows = [60]Int{ {7766279631452241920, 5, 0, 0}, {3875820019684212736, 54, 0, 0}, {1864712049423024128, 542, 0, 0}, {200376420520689664, 5421, 0, 0}, {2003764205206896640, 54210, 0, 0}, {1590897978359414784, 542101, 0, 0}, {15908979783594147840, 5421010, 0, 0}, {11515845246265065472, 54210108, 0, 0}, {4477988020393345024, 542101086, 0, 0}, {7886392056514347008, 5421010862, 0, 0}, {5076944270305263616, 54210108624, 0, 0}, {13875954555633532928, 542101086242, 0, 0}, {9632337040368467968, 5421010862427, 0, 0}, {4089650035136921600, 54210108624275, 0, 0}, {4003012203950112768, 542101086242752, 0, 0}, {3136633892082024448, 5421010862427522, 0, 0}, {12919594847110692864, 54210108624275221, 0, 0}, {68739955140067328, 542101086242752217, 0, 0}, {687399551400673280, 5421010862427522170, 0, 0}, {6873995514006732800, 17316620476856118468, 2, 0}, {13399722918938673152, 7145508105175220139, 29, 0}, {4870020673419870208, 16114848830623546549, 293, 0}, {11806718586779598848, 13574535716559052564, 2938, 0}, {7386721425538678784, 6618148649623664334, 29387, 0}, {80237960548581376, 10841254275107988496, 293873, 0}, {802379605485813760, 16178822382532126880, 2938735, 0}, {8023796054858137600, 14214271235644855872, 29387358, 0}, {6450984253743169536, 13015503840481697412, 293873587, 0}, {9169610316303040512, 1027829888850112811, 2938735877, 0}, {17909126868192198656, 10278298888501128114, 29387358770, 0}, {13070572018536022016, 10549268516463523069, 293873587705, 0}, {1578511669393358848, 13258964796087472617, 2938735877055, 0}, {15785116693933588480, 3462439444907864858, 29387358770557, 0}, {10277214349659471872, 16177650375369096972, 293873587705571, 0}, {10538423128046960640, 14202551164014556797, 2938735877055718, 0}, {13150510911921848320, 12898303124178706663, 29387358770557187, 0}, {2377900603251621888, 18302566799529756941, 293873587705571876, 0}, {5332261958806667264, 17004971331911604867, 2938735877055718769, 0}, {16429131440647569408, 4029016655730084128, 10940614696847636083, 1}, {16717361816799281152, 3396678409881738056, 17172426599928602752, 15}, {1152921504606846976, 15520040025107828953, 5703569335900062977, 159}, {11529215046068469760, 7626447661401876602, 1695461137871974930, 1593}, {4611686018427387904, 2477500319180559562, 16954611378719749304, 15930}, {9223372036854775808, 6328259118096044006, 3525417123811528497, 159309}, {0, 7942358959831785217, 16807427164405733357, 1593091}, {0, 5636613303479645706, 2053574980671369030, 15930919}, {0, 1025900813667802212, 2089005733004138687, 159309191}, {0, 10259008136678022120, 2443313256331835254, 1593091911}, {0, 10356360998232463120, 5986388489608800929, 15930919111}, {0, 11329889613776873120, 4523652674959354447, 159309191113}, {0, 2618431695511421504, 8343038602174441244, 1593091911132}, {0, 7737572881404663424, 9643409726906205977, 15930919111324}, {0, 3588752519208427776, 4200376900514301694, 159309191113245}, {0, 17440781118374726144, 5110280857723913709, 1593091911132452}, {0, 8387114520361296896, 14209320429820033867, 15930919111324522}, {0, 10084168908774762496, 12965995782233477362, 159309191113245227}, {0, 8607968719199866880, 532749306367912313, 1593091911132452277}, {0, 12292710897160462336, 5327493063679123134, 15930919111324522770}, {0, 12246644529347313664, 16381442489372128114, 11735238523568814774}, {0, 11785980851215826944, 16240472304044868218, 6671920793430838052}, } ) // Log10 returns the log in base 10, floored to nearest integer. // **OBS** This method returns '0' for '0', not `-Inf`. func (z *Int) Log10() uint { // The following algorithm is taken from "Bit twiddling hacks" // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 // // The idea is that log10(z) = log2(z) / log2(10) // log2(z) trivially is z.Bitlen() // 1/log2(10) is a constant ~ 1233 / 4096. The approximation is correct up to 5 digit after // the decimal point and it seems no further refinement is needed. // Our tests check all boundary cases anyway. bitlen := z.BitLen() if bitlen == 0 { return 0 } t := (bitlen + 1) * 1233 >> 12 if bitlen <= 64 && z[0] < pows64[t] || t >= 20 && z.Lt(&pows[t-20]) { return uint(t - 1) } return uint(t) } uint256-1.3.2/uint256_test.go000066400000000000000000000637121472460254700155570ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2018-2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "bytes" "crypto/rand" "encoding/hex" "fmt" "math" "math/big" "testing" ) func hex2Bytes(str string) []byte { h, _ := hex.DecodeString(str) return h } func checkOverflow(b *big.Int, f *Int, overflow bool) error { max := big.NewInt(0).SetBytes(hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) shouldOverflow := b.Cmp(max) > 0 if overflow != shouldOverflow { return fmt.Errorf("Overflow should be %v, was %v\nf= %x\nb= %x\b", shouldOverflow, overflow, f, b) } return nil } func randNums() (*big.Int, *Int) { //How many bits? 0-256 nbits, _ := rand.Int(rand.Reader, big.NewInt(257)) //Max random value, a 130-bits integer, i.e 2^130 max := new(big.Int) max.Exp(big.NewInt(2), big.NewInt(nbits.Int64()), nil) b, _ := rand.Int(rand.Reader, max) f, overflow := FromBig(b) if err := checkOverflow(b, f, overflow); err != nil { panic(err) } return b, f } func randHighNums() (*big.Int, *Int) { //How many bits? 0-256 nbits := int64(256) //Max random value, a 130-bits integer, i.e 2^130 max := new(big.Int) max.Exp(big.NewInt(2), big.NewInt(nbits), nil) //Generate cryptographically strong pseudo-random between 0 - max b, _ := rand.Int(rand.Reader, max) f, overflow := FromBig(b) if err := checkOverflow(b, f, overflow); err != nil { panic(err) } return b, f } func checkEq(b *big.Int, f *Int) bool { f2, _ := FromBig(b) return f.Eq(f2) } func requireEq(t *testing.T, exp *big.Int, got *Int, txt string) bool { expF, _ := FromBig(exp) if !expF.Eq(got) { t.Errorf("got %x expected %x: %v\n", got, expF, txt) return false } return true } func TestRandomSubOverflow(t *testing.T) { for i := 0; i < 10000; i++ { b, f1 := randNums() b2, f2 := randNums() f1a, f2a := f1.Clone(), f2.Clone() _, overflow := f1.SubOverflow(f1, f2) b.Sub(b, b2) // check overflow if have, want := overflow, b.Cmp(big.NewInt(0)) < 0; have != want { t.Fatalf("underflow should be %v, was %v\nf= %x\nb= %x\b", have, want, f1, b) } if eq := checkEq(b, f1); !eq { t.Fatalf("Expected equality:\nf1= %x\nf2= %x\n[ - ]==\nf= %x\nb= %x\n", f1a, f2a, f1, b) } } } func TestRandomMulOverflow(t *testing.T) { for i := 0; i < 10000; i++ { b, f1 := randNums() b2, f2 := randNums() f1a, f2a := f1.Clone(), f2.Clone() _, overflow := f1.MulOverflow(f1, f2) b.Mul(b, b2) if err := checkOverflow(b, f1, overflow); err != nil { t.Fatal(err) } if eq := checkEq(b, f1); !eq { t.Fatalf("Expected equality:\nf1= %x\nf2= %x\n[ - ]==\nf= %x\nb= %x\n", f1a, f2a, f1, b) } } } func set3Int(s1, s2, s3, d1, d2, d3 *Int) { d1.Set(s1) d2.Set(s2) d3.Set(s3) } func set3Big(s1, s2, s3, d1, d2, d3 *big.Int) { d1.Set(s1) d2.Set(s2) d3.Set(s3) } func TestRandomMulMod(t *testing.T) { for i := 0; i < 10000; i++ { b1, f1 := randNums() b2, f2 := randNums() b3, f3 := randNums() b4, f4 := randNums() for b4.Cmp(big.NewInt(0)) == 0 { b4, f4 = randNums() } f1.MulMod(f2, f3, f4) b1.Mod(big.NewInt(0).Mul(b2, b3), b4) if !checkEq(b1, f1) { t.Fatalf("Expected equality:\nf2= %x\nf3= %x\nf4= %x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f4, f1, b1) } f1.mulModWithReciprocalWrapper(f2, f3, f4) if !checkEq(b1, f1) { t.Fatalf("Expected equality:\nf2= %x\nf3= %x\nf4= %x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f4, f1, b1) } } // Tests related to powers of 2 f_minusone := &Int{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} b_one := big.NewInt(1) b_minusone := big.NewInt(0) b_minusone = b_minusone.Sub(b_minusone, b_one) for i := uint(0); i < 256; i++ { b := big.NewInt(0) f := NewInt(0) t1, t2, t3 := b, b, b u1, u2, u3 := f, f, f b1 := b.Lsh(b, i) f1 := f.Lsh(f, i) b2, f2 := randNums() for b2.Cmp(big.NewInt(0)) == 0 { b2, f2 = randNums() } b3, f3 := randNums() for b3.Cmp(big.NewInt(0)) == 0 { b3, f3 = randNums() } // Tests with one operand a power of 2 set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t1, t2), t3) f.MulMod(u1, u2, u3) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf1= 0x%x\nf2= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f2, f3, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t1, t3), t2) f.MulMod(u1, u3, u2) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf1= 0x%x\nf3= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f3, f2, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t2, t1), t3) f.MulMod(u2, u1, u3) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf2= 0x%x\nf1= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f1, f3, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t2, t3), t1) f.MulMod(u2, u3, u1) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf2= 0x%x\nf3= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f1, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t3, t1), t2) f.MulMod(u3, u1, u2) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf3= 0x%x\nf1= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f1, f2, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t3, t2), t1) f.MulMod(u3, u2, u1) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf3= 0x%x\nf2= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f2, f1, f, b) } // Tests with one operand 2^256 minus a power of 2 f1.Xor(f1, f_minusone) b1.Xor(b1, b_minusone) set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t1, t2), t3) f.MulMod(u1, u2, u3) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf1= 0x%x\nf2= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f2, f3, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t1, t3), t2) f.MulMod(u1, u3, u2) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf1= 0x%x\nf3= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f3, f2, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t2, t1), t3) f.MulMod(u2, u1, u3) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf2= 0x%x\nf1= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f1, f3, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t2, t3), t1) f.MulMod(u2, u3, u1) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf2= 0x%x\nf3= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f1, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t3, t1), t2) f.MulMod(u3, u1, u2) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf3= 0x%x\nf1= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f1, f2, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t3, t2), t1) f.MulMod(u3, u2, u1) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf3= 0x%x\nf2= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f2, f1, f, b) } f1.Xor(f1, f_minusone) b1.Xor(b1, b_minusone) // Tests with one operand a power of 2 plus 1 b1.Add(b1, b_one) f1.AddUint64(f1, 1) set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t1, t2), t3) f.MulMod(u1, u2, u3) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf1= 0x%x\nf2= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f2, f3, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t1, t3), t2) f.MulMod(u1, u3, u2) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf1= 0x%x\nf3= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f3, f2, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t2, t1), t3) f.MulMod(u2, u1, u3) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf2= 0x%x\nf1= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f1, f3, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t2, t3), t1) f.MulMod(u2, u3, u1) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf2= 0x%x\nf3= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f1, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t3, t1), t2) f.MulMod(u3, u1, u2) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf3= 0x%x\nf1= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f1, f2, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t3, t2), t1) f.MulMod(u3, u2, u1) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf3= 0x%x\nf2= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f2, f1, f, b) } // Tests with one operand a power of 2 minus 1 if i == 0 { continue // skip zero operand } b1.Sub(b1, b_one) b1.Sub(b1, b_one) f1.SubUint64(f1, 2) set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t1, t2), t3) f.MulMod(u1, u2, u3) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf1= 0x%x\nf2= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f2, f3, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t1, t3), t2) f.MulMod(u1, u3, u2) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf1= 0x%x\nf3= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f1, f3, f2, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t2, t1), t3) f.MulMod(u2, u1, u3) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf2= 0x%x\nf1= 0x%x\nf3= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f1, f3, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t2, t3), t1) f.MulMod(u2, u3, u1) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf2= 0x%x\nf3= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f1, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t3, t1), t2) f.MulMod(u3, u1, u2) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf3= 0x%x\nf1= 0x%x\nf2= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f1, f2, f, b) } set3Big(b1, b2, b3, t1, t2, t3) set3Int(f1, f2, f3, u1, u2, u3) b.Mod(b.Mul(t3, t2), t1) f.MulMod(u3, u2, u1) if !checkEq(b, f) { t.Fatalf("Expected equality:\nf3= 0x%x\nf2= 0x%x\nf1= 0x%x\n[ op ]==\nf = %x\nb = %x\n", f3, f2, f1, f, b) } } } func TestRandomMulDivOverflow(t *testing.T) { for i := 0; i < 10000; i++ { b1, f1 := randNums() b2, f2 := randNums() b3, f3 := randNums() f1a, f2a, f3a := f1.Clone(), f2.Clone(), f3.Clone() _, overflow := f1.MulDivOverflow(f1, f2, f3) if b3.BitLen() == 0 { b1.SetInt64(0) } else { b1.Div(b1.Mul(b1, b2), b3) } if err := checkOverflow(b1, f1, overflow); err != nil { t.Fatal(err) } if eq := checkEq(b1, f1); !eq { t.Fatalf("Expected equality:\nf1= %x\nf2= %x\nf3= %x\n[ - ]==\nf= %x\nb= %x\n", f1a, f2a, f3a, f1, b1) } } } func TestRandomAbs(t *testing.T) { for i := 0; i < 10000; i++ { b, f1 := randHighNums() b2 := bigS256(big.NewInt(0).Set(b)) b2.Abs(b2) f1a := new(Int).Abs(f1) if eq := checkEq(b2, f1a); !eq { bf, _ := FromBig(b2) t.Fatalf("Expected equality:\nf1= %x\n[ abs ]==\nf = %x\nbf= %x\nb = %x\n", f1, f1a, bf, b2) } } } func TestUdivremQuick(t *testing.T) { var ( u = []uint64{1, 0, 0, 0, 0} expected = new(Int) rem Int ) udivrem([]uint64{}, u, &Int{0, 1, 0, 0}, &rem) copy(expected[:], u) if !rem.Eq(expected) { t.Errorf("Wrong remainder: %x, expected %x", rem, expected) } } func Test10KRandomSDiv(t *testing.T) { test10KRandom(t, "SDiv") } func Test10KRandomLsh(t *testing.T) { test10KRandom(t, "Lsh") } func Test10KRandomRsh(t *testing.T) { test10KRandom(t, "Rsh") } func Test10KRandomSRsh(t *testing.T) { test10KRandom(t, "SRsh") } func Test10KRandomExp(t *testing.T) { test10KRandom(t, "Exp") } func test10KRandom(t *testing.T, name string) { tc := lookupBinary(name) for i := 0; i < 10000; i++ { f1 := randNum() f2 := randNum() checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) } } func TestSRsh(t *testing.T) { type testCase struct { arg string n uint64 } testCases := []testCase{ {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 0}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 16}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 64}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 96}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 127}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 128}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 129}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 192}, {"0x8000000000000000000000000000000000000000000000000000000000000000", 254}, {"0x8000000000000000000000000000000000000000000000000000000000000000", 255}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 256}, {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 300}, {"0x7FFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 16}, {"0x7FFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 256}, } op := lookupBinary("SRsh") for _, tc := range testCases { arg := MustFromHex(tc.arg) n := NewInt(tc.n) checkBinaryOperation(t, op.name, op.u256Fn, op.bigFn, *arg, *n) } } func TestByte(t *testing.T) { input, err := FromHex("0x102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") if err != nil { t.Fatal(err) } for i := uint64(0); i < 35; i++ { var ( z = input.Clone() index = NewInt(i) have = z.Byte(index) want = NewInt(i) ) if i >= 32 { want.Clear() } if !have.Eq(want) { t.Fatalf("index %d: have %#x want %#x", i, have, want) } // Also check that we indeed modified the z if z != have { t.Fatalf("index %d: should return self %v %v", i, z, have) } } } func TestSignExtend(t *testing.T) { type testCase struct { arg string n uint64 } testCases := []testCase{ {"10000000000000000", 2}, {"8080808080808080808080808080808080808080808080808080808080808080", 0}, {"8080808080808080808080808080808080808080808080808080808080808080", 1}, {"8080808080808080808080808080808080808080808080808080808080808080", 2}, {"8080808080808080808080808080808080808080808080808080808080808080", 3}, {"8080808080808080808080808080808080808080808080808080808080808080", 8}, {"8080808080808080808080808080808080808080808080808080808080808080", 18}, {"8080808080808080808080808080808080808080808080808080808080808080", 30}, {"8080808080808080808080808080808080808080808080808080808080808080", 31}, {"8080808080808080808080808080808080808080808080808080808080808080", 32}, {"4040404040404040404040404040404040404040404040404040404040404040", 0}, {"4040404040404040404040404040404040404040404040404040404040404040", 1}, {"4040404040404040404040404040404040404040404040404040404040404040", 15}, {"4040404040404040404040404040404040404040404040404040404040404040", 19}, {"4040404040404040404040404040404040404040404040404040404040404040", 30}, {"4040404040404040404040404040404040404040404040404040404040404040", 31}, {"4040404040404040404040404040404040404040404040404040404040404040", 32}, } op := lookupBinary("ExtendSign") for _, tc := range testCases { arg := new(Int).SetBytes(hex2Bytes(tc.arg)) n := new(Int).SetUint64(tc.n) checkBinaryOperation(t, op.name, op.u256Fn, op.bigFn, *arg, *n) } } func TestAddSubUint64(t *testing.T) { type testCase struct { arg string n uint64 } testCases := []testCase{ {"0", 1}, {"1", 0}, {"1", 1}, {"1", 3}, {"0x10000000000000000", 1}, {"0x100000000000000000000000000000000", 1}, {"0", 0xffffffffffffffff}, {"1", 0xffffffff}, {"0xffffffffffffffff", 1}, {"0xffffffffffffffff", 0xffffffffffffffff}, {"0x10000000000000000", 1}, {"0xfffffffffffffffffffffffffffffffff", 1}, {"0xfffffffffffffffffffffffffffffffff", 2}, } for i := 0; i < len(testCases); i++ { tc := &testCases[i] bigArg, _ := new(big.Int).SetString(tc.arg, 0) arg, _ := FromBig(bigArg) { // SubUint64 want, _ := FromBig(bigU256(new(big.Int).Sub(bigArg, new(big.Int).SetUint64(tc.n)))) have := new(Int).SetAllOne().SubUint64(arg, tc.n) if !have.Eq(want) { t.Logf("args: %s, %d\n", tc.arg, tc.n) t.Logf("want : %x\n", want) t.Logf("have : %x\n\n", have) t.Fail() } } { // AddUint64 want, _ := FromBig(bigU256(new(big.Int).Add(bigArg, new(big.Int).SetUint64(tc.n)))) have := new(Int).AddUint64(arg, tc.n) if !have.Eq(want) { t.Logf("args: %s, %d\n", tc.arg, tc.n) t.Logf("want : %x\n", want) t.Logf("have : %x\n\n", have) t.Fail() } } } } func TestSGT(t *testing.T) { x := new(Int).SetBytes(hex2Bytes("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")) y := new(Int).SetBytes(hex2Bytes("00")) actual := x.Sgt(y) if actual { t.Fatalf("Expected %v false", actual) } x = new(Int).SetBytes(hex2Bytes("00")) y = new(Int).SetBytes(hex2Bytes("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")) actual = x.Sgt(y) if !actual { t.Fatalf("Expected %v true", actual) } } const ( // number of bits in a big.Word wordBits = 32 << (uint64(^big.Word(0)) >> 63) ) // TestFixedExpReusedArgs tests the cases in Exp() where the arguments (including result) alias the same objects. func TestFixedExpReusedArgs(t *testing.T) { f2 := Int{2, 0, 0, 0} f2.Exp(&f2, &f2) requireEq(t, big.NewInt(2*2), &f2, "") // TODO: This is tested in TestBinOp(). f3 := Int{3, 0, 0, 0} f4 := Int{4, 0, 0, 0} f3.Exp(&f4, &f3) requireEq(t, big.NewInt(4*4*4), &f3, "") // TODO: This is tested in TestBinOp(). f5 := Int{5, 0, 0, 0} f6 := Int{6, 0, 0, 0} f6.Exp(&f6, &f5) requireEq(t, big.NewInt(6*6*6*6*6), &f6, "") f3 = Int{3, 0, 0, 0} fr := new(Int).Exp(&f3, &f3) requireEq(t, big.NewInt(3*3*3), fr, "") } func TestPaddingRepresentation(t *testing.T) { a := big.NewInt(0xFF0AFcafe) aa := new(Int).SetUint64(0xFF0afcafe) bb := new(Int).SetBytes(a.Bytes()) if !aa.Eq(bb) { t.Fatal("aa != bb") } check := func(padded []byte, expectedHex string) { if expected := hex2Bytes(expectedHex); !bytes.Equal(padded, expected) { t.Errorf("incorrect padded bytes: %x, expected: %x", padded, expected) } } check(aa.PaddedBytes(32), "0000000000000000000000000000000000000000000000000000000ff0afcafe") check(aa.PaddedBytes(20), "0000000000000000000000000000000ff0afcafe") check(aa.PaddedBytes(40), "00000000000000000000000000000000000000000000000000000000000000000000000ff0afcafe") bytearr := hex2Bytes("0e320219838e859b2f9f18b72e3d4073ca50b37d") a = new(big.Int).SetBytes(bytearr) aa = new(Int).SetBytes(bytearr) bb = new(Int).SetBytes(a.Bytes()) if !aa.Eq(bb) { t.Fatal("aa != bb") } check(aa.PaddedBytes(32), "0000000000000000000000000e320219838e859b2f9f18b72e3d4073ca50b37d") check(aa.PaddedBytes(20), "0e320219838e859b2f9f18b72e3d4073ca50b37d") check(aa.PaddedBytes(40), "00000000000000000000000000000000000000000e320219838e859b2f9f18b72e3d4073ca50b37d") } func TestWriteToSlice(t *testing.T) { x1 := hex2Bytes("fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611") a := big.NewInt(0).SetBytes(x1) fa, _ := FromBig(a) dest := make([]byte, 32) fa.WriteToSlice(dest) if !bytes.Equal(dest, x1) { t.Errorf("got %x, expected %x", dest, x1) } fb := new(Int) exp := make([]byte, 32) fb.WriteToSlice(dest) if !bytes.Equal(dest, exp) { t.Errorf("got %x, expected %x", dest, exp) } // a too small buffer // Should fill the lower parts, masking upper bytes exp = hex2Bytes("683fd1e870eec79504c60144cc7f5fc2bad1e611") dest = make([]byte, 20) fa.WriteToSlice(dest) if !bytes.Equal(dest, exp) { t.Errorf("got %x, expected %x", dest, exp) } // a too large buffer, already filled with stuff // Should fill the leftmost 32 bytes, not touch the other things dest = hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") exp = hex2Bytes("fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611ffffffffffffffff") fa.WriteToSlice(dest) if !bytes.Equal(dest, exp) { t.Errorf("got %x, expected %x", dest, x1) } // an empty slice, no panics please dest = []byte{} exp = []byte{} fa.WriteToSlice(dest) if !bytes.Equal(dest, exp) { t.Errorf("got %x, expected %x", dest, x1) } } func TestInt_WriteToArray(t *testing.T) { x1 := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") a := big.NewInt(0).SetBytes(x1) fa, _ := FromBig(a) { dest := [20]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} fa.WriteToArray20(&dest) exp := hex2Bytes("0d0ed1e870eec79504c60144cc7f5fc2bad1e611") if !bytes.Equal(dest[:], exp) { t.Errorf("got %x, expected %x", dest, exp) } } { dest := [32]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} fa.WriteToArray32(&dest) exp := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") if !bytes.Equal(dest[:], exp) { t.Errorf("got %x, expected %x", dest, exp) } } { // A 36-byte slice: the first 32 bytes are overwritten dest := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} fa.PutUint256(dest) exp := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611ffffffff") if !bytes.Equal(dest[:], exp) { t.Errorf("got %x, expected %x", dest, exp) } } } type gethAddress [20]byte // SetBytes sets the address to the value of b. // If b is larger than len(a) it will panic. func (a *gethAddress) setBytes(b []byte) { if len(b) > len(a) { b = b[len(b)-20:] } copy(a[20-len(b):], b) } // BytesToAddress returns Address with value b. // If b is larger than len(h), b will be cropped from the left. func bytesToAddress(b []byte) gethAddress { var a gethAddress a.setBytes(b) return a } type gethHash [32]byte // SetBytes sets the address to the value of b. // If b is larger than len(a) it will panic. func (a *gethHash) setBytes(b []byte) { if len(b) > len(a) { b = b[len(b)-32:] } copy(a[32-len(b):], b) } // BytesToHash returns gethHash with value b. // If b is larger than len(h), b will be cropped from the left. func bytesToHash(b []byte) gethHash { var a gethHash a.setBytes(b) return a } func TestByteRepresentation(t *testing.T) { for i, tt := range []string{ "1337fafafa0e320219838e859b2f9f18b72e3d4073ca50b37d", "fafafa0e320219838e859b2f9f18b72e3d4073ca50b37d", "0e320219838e859b2f9f18b72e3d4073ca50b37d", "320219838e859b2f9f18b72e3d4073ca50b37d", "838e859b2f9f18b72e3d4073ca50b37d", "38e859b2f9f18b72e3d4073ca50b37d", "f18b72e3d4073ca50b37d", "b37d", "01", "", "00", } { bytearr := hex2Bytes(tt) // big.Int -> address, hash a := big.NewInt(0).SetBytes(bytearr) want20 := bytesToAddress(a.Bytes()) want32 := bytesToHash(a.Bytes()) // uint256.Int -> address b := new(Int).SetBytes(bytearr) have20 := gethAddress(b.Bytes20()) have32 := gethHash(b.Bytes32()) if have, want := want20, have20; have != want { t.Errorf("test %d: have %x want %x", i, have, want) } if have, want := want32, have32; have != want { t.Errorf("test %d: have %x want %x", i, have, want) } } } func testLog10(t *testing.T, z *Int) { want := uint(len(z.Dec())) if want > 0 { want-- } if have := z.Log10(); have != want { t.Errorf("%s (%s): have %v want %v", z.Hex(), z.Dec(), have, want) } } func TestLog10(t *testing.T) { testLog10(t, new(Int)) for i := uint(0); i < 255; i++ { z := NewInt(1) testLog10(t, z.Lsh(z, i)) if i != 0 { testLog10(t, new(Int).SubUint64(z, 1)) } } z := NewInt(1) ten := NewInt(10) for i := uint(0); i < 80; i++ { testLog10(t, z.Mul(z, ten)) testLog10(t, new(Int).SubUint64(z, 1)) } } func FuzzLog10(f *testing.F) { f.Fuzz(func(t *testing.T, aa, bb, cc, dd uint64) { testLog10(t, &Int{aa, bb, cc, dd}) }) } func BenchmarkLog10(b *testing.B) { var u256Ints []*Int var bigints []*big.Int for i := uint(0); i < 255; i++ { a := NewInt(1) a.Lsh(a, i) u256Ints = append(u256Ints, a) bigints = append(bigints, a.ToBig()) } b.Run("Log10/uint256", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, z := range u256Ints { _ = z.Log10() } } }) b.Run("Log10/big", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, z := range bigints { f, _ := new(big.Float).SetInt(z).Float64() _ = int(math.Log10(f)) } } }) } func TestCmpUint64(t *testing.T) { check := func(z *Int, x uint64) { want := z.ToBig().Cmp(new(big.Int).SetUint64(x)) have := z.CmpUint64(x) if have != want { t.Errorf("%s.CmpUint64( %x ) : have %v want %v", z.Hex(), x, have, want) } } for i := uint(0); i < 255; i++ { z := NewInt(1) z.Lsh(z, i) check(z, new(Int).Set(z).Uint64()) // z, z check(z, new(Int).AddUint64(z, 1).Uint64()) // z, z + 1 check(z, new(Int).SubUint64(z, 1).Uint64()) // z, z - 1 check(z, new(big.Int).Rsh(new(Int).Set(z).ToBig(), 64).Uint64()) // z, z >> 64 } } func TestCmpBig(t *testing.T) { check := func(z *Int, x *big.Int) { want := z.ToBig().Cmp(x) have := z.CmpBig(x) if have != want { t.Errorf("%s.CmpBig( %x ) : have %v want %v", z.Hex(), x, have, want) } } for i := uint(0); i < 255; i++ { z := NewInt(1) z.Lsh(z, i) check(z, new(Int).Set(z).ToBig()) // z, z check(z, new(Int).AddUint64(z, 1).ToBig()) // z, z + 1 check(z, new(Int).SubUint64(z, 1).ToBig()) // z, z - 1 check(z, new(big.Int).Neg(new(Int).Set(z).ToBig())) // z, -z check(z, new(big.Int).Lsh(new(Int).Set(z).ToBig(), 256)) // z, z << 256 } } uint256-1.3.2/unary_test.go000066400000000000000000000037561472460254700155030ustar00rootroot00000000000000// uint256: Fixed size 256-bit math library // Copyright 2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause package uint256 import ( "fmt" "math/big" "testing" ) type opUnaryArgFunc func(*Int, *Int) *Int type bigUnaryArgFunc func(*big.Int, *big.Int) *big.Int var unaryOpFuncs = []struct { name string u256Fn opUnaryArgFunc bigFn bigUnaryArgFunc }{ {"Not", (*Int).Not, (*big.Int).Not}, {"Neg", (*Int).Neg, (*big.Int).Neg}, {"Sqrt", (*Int).Sqrt, (*big.Int).Sqrt}, {"square", func(x *Int, y *Int) *Int { res := y.Clone() res.squared() return x.Set(res) }, func(b1, b2 *big.Int) *big.Int { return b1.Mul(b2, b2) }}, {"Abs", (*Int).Abs, func(b1, b2 *big.Int) *big.Int { return b1.Abs(bigS256(b2)) }}, } func checkUnaryOperation(t *testing.T, opName string, op opUnaryArgFunc, bigOp bigUnaryArgFunc, x Int) { var ( b1 = x.ToBig() f1 = x.Clone() operation = fmt.Sprintf("op: %v ( %v ) ", opName, x.Hex()) want, _ = FromBig(bigOp(new(big.Int), b1)) have = op(new(Int), f1) ) // Compare result with big.Int. if !have.Eq(want) { t.Fatalf("%v\nwant : %#x\nhave : %#x\n", operation, want, have) } // Check if arguments are unmodified. if !f1.Eq(x.Clone()) { t.Fatalf("%v\nfirst argument had been modified: %x", operation, f1) } // Check if reusing args as result works correctly. have = op(f1, f1) if have != f1 { t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f1) } if !have.Eq(want) { t.Fatalf("%v\n on argument reuse x.op(x)\nwant : %#x\nhave : %#x\n", operation, want, have) } } func TestUnaryOperations(t *testing.T) { for _, tc := range unaryOpFuncs { for _, arg := range unTestCases { f1 := MustFromHex(arg) checkUnaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1) } } } func FuzzUnaryOperations(f *testing.F) { f.Fuzz(func(t *testing.T, x0, x1, x2, x3 uint64) { x := Int{x0, x1, x2, x3} for _, tc := range unaryOpFuncs { checkUnaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, x) } }) }