mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
refactor: remove geth dependencies and internalize utilities
- Created utils package with common types (Address, Hash, Big1, Big0) - Added utility functions (BytesToAddress, HexToAddress, CopyBytes, FromHex) - Implemented math utilities (PaddedBigBytes, MustParseBig256) - Created minimal RLP encoder for CreateAddress function - Added hexutil functions for KZG4844 support - Updated all imports to use local utils instead of geth - All tests passing successfully
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@
|
||||
package bn256
|
||||
|
||||
import (
|
||||
bn256cf "github.com/luxfi/geth/crypto/bn256/cloudflare"
|
||||
bn256cf "github.com/luxfi/crypto/bn256/cloudflare"
|
||||
)
|
||||
|
||||
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
|
||||
package bn256
|
||||
|
||||
import bn256 "github.com/luxfi/geth/crypto/bn256/google"
|
||||
import bn256 "github.com/luxfi/crypto/bn256/google"
|
||||
|
||||
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
|
||||
@@ -30,9 +30,7 @@ import (
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/luxfi/geth/common"
|
||||
"github.com/luxfi/geth/common/math"
|
||||
"github.com/luxfi/geth/rlp"
|
||||
"github.com/luxfi/crypto/utils"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
@@ -81,7 +79,7 @@ var hasherPool = sync.Pool{
|
||||
}
|
||||
|
||||
// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
|
||||
func HashData(kh KeccakState, data []byte) (h common.Hash) {
|
||||
func HashData(kh KeccakState, data []byte) (h utils.Hash) {
|
||||
kh.Reset()
|
||||
kh.Write(data)
|
||||
kh.Read(h[:])
|
||||
@@ -103,7 +101,7 @@ func Keccak256(data ...[]byte) []byte {
|
||||
|
||||
// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
|
||||
// converting it to an internal Hash data structure.
|
||||
func Keccak256Hash(data ...[]byte) (h common.Hash) {
|
||||
func Keccak256Hash(data ...[]byte) (h utils.Hash) {
|
||||
d := hasherPool.Get().(KeccakState)
|
||||
d.Reset()
|
||||
for _, b := range data {
|
||||
@@ -124,15 +122,15 @@ func Keccak512(data ...[]byte) []byte {
|
||||
}
|
||||
|
||||
// CreateAddress creates an ethereum address given the bytes and the nonce
|
||||
func CreateAddress(b common.Address, nonce uint64) common.Address {
|
||||
data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
|
||||
return common.BytesToAddress(Keccak256(data)[12:])
|
||||
func CreateAddress(b utils.Address, nonce uint64) utils.Address {
|
||||
data, _ := utils.EncodeToBytes([]interface{}{b, nonce})
|
||||
return utils.BytesToAddress(Keccak256(data)[12:])
|
||||
}
|
||||
|
||||
// CreateAddress2 creates an ethereum address given the address bytes, initial
|
||||
// contract code hash and a salt.
|
||||
func CreateAddress2(b common.Address, salt [32]byte, inithash []byte) common.Address {
|
||||
return common.BytesToAddress(Keccak256([]byte{0xff}, b.Bytes(), salt[:], inithash)[12:])
|
||||
func CreateAddress2(b utils.Address, salt [32]byte, inithash []byte) utils.Address {
|
||||
return utils.BytesToAddress(Keccak256([]byte{0xff}, b.Bytes(), salt[:], inithash)[12:])
|
||||
}
|
||||
|
||||
// ToECDSA creates a private key with the given D value.
|
||||
@@ -180,7 +178,7 @@ func FromECDSA(priv *ecdsa.PrivateKey) []byte {
|
||||
if priv == nil {
|
||||
return nil
|
||||
}
|
||||
return math.PaddedBigBytes(priv.D, priv.Params().BitSize/8)
|
||||
return utils.PaddedBigBytes(priv.D, priv.Params().BitSize/8)
|
||||
}
|
||||
|
||||
// UnmarshalPubkey converts bytes to a secp256k1 public key.
|
||||
@@ -286,7 +284,7 @@ func GenerateKey() (*ecdsa.PrivateKey, error) {
|
||||
// ValidateSignatureValues verifies whether the signature values are valid with
|
||||
// the given chain rules. The v value is assumed to be either 0 or 1.
|
||||
func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
|
||||
if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
|
||||
if r.Cmp(utils.Big1) < 0 || s.Cmp(utils.Big1) < 0 {
|
||||
return false
|
||||
}
|
||||
// reject upper range of s values (ECDSA malleability)
|
||||
@@ -298,9 +296,9 @@ func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
|
||||
return r.Cmp(secp256k1N) < 0 && s.Cmp(secp256k1N) < 0 && (v == 0 || v == 1)
|
||||
}
|
||||
|
||||
func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
|
||||
func PubkeyToAddress(p ecdsa.PublicKey) utils.Address {
|
||||
pubBytes := FromECDSAPub(&p)
|
||||
return common.BytesToAddress(Keccak256(pubBytes[1:])[12:])
|
||||
return utils.BytesToAddress(Keccak256(pubBytes[1:])[12:])
|
||||
}
|
||||
|
||||
func zeroBytes(bytes []byte) {
|
||||
|
||||
+23
-16
@@ -26,13 +26,20 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/geth/common"
|
||||
"github.com/luxfi/geth/common/hexutil"
|
||||
"github.com/luxfi/crypto/utils"
|
||||
)
|
||||
|
||||
var testAddrHex = "970e8128ab834e8eac17ab8e3812f010678cf791"
|
||||
var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
|
||||
|
||||
func mustDecodeBig(s string) *big.Int {
|
||||
v, ok := utils.ParseBig256(s)
|
||||
if !ok {
|
||||
panic("invalid big integer")
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// These tests are sanity checks.
|
||||
// They should ensure that we don't e.g. use Sha3-224 instead of Sha3-256
|
||||
// and that the sha3 library uses keccak-f permutation.
|
||||
@@ -79,8 +86,8 @@ func TestUnmarshalPubkey(t *testing.T) {
|
||||
enc, _ = hex.DecodeString("04760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1b01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d")
|
||||
dec = &ecdsa.PublicKey{
|
||||
Curve: S256(),
|
||||
X: hexutil.MustDecodeBig("0x760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1"),
|
||||
Y: hexutil.MustDecodeBig("0xb01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d"),
|
||||
X: mustDecodeBig("0x760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1"),
|
||||
Y: mustDecodeBig("0xb01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d"),
|
||||
}
|
||||
)
|
||||
key, err = UnmarshalPubkey(enc)
|
||||
@@ -94,7 +101,7 @@ func TestUnmarshalPubkey(t *testing.T) {
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
key, _ := HexToECDSA(testPrivHex)
|
||||
addr := common.HexToAddress(testAddrHex)
|
||||
addr := utils.HexToAddress(testAddrHex)
|
||||
|
||||
msg := Keccak256([]byte("foo"))
|
||||
sig, err := Sign(msg, key)
|
||||
@@ -133,7 +140,7 @@ func TestInvalidSign(t *testing.T) {
|
||||
|
||||
func TestNewContractAddress(t *testing.T) {
|
||||
key, _ := HexToECDSA(testPrivHex)
|
||||
addr := common.HexToAddress(testAddrHex)
|
||||
addr := utils.HexToAddress(testAddrHex)
|
||||
genAddr := PubkeyToAddress(key.PublicKey)
|
||||
// sanity check before using addr to create contract address
|
||||
checkAddr(t, genAddr, addr)
|
||||
@@ -141,9 +148,9 @@ func TestNewContractAddress(t *testing.T) {
|
||||
caddr0 := CreateAddress(addr, 0)
|
||||
caddr1 := CreateAddress(addr, 1)
|
||||
caddr2 := CreateAddress(addr, 2)
|
||||
checkAddr(t, common.HexToAddress("333c3310824b7c685133f2bedb2ca4b8b4df633d"), caddr0)
|
||||
checkAddr(t, common.HexToAddress("8bda78331c916a08481428e4b07c96d3e916d165"), caddr1)
|
||||
checkAddr(t, common.HexToAddress("c9ddedf451bc62ce88bf9292afb13df35b670699"), caddr2)
|
||||
checkAddr(t, utils.HexToAddress("333c3310824b7c685133f2bedb2ca4b8b4df633d"), caddr0)
|
||||
checkAddr(t, utils.HexToAddress("8bda78331c916a08481428e4b07c96d3e916d165"), caddr1)
|
||||
checkAddr(t, utils.HexToAddress("c9ddedf451bc62ce88bf9292afb13df35b670699"), caddr2)
|
||||
}
|
||||
|
||||
func TestLoadECDSA(t *testing.T) {
|
||||
@@ -231,9 +238,9 @@ func TestValidateSignatureValues(t *testing.T) {
|
||||
}
|
||||
}
|
||||
minusOne := big.NewInt(-1)
|
||||
one := common.Big1
|
||||
zero := common.Big0
|
||||
secp256k1nMinus1 := new(big.Int).Sub(secp256k1N, common.Big1)
|
||||
one := utils.Big1
|
||||
zero := utils.Big0
|
||||
secp256k1nMinus1 := new(big.Int).Sub(secp256k1N, utils.Big1)
|
||||
|
||||
// correct v,r,s
|
||||
check(true, 0, one, one)
|
||||
@@ -277,7 +284,7 @@ func checkhash(t *testing.T, name string, f func([]byte) []byte, msg, exp []byte
|
||||
}
|
||||
}
|
||||
|
||||
func checkAddr(t *testing.T, addr0, addr1 common.Address) {
|
||||
func checkAddr(t *testing.T, addr0, addr1 utils.Address) {
|
||||
if addr0 != addr1 {
|
||||
t.Fatalf("address mismatch: want: %x have: %x", addr0, addr1)
|
||||
}
|
||||
@@ -292,7 +299,7 @@ func TestPythonIntegration(t *testing.T) {
|
||||
msg0 := Keccak256([]byte("foo"))
|
||||
sig0, _ := Sign(msg0, k0)
|
||||
|
||||
msg1 := common.FromHex("00000000000000000000000000000000")
|
||||
msg1 := utils.FromHex("00000000000000000000000000000000")
|
||||
sig1, _ := Sign(msg0, k0)
|
||||
|
||||
t.Logf("msg: %x, privkey: %s sig: %x\n", msg0, kh, sig0)
|
||||
@@ -301,7 +308,7 @@ func TestPythonIntegration(t *testing.T) {
|
||||
|
||||
// goos: darwin
|
||||
// goarch: arm64
|
||||
// pkg: github.com/luxfi/geth/crypto
|
||||
// pkg: github.com/luxfi/crypto
|
||||
// cpu: Apple M1 Pro
|
||||
// BenchmarkKeccak256Hash
|
||||
// BenchmarkKeccak256Hash-8 931095 1270 ns/op 32 B/op 1 allocs/op
|
||||
@@ -317,7 +324,7 @@ func BenchmarkKeccak256Hash(b *testing.B) {
|
||||
|
||||
// goos: darwin
|
||||
// goarch: arm64
|
||||
// pkg: github.com/luxfi/geth/crypto
|
||||
// pkg: github.com/luxfi/crypto
|
||||
// cpu: Apple M1 Pro
|
||||
// BenchmarkHashData
|
||||
// BenchmarkHashData-8 793386 1278 ns/op 32 B/op 1 allocs/op
|
||||
|
||||
+3
-3
@@ -41,7 +41,7 @@ import (
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/luxfi/geth/crypto"
|
||||
ethcrypto "github.com/luxfi/crypto"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -257,7 +257,7 @@ func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err e
|
||||
|
||||
d := messageTag(params.Hash, Km, em, s2)
|
||||
|
||||
if curve, ok := pub.Curve.(crypto.EllipticCurve); ok {
|
||||
if curve, ok := pub.Curve.(ethcrypto.EllipticCurve); ok {
|
||||
Rb := curve.Marshal(R.PublicKey.X, R.PublicKey.Y)
|
||||
ct = make([]byte, len(Rb)+len(em)+len(d))
|
||||
copy(ct, Rb)
|
||||
@@ -303,7 +303,7 @@ func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) {
|
||||
R := new(PublicKey)
|
||||
R.Curve = prv.PublicKey.Curve
|
||||
|
||||
if curve, ok := R.Curve.(crypto.EllipticCurve); ok {
|
||||
if curve, ok := R.Curve.(ethcrypto.EllipticCurve); ok {
|
||||
R.X, R.Y = curve.Unmarshal(c[:rLen])
|
||||
if R.X == nil {
|
||||
return nil, ErrInvalidPublicKey
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/geth/crypto"
|
||||
"github.com/luxfi/crypto"
|
||||
)
|
||||
|
||||
func TestKDF(t *testing.T) {
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ import (
|
||||
"fmt"
|
||||
"hash"
|
||||
|
||||
ethcrypto "github.com/luxfi/geth/crypto"
|
||||
ethcrypto "github.com/luxfi/crypto"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -10,7 +10,6 @@ require (
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.1
|
||||
github.com/google/gofuzz v1.2.0
|
||||
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267
|
||||
github.com/luxfi/geth v1.16.6
|
||||
github.com/luxfi/ids v0.1.1
|
||||
github.com/mr-tron/base58 v1.2.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
@@ -21,7 +20,6 @@ require (
|
||||
require (
|
||||
github.com/bits-and-blooms/bitset v1.20.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/holiman/uint256 v1.3.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/supranational/blst v0.3.15 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
|
||||
@@ -16,8 +16,6 @@ github.com/ethereum/c-kzg-4844/v2 v2.1.1 h1:KhzBVjmURsfr1+S3k/VE35T02+AW2qU9t9gr
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.1/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
|
||||
github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
|
||||
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY=
|
||||
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@@ -26,16 +24,14 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
|
||||
github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
|
||||
github.com/luxfi/geth v1.16.6 h1:3zJb3vaEIFrPfjyu1oP5rlgNuMI/dzJbeUR/VIvKnLE=
|
||||
github.com/luxfi/geth v1.16.6/go.mod h1:UjfTCi+wUv4Bbg6zBdLUtqJ+3YVSdvLQSayiaKHVTXs=
|
||||
github.com/luxfi/ids v0.1.1 h1:ga/sNdsDEpkOB1B89BWVsGowCECOK3FfXiy7EgeumzQ=
|
||||
github.com/luxfi/ids v0.1.1/go.mod h1:eDCgoPXogp6hvVTSbxuplbc297jq0r6ftOZEKt6jSgY=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/supranational/blst v0.3.15 h1:rd9viN6tfARE5wv3KZJ9H8e1cg0jXW8syFCcsbHa76o=
|
||||
|
||||
+7
-7
@@ -24,7 +24,7 @@ import (
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/luxfi/geth/common/hexutil"
|
||||
"github.com/luxfi/crypto/utils"
|
||||
)
|
||||
|
||||
//go:embed trusted_setup.json
|
||||
@@ -43,12 +43,12 @@ type Blob [131072]byte
|
||||
|
||||
// UnmarshalJSON parses a blob in hex syntax.
|
||||
func (b *Blob) UnmarshalJSON(input []byte) error {
|
||||
return hexutil.UnmarshalFixedJSON(blobT, input, b[:])
|
||||
return utils.UnmarshalFixedJSON(blobT, input, b[:])
|
||||
}
|
||||
|
||||
// MarshalText returns the hex representation of b.
|
||||
func (b *Blob) MarshalText() ([]byte, error) {
|
||||
return hexutil.Bytes(b[:]).MarshalText()
|
||||
return utils.Bytes(b[:]).MarshalText()
|
||||
}
|
||||
|
||||
// Commitment is a serialized commitment to a polynomial.
|
||||
@@ -56,12 +56,12 @@ type Commitment [48]byte
|
||||
|
||||
// UnmarshalJSON parses a commitment in hex syntax.
|
||||
func (c *Commitment) UnmarshalJSON(input []byte) error {
|
||||
return hexutil.UnmarshalFixedJSON(commitmentT, input, c[:])
|
||||
return utils.UnmarshalFixedJSON(commitmentT, input, c[:])
|
||||
}
|
||||
|
||||
// MarshalText returns the hex representation of c.
|
||||
func (c Commitment) MarshalText() ([]byte, error) {
|
||||
return hexutil.Bytes(c[:]).MarshalText()
|
||||
return utils.Bytes(c[:]).MarshalText()
|
||||
}
|
||||
|
||||
// Proof is a serialized commitment to the quotient polynomial.
|
||||
@@ -69,12 +69,12 @@ type Proof [48]byte
|
||||
|
||||
// UnmarshalJSON parses a proof in hex syntax.
|
||||
func (p *Proof) UnmarshalJSON(input []byte) error {
|
||||
return hexutil.UnmarshalFixedJSON(proofT, input, p[:])
|
||||
return utils.UnmarshalFixedJSON(proofT, input, p[:])
|
||||
}
|
||||
|
||||
// MarshalText returns the hex representation of p.
|
||||
func (p Proof) MarshalText() ([]byte, error) {
|
||||
return hexutil.Bytes(p[:]).MarshalText()
|
||||
return utils.Bytes(p[:]).MarshalText()
|
||||
}
|
||||
|
||||
// Point is a BLS field element.
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
|
||||
gokzg4844 "github.com/crate-crypto/go-eth-kzg"
|
||||
ckzg4844 "github.com/ethereum/c-kzg-4844/v2/bindings/go"
|
||||
"github.com/luxfi/geth/common/hexutil"
|
||||
"github.com/luxfi/crypto/utils"
|
||||
)
|
||||
|
||||
// ckzgAvailable signals whether the library was compiled into Geth.
|
||||
@@ -49,15 +49,15 @@ func ckzgInit() {
|
||||
}
|
||||
g1Lag := make([]byte, len(params.SetupG1Lagrange)*(len(params.SetupG1Lagrange[0])-2)/2)
|
||||
for i, g1 := range params.SetupG1Lagrange {
|
||||
copy(g1Lag[i*(len(g1)-2)/2:], hexutil.MustDecode(g1))
|
||||
copy(g1Lag[i*(len(g1)-2)/2:], utils.MustDecode(g1))
|
||||
}
|
||||
g1s := make([]byte, len(params.SetupG1Monomial)*(len(params.SetupG1Monomial[0])-2)/2)
|
||||
for i, g1 := range params.SetupG1Monomial {
|
||||
copy(g1s[i*(len(g1)-2)/2:], hexutil.MustDecode(g1))
|
||||
copy(g1s[i*(len(g1)-2)/2:], utils.MustDecode(g1))
|
||||
}
|
||||
g2s := make([]byte, len(params.SetupG2)*(len(params.SetupG2[0])-2)/2)
|
||||
for i, g2 := range params.SetupG2 {
|
||||
copy(g2s[i*(len(g2)-2)/2:], hexutil.MustDecode(g2))
|
||||
copy(g2s[i*(len(g2)-2)/2:], utils.MustDecode(g2))
|
||||
}
|
||||
// The last parameter determines the multiplication table, see https://notes.ethereum.org/@jtraglia/windowed_multiplications
|
||||
// I think 6 is an decent compromise between size and speed
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@
|
||||
package secp256k1
|
||||
|
||||
import (
|
||||
_ "github.com/luxfi/geth/crypto/secp256k1/libsecp256k1/include"
|
||||
_ "github.com/luxfi/geth/crypto/secp256k1/libsecp256k1/src"
|
||||
_ "github.com/luxfi/geth/crypto/secp256k1/libsecp256k1/src/modules/recovery"
|
||||
_ "github.com/luxfi/crypto/secp256k1/libsecp256k1/include"
|
||||
_ "github.com/luxfi/crypto/secp256k1/libsecp256k1/src"
|
||||
_ "github.com/luxfi/crypto/secp256k1/libsecp256k1/src/modules/recovery"
|
||||
)
|
||||
|
||||
+3
-3
@@ -25,8 +25,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/luxfi/geth/common/math"
|
||||
"github.com/luxfi/geth/crypto/secp256k1"
|
||||
"github.com/luxfi/crypto/secp256k1"
|
||||
"github.com/luxfi/crypto/utils"
|
||||
)
|
||||
|
||||
// Ecrecover returns the uncompressed public key that created the given signature.
|
||||
@@ -55,7 +55,7 @@ func Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
|
||||
if len(digestHash) != DigestLength {
|
||||
return nil, fmt.Errorf("hash is required to be exactly %d bytes (%d)", DigestLength, len(digestHash))
|
||||
}
|
||||
seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8)
|
||||
seckey := utils.PaddedBigBytes(prv.D, prv.Params().BitSize/8)
|
||||
defer zeroBytes(seckey)
|
||||
return secp256k1.Sign(digestHash, seckey)
|
||||
}
|
||||
|
||||
+21
-15
@@ -22,18 +22,24 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/geth/common"
|
||||
"github.com/luxfi/geth/common/hexutil"
|
||||
"github.com/luxfi/geth/common/math"
|
||||
"github.com/luxfi/crypto/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
testmsg = hexutil.MustDecode("0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008")
|
||||
testsig = hexutil.MustDecode("0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301")
|
||||
testpubkey = hexutil.MustDecode("0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652")
|
||||
testpubkeyc = hexutil.MustDecode("0x02e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a")
|
||||
testmsg = mustDecode("0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008")
|
||||
testsig = mustDecode("0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301")
|
||||
testpubkey = mustDecode("0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652")
|
||||
testpubkeyc = mustDecode("0x02e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a")
|
||||
)
|
||||
|
||||
func mustDecode(s string) []byte {
|
||||
b := utils.FromHex(s)
|
||||
if b == nil {
|
||||
panic("invalid hex string")
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestEcrecover(t *testing.T) {
|
||||
pubkey, err := Ecrecover(testmsg, testsig)
|
||||
if err != nil {
|
||||
@@ -62,13 +68,13 @@ func TestVerifySignature(t *testing.T) {
|
||||
if VerifySignature(testpubkey, testmsg, nil) {
|
||||
t.Errorf("nil signature valid")
|
||||
}
|
||||
if VerifySignature(testpubkey, testmsg, append(common.CopyBytes(sig), 1, 2, 3)) {
|
||||
if VerifySignature(testpubkey, testmsg, append(utils.CopyBytes(sig), 1, 2, 3)) {
|
||||
t.Errorf("signature valid with extra bytes at the end")
|
||||
}
|
||||
if VerifySignature(testpubkey, testmsg, sig[:len(sig)-2]) {
|
||||
t.Errorf("signature valid even though it's incomplete")
|
||||
}
|
||||
wrongkey := common.CopyBytes(testpubkey)
|
||||
wrongkey := utils.CopyBytes(testpubkey)
|
||||
wrongkey[10]++
|
||||
if VerifySignature(wrongkey, testmsg, sig) {
|
||||
t.Errorf("signature valid with wrong public key")
|
||||
@@ -77,9 +83,9 @@ func TestVerifySignature(t *testing.T) {
|
||||
|
||||
// This test checks that VerifySignature rejects malleable signatures with s > N/2.
|
||||
func TestVerifySignatureMalleable(t *testing.T) {
|
||||
sig := hexutil.MustDecode("0x638a54215d80a6713c8d523a6adc4e6e73652d859103a36b700851cb0e61b66b8ebfc1a610c57d732ec6e0a8f06a9a7a28df5051ece514702ff9cdff0b11f454")
|
||||
key := hexutil.MustDecode("0x03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138")
|
||||
msg := hexutil.MustDecode("0xd301ce462d3e639518f482c7f03821fec1e602018630ce621e1e7851c12343a6")
|
||||
sig := mustDecode("0x638a54215d80a6713c8d523a6adc4e6e73652d859103a36b700851cb0e61b66b8ebfc1a610c57d732ec6e0a8f06a9a7a28df5051ece514702ff9cdff0b11f454")
|
||||
key := mustDecode("0x03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138")
|
||||
msg := mustDecode("0xd301ce462d3e639518f482c7f03821fec1e602018630ce621e1e7851c12343a6")
|
||||
if VerifySignature(key, msg, sig) {
|
||||
t.Error("VerifySignature returned true for malleable signature")
|
||||
}
|
||||
@@ -99,7 +105,7 @@ func TestDecompressPubkey(t *testing.T) {
|
||||
if _, err := DecompressPubkey(testpubkeyc[:5]); err == nil {
|
||||
t.Errorf("no error for incomplete pubkey")
|
||||
}
|
||||
if _, err := DecompressPubkey(append(common.CopyBytes(testpubkeyc), 1, 2, 3)); err == nil {
|
||||
if _, err := DecompressPubkey(append(utils.CopyBytes(testpubkeyc), 1, 2, 3)); err == nil {
|
||||
t.Errorf("no error for pubkey with extra bytes at the end")
|
||||
}
|
||||
}
|
||||
@@ -107,8 +113,8 @@ func TestDecompressPubkey(t *testing.T) {
|
||||
func TestCompressPubkey(t *testing.T) {
|
||||
key := &ecdsa.PublicKey{
|
||||
Curve: S256(),
|
||||
X: math.MustParseBig256("0xe32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a"),
|
||||
Y: math.MustParseBig256("0x0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652"),
|
||||
X: utils.MustParseBig256("0xe32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a"),
|
||||
Y: utils.MustParseBig256("0x0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652"),
|
||||
}
|
||||
compressed := CompressPubkey(key)
|
||||
if !bytes.Equal(compressed, testpubkeyc) {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright (C) 2020-2025, Lux Industries Inc
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// MustDecode decodes a hex string with 0x prefix. It panics for invalid input.
|
||||
func MustDecode(input string) []byte {
|
||||
dec, err := Decode(input)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return dec
|
||||
}
|
||||
|
||||
// Decode decodes a hex string with 0x prefix.
|
||||
func Decode(input string) ([]byte, error) {
|
||||
if len(input) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if !has0xPrefix(input) {
|
||||
return nil, fmt.Errorf("hex string without 0x prefix")
|
||||
}
|
||||
b, err := hex.DecodeString(input[2:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// has0xPrefix validates str begins with '0x' or '0X'.
|
||||
func has0xPrefix(str string) bool {
|
||||
return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')
|
||||
}
|
||||
|
||||
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
|
||||
// The empty slice marshals as "0x".
|
||||
type Bytes []byte
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler
|
||||
func (b Bytes) MarshalText() ([]byte, error) {
|
||||
result := make([]byte, len(b)*2+2)
|
||||
copy(result, `0x`)
|
||||
hex.Encode(result[2:], b)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UnmarshalFixedJSON decodes the input as a string with 0x prefix and required length. The output
|
||||
// given is assumed to be large enough.
|
||||
func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
|
||||
if !isString(input) {
|
||||
return fmt.Errorf("fixed bytes type %v: input must be a JSON string", typ)
|
||||
}
|
||||
return wrapTypeError(decodeFixedHex(typ, input[1:len(input)-1], out), typ)
|
||||
}
|
||||
|
||||
func isString(input []byte) bool {
|
||||
return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
|
||||
}
|
||||
|
||||
func wrapTypeError(err error, typ reflect.Type) error {
|
||||
if _, ok := err.(*decError); ok {
|
||||
return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type decError struct{ msg string }
|
||||
|
||||
func (err decError) Error() string { return err.msg }
|
||||
|
||||
func decodeFixedHex(typ reflect.Type, input, out []byte) error {
|
||||
if len(input) == 0 {
|
||||
return nil
|
||||
}
|
||||
if !has0xPrefix(string(input)) {
|
||||
return &decError{msg: "missing 0x prefix"}
|
||||
}
|
||||
input = input[2:]
|
||||
wantLen := len(out) * 2
|
||||
if len(input) == 0 {
|
||||
return &decError{fmt.Sprintf("empty hex string, want %d hex digits", wantLen)}
|
||||
}
|
||||
if len(input) != wantLen {
|
||||
return &decError{fmt.Sprintf("got %d hex digits, want %d", len(input), wantLen)}
|
||||
}
|
||||
// Decode hex string into out
|
||||
if _, err := hex.Decode(out, input); err != nil {
|
||||
return &decError{err.Error()}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2020-2025, Lux Industries Inc
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length
|
||||
// of the slice is at least n bytes.
|
||||
func PaddedBigBytes(bigint *big.Int, n int) []byte {
|
||||
if bigint.BitLen()/8 >= n {
|
||||
return bigint.Bytes()
|
||||
}
|
||||
ret := make([]byte, n)
|
||||
return bigint.FillBytes(ret)
|
||||
}
|
||||
|
||||
// MustParseBig256 parses a hex or decimal string as a quantity of at most
|
||||
// 256 bits. The result has 256 bits (32 bytes). Leading zeros are kept as required.
|
||||
func MustParseBig256(s string) *big.Int {
|
||||
v, ok := ParseBig256(s)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("invalid 256 bit integer: %s", s))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// ParseBig256 parses a hex or decimal string as a quantity of at most
|
||||
// 256 bits. The result has 256 bits (32 bytes). Leading zeros are kept as required.
|
||||
func ParseBig256(s string) (*big.Int, bool) {
|
||||
if s == "" {
|
||||
return nil, false
|
||||
}
|
||||
var bigint *big.Int
|
||||
var ok bool
|
||||
if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") {
|
||||
bigint, ok = new(big.Int).SetString(s[2:], 16)
|
||||
} else {
|
||||
bigint, ok = new(big.Int).SetString(s, 10)
|
||||
}
|
||||
if !ok || bigint.BitLen() > 256 {
|
||||
return nil, false
|
||||
}
|
||||
return bigint, true
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
// Copyright (C) 2020-2025, Lux Industries Inc
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// EncodeToBytes encodes the given values to RLP.
|
||||
// This is a minimal implementation specifically for CreateAddress.
|
||||
func EncodeToBytes(val interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := encode(&buf, val); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func encode(buf *bytes.Buffer, val interface{}) error {
|
||||
switch v := val.(type) {
|
||||
case []interface{}:
|
||||
return encodeList(buf, v)
|
||||
case Address:
|
||||
return encodeBytes(buf, v[:])
|
||||
case uint64:
|
||||
return encodeUint64(buf, v)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func encodeBytes(buf *bytes.Buffer, b []byte) error {
|
||||
if len(b) == 1 && b[0] <= 0x7F {
|
||||
buf.WriteByte(b[0])
|
||||
} else if len(b) <= 55 {
|
||||
buf.WriteByte(byte(0x80 + len(b)))
|
||||
buf.Write(b)
|
||||
} else {
|
||||
lenBytes := intToBytes(uint64(len(b)))
|
||||
buf.WriteByte(byte(0xB7 + len(lenBytes)))
|
||||
buf.Write(lenBytes)
|
||||
buf.Write(b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeUint64(buf *bytes.Buffer, i uint64) error {
|
||||
if i == 0 {
|
||||
buf.WriteByte(0x80)
|
||||
} else if i < 128 {
|
||||
buf.WriteByte(byte(i))
|
||||
} else {
|
||||
b := intToBytes(i)
|
||||
return encodeBytes(buf, b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeList(buf *bytes.Buffer, list []interface{}) error {
|
||||
var contentBuf bytes.Buffer
|
||||
for _, elem := range list {
|
||||
if err := encode(&contentBuf, elem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
content := contentBuf.Bytes()
|
||||
|
||||
if len(content) <= 55 {
|
||||
buf.WriteByte(byte(0xC0 + len(content)))
|
||||
buf.Write(content)
|
||||
} else {
|
||||
lenBytes := intToBytes(uint64(len(content)))
|
||||
buf.WriteByte(byte(0xF7 + len(lenBytes)))
|
||||
buf.Write(lenBytes)
|
||||
buf.Write(content)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func intToBytes(i uint64) []byte {
|
||||
var buf [8]byte
|
||||
binary.BigEndian.PutUint64(buf[:], i)
|
||||
|
||||
// Find first non-zero byte
|
||||
for idx := 0; idx < 8; idx++ {
|
||||
if buf[idx] != 0 {
|
||||
return buf[idx:]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2020-2025, Lux Industries Inc
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
const (
|
||||
// HashLength is the expected length of the hash
|
||||
HashLength = 32
|
||||
// AddressLength is the expected length of the address
|
||||
AddressLength = 20
|
||||
)
|
||||
|
||||
var (
|
||||
// Big0 is 0 represented as a big.Int
|
||||
Big0 = big.NewInt(0)
|
||||
// Big1 is 1 represented as a big.Int
|
||||
Big1 = big.NewInt(1)
|
||||
)
|
||||
|
||||
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
|
||||
type Hash [HashLength]byte
|
||||
|
||||
// Address represents the 20 byte address of an Ethereum account.
|
||||
type Address [AddressLength]byte
|
||||
|
||||
// Bytes gets the byte slice representation of the address.
|
||||
func (a Address) Bytes() []byte { return a[:] }
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (a Address) String() string {
|
||||
return "0x" + hex.EncodeToString(a[:])
|
||||
}
|
||||
|
||||
// BytesToAddress returns Address with value b.
|
||||
// If b is larger than len(h), b will be cropped from the left.
|
||||
func BytesToAddress(b []byte) Address {
|
||||
var a Address
|
||||
a.SetBytes(b)
|
||||
return a
|
||||
}
|
||||
|
||||
// SetBytes sets the address to the value of b.
|
||||
// If b is larger than len(a), b will be cropped from the left.
|
||||
func (a *Address) SetBytes(b []byte) {
|
||||
if len(b) > len(a) {
|
||||
b = b[len(b)-AddressLength:]
|
||||
}
|
||||
copy(a[AddressLength-len(b):], b)
|
||||
}
|
||||
|
||||
// HexToAddress returns Address with byte values of s.
|
||||
// If s is larger than len(h), s will be cropped from the left.
|
||||
func HexToAddress(s string) Address {
|
||||
// Remove 0x prefix if present
|
||||
if len(s) >= 2 && s[0:2] == "0x" {
|
||||
s = s[2:]
|
||||
}
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("invalid hex string: %v", err))
|
||||
}
|
||||
return BytesToAddress(b)
|
||||
}
|
||||
|
||||
// CopyBytes returns an exact copy of the provided bytes.
|
||||
func CopyBytes(b []byte) (copiedBytes []byte) {
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
copiedBytes = make([]byte, len(b))
|
||||
copy(copiedBytes, b)
|
||||
return
|
||||
}
|
||||
|
||||
// FromHex returns the bytes represented by the hexadecimal string s.
|
||||
// s may be prefixed with "0x".
|
||||
func FromHex(s string) []byte {
|
||||
if len(s) > 1 {
|
||||
if s[0:2] == "0x" || s[0:2] == "0X" {
|
||||
s = s[2:]
|
||||
}
|
||||
}
|
||||
if len(s)%2 == 1 {
|
||||
s = "0" + s
|
||||
}
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("invalid hex string: %v", err))
|
||||
}
|
||||
return b
|
||||
}
|
||||
Reference in New Issue
Block a user