mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Merge pull request #1 from dcSpark/MartinOndejka/add-mina-precompiles
Add mina precompiles - add poseidon hash precompile - add schnor signature precompile
This commit is contained in:
commit
352d900fea
18 changed files with 2078 additions and 6 deletions
9
Makefile
9
Makefile
|
|
@ -2,13 +2,18 @@
|
|||
# with Go source code. If you know what GOPATH is then you probably
|
||||
# don't need to bother with make.
|
||||
|
||||
.PHONY: geth android ios evm all test clean
|
||||
.PHONY: geth android ios evm all test clean mina
|
||||
|
||||
GOBIN = ./build/bin
|
||||
GO ?= latest
|
||||
GORUN = env GO111MODULE=on go run
|
||||
|
||||
geth:
|
||||
mina:
|
||||
cd mina && cargo build --release
|
||||
cp mina/target/mina.h mina/lib/mina.h
|
||||
cp mina/target/release/libmina.a mina/lib/libmina.a
|
||||
|
||||
geth: mina
|
||||
$(GORUN) build/ci.go install ./cmd/geth
|
||||
@echo "Done building."
|
||||
@echo "Run \"$(GOBIN)/geth\" to launch geth."
|
||||
|
|
|
|||
|
|
@ -104,11 +104,17 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
|
|||
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
|
||||
}
|
||||
|
||||
var PrecompiledContractsMina = map[common.Address]PrecompiledContract{
|
||||
common.BytesToAddress([]byte{0x50}): &MinaHasher{},
|
||||
common.BytesToAddress([]byte{0x51}): &MinaSigner{},
|
||||
}
|
||||
|
||||
var (
|
||||
PrecompiledAddressesBerlin []common.Address
|
||||
PrecompiledAddressesIstanbul []common.Address
|
||||
PrecompiledAddressesByzantium []common.Address
|
||||
PrecompiledAddressesHomestead []common.Address
|
||||
PrecompiledAddressesMina []common.Address
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -124,19 +130,24 @@ func init() {
|
|||
for k := range PrecompiledContractsBerlin {
|
||||
PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k)
|
||||
}
|
||||
for k := range PrecompiledContractsMina {
|
||||
PrecompiledAddressesMina = append(PrecompiledAddressesMina, k)
|
||||
}
|
||||
}
|
||||
|
||||
// ActivePrecompiles returns the precompiles enabled with the current configuration.
|
||||
func ActivePrecompiles(rules params.Rules) []common.Address {
|
||||
result := PrecompiledAddressesMina
|
||||
|
||||
switch {
|
||||
case rules.IsBerlin:
|
||||
return PrecompiledAddressesBerlin
|
||||
return append(result, PrecompiledAddressesBerlin...)
|
||||
case rules.IsIstanbul:
|
||||
return PrecompiledAddressesIstanbul
|
||||
return append(result, PrecompiledAddressesIstanbul...)
|
||||
case rules.IsByzantium:
|
||||
return PrecompiledAddressesByzantium
|
||||
return append(result, PrecompiledAddressesByzantium...)
|
||||
default:
|
||||
return PrecompiledAddressesHomestead
|
||||
return append(result, PrecompiledAddressesHomestead...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
|
|||
common.BytesToAddress([]byte{16}): &bls12381Pairing{},
|
||||
common.BytesToAddress([]byte{17}): &bls12381MapG1{},
|
||||
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
|
||||
common.BytesToAddress([]byte{0x50}): &MinaHasher{},
|
||||
common.BytesToAddress([]byte{0x51}): &MinaSigner{},
|
||||
}
|
||||
|
||||
// EIP-152 test vectors
|
||||
|
|
@ -311,6 +313,8 @@ func TestPrecompiledBLS12381G2MultiExp(t *testing.T) { testJson("blsG2MultiExp",
|
|||
func TestPrecompiledBLS12381Pairing(t *testing.T) { testJson("blsPairing", "10", t) }
|
||||
func TestPrecompiledBLS12381MapG1(t *testing.T) { testJson("blsMapG1", "11", t) }
|
||||
func TestPrecompiledBLS12381MapG2(t *testing.T) { testJson("blsMapG2", "12", t) }
|
||||
func TestPrecompiledMinaHasher(t *testing.T) { testJson("minaHasher", "50", t) }
|
||||
func TestPrecompiledMinaSigner(t *testing.T) { testJson("minaSigner", "51", t) }
|
||||
|
||||
func BenchmarkPrecompiledBLS12381G1Add(b *testing.B) { benchJson("blsG1Add", "0a", b) }
|
||||
func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B) { benchJson("blsG1Mul", "0b", b) }
|
||||
|
|
@ -321,6 +325,8 @@ func BenchmarkPrecompiledBLS12381G2MultiExp(b *testing.B) { benchJson("blsG2Mult
|
|||
func BenchmarkPrecompiledBLS12381Pairing(b *testing.B) { benchJson("blsPairing", "10", b) }
|
||||
func BenchmarkPrecompiledBLS12381MapG1(b *testing.B) { benchJson("blsMapG1", "11", b) }
|
||||
func BenchmarkPrecompiledBLS12381MapG2(b *testing.B) { benchJson("blsMapG2", "12", b) }
|
||||
func BenchmarkPrecompiledMinaHasher(b *testing.B) { benchJson("minaHasher", "50", b) }
|
||||
func BenchmarkPrecompiledMinaSigner(b *testing.B) { benchJson("minaSigner", "51", b) }
|
||||
|
||||
// Failure tests
|
||||
func TestPrecompiledBLS12381G1AddFail(t *testing.T) { testJsonFail("blsG1Add", "0a", t) }
|
||||
|
|
@ -332,6 +338,8 @@ func TestPrecompiledBLS12381G2MultiExpFail(t *testing.T) { testJsonFail("blsG2Mu
|
|||
func TestPrecompiledBLS12381PairingFail(t *testing.T) { testJsonFail("blsPairing", "10", t) }
|
||||
func TestPrecompiledBLS12381MapG1Fail(t *testing.T) { testJsonFail("blsMapG1", "11", t) }
|
||||
func TestPrecompiledBLS12381MapG2Fail(t *testing.T) { testJsonFail("blsMapG2", "12", t) }
|
||||
func TestPrecompiledMinaHasherFail(t *testing.T) { testJsonFail("minaHasher", "50", t) }
|
||||
func TestPrecompiledMinaSignerFail(t *testing.T) { testJsonFail("minaSigner", "51", t) }
|
||||
|
||||
func loadJson(name string) ([]precompiledTest, error) {
|
||||
data, err := os.ReadFile(fmt.Sprintf("testdata/precompiles/%v.json", name))
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ type (
|
|||
)
|
||||
|
||||
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
||||
if p, ok := PrecompiledContractsMina[addr]; ok {
|
||||
return p, ok
|
||||
}
|
||||
|
||||
var precompiles map[common.Address]PrecompiledContract
|
||||
switch {
|
||||
case evm.chainRules.IsBerlin:
|
||||
|
|
@ -53,6 +57,7 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
|||
default:
|
||||
precompiles = PrecompiledContractsHomestead
|
||||
}
|
||||
|
||||
p, ok := precompiles[addr]
|
||||
return p, ok
|
||||
}
|
||||
|
|
|
|||
175
core/vm/mina_contracts.go
Normal file
175
core/vm/mina_contracts.go
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
package vm
|
||||
|
||||
// Solidity interfaces for precompiles
|
||||
//
|
||||
// enum HashParameter {
|
||||
// MAINNET,
|
||||
// TESTNET,
|
||||
// EMPTY
|
||||
// }
|
||||
//
|
||||
// interface IHasher {
|
||||
// function poseidonHash(
|
||||
// HashParameter hashParameter,
|
||||
// bytes32[] memory fields
|
||||
// ) external view returns (bytes32);
|
||||
// }
|
||||
//
|
||||
// interface ISigner {
|
||||
// function verify(
|
||||
// HashParameter hashParameter,
|
||||
// bytes32 pubKeyX,
|
||||
// bytes32 pubKeyY,
|
||||
// bytes32 signatureRX,
|
||||
// bytes32 signatureS,
|
||||
// bytes32[] calldata fields
|
||||
// ) external view returns (bool);
|
||||
// }
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: ${SRCDIR}/../../mina/lib/libmina.a -ldl
|
||||
#include "../../mina/lib/mina.h"
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
var sol_bool, _ = abi.NewType("bool", "", nil)
|
||||
var sol_uint8, _ = abi.NewType("uint8", "", nil)
|
||||
var sol_string, _ = abi.NewType("string", "", nil)
|
||||
var sol_bytes32, _ = abi.NewType("bytes32", "", nil)
|
||||
var sol_bytes32Arr, _ = abi.NewType("bytes32[]", "", nil)
|
||||
|
||||
var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
|
||||
|
||||
func packErr(message string) []byte {
|
||||
bytes, err := abi.Arguments{{Type: sol_string}}.Pack(message)
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return append(revertSelector, bytes...)
|
||||
}
|
||||
|
||||
var (
|
||||
errMinaInvalidSignature = errors.New("invalid function signature")
|
||||
errMinaCallingRustLibFailed = errors.New("calling rust library failed")
|
||||
)
|
||||
|
||||
type MinaHasher struct{}
|
||||
|
||||
func (c *MinaHasher) RequiredGas(input []byte) uint64 {
|
||||
return 1000
|
||||
}
|
||||
|
||||
func poseidonHash(calldata []byte) ([]byte, error) {
|
||||
unpacked, err := (abi.Arguments{{
|
||||
Type: sol_uint8}, // hashParameter
|
||||
{Type: sol_bytes32Arr}, // fields
|
||||
}).Unpack(calldata)
|
||||
|
||||
if err != nil {
|
||||
return packErr("Unable to unpack calldata"), err
|
||||
}
|
||||
|
||||
hashParameter := unpacked[0].(uint8)
|
||||
fields := unpacked[1].([][32]uint8)
|
||||
|
||||
output_buffer := [32]byte{}
|
||||
|
||||
var fields_ptr *C.uint8_t
|
||||
if len(fields) == 0 {
|
||||
fields_ptr = (*C.uint8_t)(nil)
|
||||
} else {
|
||||
fields_ptr = (*C.uint8_t)(&fields[0][0])
|
||||
}
|
||||
|
||||
if !C.poseidon(
|
||||
C.uint8_t(hashParameter),
|
||||
fields_ptr,
|
||||
C.uintptr_t(len(fields)),
|
||||
(*C.uint8_t)(&output_buffer[0]),
|
||||
) {
|
||||
return packErr("Calling Poseidon hash failed"), errMinaCallingRustLibFailed
|
||||
}
|
||||
|
||||
return output_buffer[:], nil
|
||||
}
|
||||
|
||||
// 0x1f831f84
|
||||
var poseidonHashSignature = crypto.Keccak256([]byte("poseidonHash(uint8,bytes32[])"))[:4]
|
||||
|
||||
func (c *MinaHasher) Run(input []byte) ([]byte, error) {
|
||||
if len(input) < 4 || !bytes.Equal(input[:4], poseidonHashSignature) {
|
||||
return packErr("Invalid signature"), errMinaInvalidSignature
|
||||
}
|
||||
|
||||
return poseidonHash(input[4:])
|
||||
}
|
||||
|
||||
type MinaSigner struct{}
|
||||
|
||||
func (c *MinaSigner) RequiredGas(input []byte) uint64 {
|
||||
return 1000
|
||||
}
|
||||
|
||||
// 0x462e39d6
|
||||
var verifySignature = crypto.Keccak256([]byte("verify(uint8,bytes32,bytes32,bytes32,bytes32,bytes32[])"))[:4]
|
||||
|
||||
func (c *MinaSigner) Run(input []byte) ([]byte, error) {
|
||||
if len(input) < 4 || !bytes.Equal(input[:4], verifySignature) {
|
||||
return packErr("Invalid signature"), errMinaInvalidSignature
|
||||
}
|
||||
|
||||
calldata := input[4:]
|
||||
|
||||
unpacked, err := (abi.Arguments{
|
||||
{Type: sol_uint8}, // hashParameter
|
||||
{Type: sol_bytes32}, // pubKeyX
|
||||
{Type: sol_bytes32}, // pubKeyY
|
||||
{Type: sol_bytes32}, // signatureRX
|
||||
{Type: sol_bytes32}, // signatureS
|
||||
{Type: sol_bytes32Arr}, // fields
|
||||
}).Unpack(calldata)
|
||||
|
||||
if err != nil {
|
||||
return packErr("Unable to unpack calldata"), err
|
||||
}
|
||||
|
||||
hashParameter := unpacked[0].(uint8)
|
||||
pubKeyX := unpacked[1].([32]uint8)
|
||||
pubKeyY := unpacked[2].([32]uint8)
|
||||
signatureRX := unpacked[3].([32]uint8)
|
||||
signatureS := unpacked[4].([32]uint8)
|
||||
fields := unpacked[5].([][32]uint8)
|
||||
|
||||
output_buffer := false
|
||||
|
||||
var fields_ptr *C.uint8_t
|
||||
if len(fields) == 0 {
|
||||
fields_ptr = (*C.uint8_t)(nil)
|
||||
} else {
|
||||
fields_ptr = (*C.uint8_t)(&fields[0][0])
|
||||
}
|
||||
|
||||
if !C.verify(
|
||||
C.uint8_t(hashParameter),
|
||||
(*C.uint8_t)(&pubKeyX[0]),
|
||||
(*C.uint8_t)(&pubKeyY[0]),
|
||||
(*C.uint8_t)(&signatureRX[0]),
|
||||
(*C.uint8_t)(&signatureS[0]),
|
||||
fields_ptr,
|
||||
C.uintptr_t(len(fields)),
|
||||
(*C.bool)(&output_buffer),
|
||||
) {
|
||||
return packErr("Calling verify failed"), errMinaCallingRustLibFailed
|
||||
}
|
||||
|
||||
return abi.Arguments{{Type: sol_bool}}.Pack(output_buffer)
|
||||
}
|
||||
22
core/vm/testdata/precompiles/fail-minaHasher.json
vendored
Normal file
22
core/vm/testdata/precompiles/fail-minaHasher.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
[
|
||||
{
|
||||
"Input": "aabbccdd",
|
||||
"ExpectedError": "invalid function signature",
|
||||
"Name": "mina_poseidon_invalid_signature"
|
||||
},
|
||||
{
|
||||
"Input": "1f831f84",
|
||||
"ExpectedError": "abi: attempting to unmarshall an empty string while arguments are expected",
|
||||
"Name": "mina_poseidon_invalid_calldata 1"
|
||||
},
|
||||
{
|
||||
"Input": "1f831f84aabbccdd",
|
||||
"ExpectedError": "abi: cannot marshal in to go type: length insufficient 4 require 32",
|
||||
"Name": "mina_poseidon_invalid_calldata 2"
|
||||
},
|
||||
{
|
||||
"Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"ExpectedError": "calling rust library failed",
|
||||
"Name": "mina_poseidon_invalid_field"
|
||||
}
|
||||
]
|
||||
22
core/vm/testdata/precompiles/fail-minaSigner.json
vendored
Normal file
22
core/vm/testdata/precompiles/fail-minaSigner.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
[
|
||||
{
|
||||
"Input": "aabbccdd",
|
||||
"ExpectedError": "invalid function signature",
|
||||
"Name": "mina_signer_invalid_signature"
|
||||
},
|
||||
{
|
||||
"Input": "462e39d6",
|
||||
"ExpectedError": "abi: attempting to unmarshall an empty string while arguments are expected",
|
||||
"Name": "mina_signer_invalid_calldata 1"
|
||||
},
|
||||
{
|
||||
"Input": "462e39d6aabbccdd",
|
||||
"ExpectedError": "abi: cannot marshal in to go type: length insufficient 4 require 32",
|
||||
"Name": "mina_signer_invalid_calldata 2"
|
||||
},
|
||||
{
|
||||
"Input": "462e39d60000000000000000000000000000000000000000000000000000000000000001ffb2abc6b0af14d8174f994590e37255f187c474ee385af4a399ad272e1eb60cf553e6e81fec4abc17cc21965c1991de96378b28754ab52dc758afe60afa1f0241197af9c449fcfe22fd770592997f157ef7c26eb33657897d077c71fdbb7f30bf2dc3c90732e136a85253dbb6db0c18823a5c573e70fa02c22eba7e04538c0100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"ExpectedError": "calling rust library failed",
|
||||
"Name": "mina_poseidon_invalid_field"
|
||||
}
|
||||
]
|
||||
44
core/vm/testdata/precompiles/minaHasher.json
vendored
Normal file
44
core/vm/testdata/precompiles/minaHasher.json
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[
|
||||
{
|
||||
"Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Expected": "a8eb9ee0f30046308abbfa5d20af73c81bbdabc25b459785024d045228bead2f",
|
||||
"Name": "vector 1",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001f2eee8d8f6e5fb182c610cae6c5393fce69dc4d900e7b4923b074e54ad00fb36",
|
||||
"Expected": "fb5992f65c07f9335995f43fd791d39012ad466717729e61045c297507054f3d",
|
||||
"Name": "vector 2",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002bd3f1c8f183ceedea15080edbe79d30bd7d613b86bf2ba12007091c60ae3933765e4f04ab87706bab06d13c7eee0a7807d0b8ce268b4ece6aab1e0508ec9c42f",
|
||||
"Expected": "fe2436f2027620a11233318b55d0a117086f09674826d1b7ce08d48ad0736c33",
|
||||
"Name": "vector 3",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003f5ea61ce47773495363dc4f6a41c3e2da14b13d6dd173acf87c9ca7357fb2400f28573f49c658b4ba151e82ed0bd6aaab045311d1a72df58c21eed462bede01873cf45c39285f17ccea99e0daeb547430cf7921218fe3726010f608e682a841a",
|
||||
"Expected": "9b1b94444a54af49a7623d1fe1ca72649f0a098daf5704925f024eb6ab0e4b3f",
|
||||
"Name": "vector 4",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "1f831f840000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000044c28b87198e0012207f93cdbdaa35355ec8213fa97a60e62701f62602d4659200787a40fc046c4dd0ff3cad0e54006577fece871c774707494984f1c7d3347271504ffe48e4e6dfcc4ded439edd386cf271b69d94afae83079f3ee3e7c04d52d290b6506516fe7588b5100f8db2e871427c6d74e7a60ab656f43dd9bc687c312",
|
||||
"Expected": "47ecd3bf2eed86dcf8d2cef3d7667104689dba4d9bcb54006e0c66f6ec8c5a16",
|
||||
"Name": "vector 5",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005da99182b35f2cd9f8a137052c4262576377a16deb83652db459a74893a0cf73c9805573990c4028292c9db171cd2b97902f9fc494983f6f7e0a0c184bc55df1b90ff1001b9dab21358aad1f6b7906a56d0c039502c1590c3ef9921a8951e440988b56238a0eda34576db959fecd1c3790bb5311fdb231753243c5085974a5b37896a7727e511a4c30d99082bf3542623fb702afab0b62ebbf301ed51e38f6812",
|
||||
"Expected": "09a2d55277908b7c8214f745b3605f0f9055dcd4c9b594cdd759292c34c3a20c",
|
||||
"Name": "vector 6",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
}
|
||||
]
|
||||
44
core/vm/testdata/precompiles/minaSigner.json
vendored
Normal file
44
core/vm/testdata/precompiles/minaSigner.json
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[
|
||||
{
|
||||
"Input": "462e39d60000000000000000000000000000000000000000000000000000000000000001ffb2abc6b0af14d8174f994590e37255f187c474ee385af4a399ad272e1eb60cf553e6e81fec4abc17cc21965c1991de96378b28754ab52dc758afe60afa1f0241197af9c449fcfe22fd770592997f157ef7c26eb33657897d077c71fdbb7f30bf2dc3c90732e136a85253dbb6db0c18823a5c573e70fa02c22eba7e04538c0100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000147e64adc9759307d1472d1fe8b9340d67d56b79cea7cfafb04b5647229968809",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"Name": "vector 1",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "462e39d60000000000000000000000000000000000000000000000000000000000000001b4286e40a0cfd61dd7457433adfd13d229f8ea277faef68ad6a2ab15a1bf910fd090cf75ab20da968fc2642f5b1545b819c563d14106a943fcce4bab0b2458177e7f89d308cd9fe434621eef98ad4e3fa42461ab4acf39d6051a862793c88c239940148992baff75f41e1c4a1cc13596cfdbc71bc9043cc8deb4f731df3ba13a00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000041b856ed3cd4b1c194835c47d194ed90dc8cc18eb61825efc53ce72fe8451d006488f11b7917a37b2dc8d54c4aa8bb09ebcedeca1d9aa4bb790dd5710eedf061e5c2e11fac12b2dff35c8bda983880c18084f74b2bd150a6eaf88d9ea9492bd063ae94f5a90f0ccc35b40b91cc1770e97ff951679c9a497334521ea0ea48be32f",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"Name": "vector 2",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "462e39d60000000000000000000000000000000000000000000000000000000000000001bf2e7149abba9571f50fcb32c3486af9517dfcc8474909adc3b6cbd2245cf61cbb42e2b30e3e3b8c3cde48299bbd20195cc207e95fba1bb2d68fe79f8ff78931749b0b525a821c5d6393edace3c82a908e91c878a4264eea6710d6924b217a3c7a1df4449137deb4d21b766333358957676cb3dcad1a5a940a7d3eaf33cf1f1600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003a359b9b2c05816f11df3b83c11f67c7111bfc82297afcf1d419964a2afc06f3bba9bab58485eebaed5a8192c373a3967a46b70d5a9d141bb3d1ac61422045622af9f76a9f9237d3adb7fd7c4fd3bd3620060578395180c41079292e2b2e10621",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"Name": "vector 3",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "462e39d60000000000000000000000000000000000000000000000000000000000000001bf2e7149abba9571f50fcb32c3486af9517dfcc8474909adc3b6cbd2245cf61cbb42e2b30e3e3b8c3cde48299bbd20195cc207e95fba1bb2d68fe79f8ff78931749b0b525a821c5d6393edace3c82a908e91c878a4264eea6710d6924b217a3c7a1df4449137deb4d21b766333358957676cb3dcad1a5a940a7d3eaf33cf1f1600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002a359b9b2c05816f11df3b83c11f67c7111bfc82297afcf1d419964a2afc06f3bba9bab58485eebaed5a8192c373a3967a46b70d5a9d141bb3d1ac61422045622",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Name": "vector 4",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "462e39d60000000000000000000000000000000000000000000000000000000000000001b4286e40a0cfd61dd7457433adfd13d229f8ea277faef68ad6a2ab15a1bf910fbb42e2b30e3e3b8c3cde48299bbd20195cc207e95fba1bb2d68fe79f8ff78931749b0b525a821c5d6393edace3c82a908e91c878a4264eea6710d6924b217a3c7a1df4449137deb4d21b766333358957676cb3dcad1a5a940a7d3eaf33cf1f1600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003a359b9b2c05816f11df3b83c11f67c7111bfc82297afcf1d419964a2afc06f3bba9bab58485eebaed5a8192c373a3967a46b70d5a9d141bb3d1ac61422045622af9f76a9f9237d3adb7fd7c4fd3bd3620060578395180c41079292e2b2e10621",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Name": "vector 5",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "462e39d60000000000000000000000000000000000000000000000000000000000000001bf2e7149abba9571f50fcb32c3486af9517dfcc8474909adc3b6cbd2245cf61cbb42e2b30e3e3b8c3cde48299bbd20195cc207e95fba1bb2d68fe79f8ff78931749b0b525a821c5d6393edace3c82a908e91c878a4264eea6710d6924b217a3cbf2dc3c90732e136a85253dbb6db0c18823a5c573e70fa02c22eba7e04538c0100000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003a359b9b2c05816f11df3b83c11f67c7111bfc82297afcf1d419964a2afc06f3bba9bab58485eebaed5a8192c373a3967a46b70d5a9d141bb3d1ac61422045622af9f76a9f9237d3adb7fd7c4fd3bd3620060578395180c41079292e2b2e10621",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Name": "vector 6",
|
||||
"Gas": 1000,
|
||||
"NoBenchmark": false
|
||||
}
|
||||
]
|
||||
2
mina/.gitignore
vendored
Normal file
2
mina/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/lib/libmina.a
|
||||
1185
mina/Cargo.lock
generated
Normal file
1185
mina/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
22
mina/Cargo.toml
Normal file
22
mina/Cargo.toml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
name = "mina"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
mina-hasher = { git = "https://github.com/o1-labs/proof-systems", tag = "0.1.0", version = "0.1.0" }
|
||||
mina-signer = { git = "https://github.com/o1-labs/proof-systems", tag = "0.1.0", version = "0.1.0" }
|
||||
o1-utils = { git = "https://github.com/o1-labs/proof-systems", tag = "0.1.0", version = "0.1.0" }
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.24.3"
|
||||
|
||||
[dev-dependencies]
|
||||
num-bigint = "0.4.3"
|
||||
serde = "1.0.160"
|
||||
serde_json = "1.0.96"
|
||||
35
mina/build.rs
Normal file
35
mina/build.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
extern crate cbindgen;
|
||||
|
||||
use cbindgen::Config;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
|
||||
let package_name = env::var("CARGO_PKG_NAME").unwrap();
|
||||
let output_file = target_dir()
|
||||
.join(format!("{}.h", package_name))
|
||||
.display()
|
||||
.to_string();
|
||||
|
||||
let config = Config {
|
||||
language: cbindgen::Language::C,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
cbindgen::generate_with_config(crate_dir, config)
|
||||
.unwrap()
|
||||
.write_to_file(output_file);
|
||||
}
|
||||
|
||||
/// Find the location of the `target/` directory. Note that this may be
|
||||
/// overridden by `cmake`, so we also need to check the `CARGO_TARGET_DIR`
|
||||
/// variable.
|
||||
fn target_dir() -> PathBuf {
|
||||
if let Ok(target) = env::var("CARGO_TARGET_DIR") {
|
||||
PathBuf::from(target)
|
||||
} else {
|
||||
PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("target")
|
||||
}
|
||||
}
|
||||
26
mina/lib/mina.h
Normal file
26
mina/lib/mina.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FIELD_SIZE 32
|
||||
|
||||
/**
|
||||
* * # Safety * this functions accepts raw pointer from golang
|
||||
*/
|
||||
bool poseidon(uint8_t network_id,
|
||||
const uint8_t *field_ptr,
|
||||
uintptr_t field_len,
|
||||
uint8_t *output_ptr);
|
||||
|
||||
/**
|
||||
* * # Safety * this functions accepts raw pointer from golang
|
||||
*/
|
||||
bool verify(uint8_t network_id,
|
||||
const uint8_t *pubkey_x,
|
||||
const uint8_t *pubkey_y,
|
||||
const uint8_t *sig_rx,
|
||||
const uint8_t *sig_s,
|
||||
const uint8_t *field_ptr,
|
||||
uintptr_t field_len,
|
||||
bool *output_ptr);
|
||||
271
mina/src/lib.rs
Normal file
271
mina/src/lib.rs
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
mod mina;
|
||||
|
||||
use std::array::TryFromSliceError;
|
||||
|
||||
use mina::{HashParameter, Message};
|
||||
use mina_signer::{BaseField, CurvePoint, PubKey, ScalarField, Signature};
|
||||
use o1_utils::FieldHelpers;
|
||||
|
||||
pub const FIELD_SIZE: usize = 32;
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* this functions accepts raw pointer from golang
|
||||
*/
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn poseidon(
|
||||
network_id: u8,
|
||||
field_ptr: *const u8,
|
||||
field_len: usize,
|
||||
output_ptr: *mut u8, // 32 bytes
|
||||
) -> bool {
|
||||
if (field_ptr.is_null() && field_len != 0) || output_ptr.is_null() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let network_id = match network_id {
|
||||
0x00 => HashParameter::Mainnet,
|
||||
0x01 => HashParameter::Testnet,
|
||||
0x02 => HashParameter::Empty,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let fields = unsafe { std::slice::from_raw_parts(field_ptr, field_len * FIELD_SIZE) };
|
||||
|
||||
let fields = match fields
|
||||
.chunks(FIELD_SIZE)
|
||||
.map(|chunk| chunk[..32].try_into())
|
||||
.collect::<Result<Vec<[u8; 32]>, TryFromSliceError>>()
|
||||
{
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let msg = match Message::from_bytes_slice(&fields) {
|
||||
Ok(msg) => msg,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let hash = mina::poseidon(&msg, network_id);
|
||||
|
||||
let output = unsafe { std::slice::from_raw_parts_mut(output_ptr, FIELD_SIZE) };
|
||||
|
||||
output.copy_from_slice(&hash.to_bytes());
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* this functions accepts raw pointer from golang
|
||||
*/
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn verify(
|
||||
network_id: u8,
|
||||
pubkey_x: *const u8,
|
||||
pubkey_y: *const u8,
|
||||
sig_rx: *const u8,
|
||||
sig_s: *const u8,
|
||||
field_ptr: *const u8,
|
||||
field_len: usize,
|
||||
output_ptr: *mut bool,
|
||||
) -> bool {
|
||||
if pubkey_x.is_null()
|
||||
|| pubkey_y.is_null()
|
||||
|| sig_rx.is_null()
|
||||
|| sig_s.is_null()
|
||||
|| (field_ptr.is_null() && field_len != 0)
|
||||
|| output_ptr.is_null()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let network_id = match network_id {
|
||||
0x00 => HashParameter::Mainnet,
|
||||
0x01 => HashParameter::Testnet,
|
||||
0x02 => HashParameter::Empty,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let pubkey_x = unsafe { std::slice::from_raw_parts(pubkey_x, FIELD_SIZE) };
|
||||
let pubkey_y = unsafe { std::slice::from_raw_parts(pubkey_y, FIELD_SIZE) };
|
||||
|
||||
let pubkey = PubKey::from_point_unsafe(CurvePoint::new(
|
||||
match BaseField::from_bytes(pubkey_x) {
|
||||
Ok(x) => x,
|
||||
Err(_) => return false,
|
||||
},
|
||||
match BaseField::from_bytes(pubkey_y) {
|
||||
Ok(y) => y,
|
||||
Err(_) => return false,
|
||||
},
|
||||
false,
|
||||
));
|
||||
|
||||
let sig_rx = unsafe { std::slice::from_raw_parts(sig_rx, FIELD_SIZE) };
|
||||
let sig_s = unsafe { std::slice::from_raw_parts(sig_s, FIELD_SIZE) };
|
||||
|
||||
let signature = Signature::new(
|
||||
match BaseField::from_bytes(sig_rx) {
|
||||
Ok(rx) => rx,
|
||||
Err(_) => return false,
|
||||
},
|
||||
match ScalarField::from_bytes(sig_s) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return false,
|
||||
},
|
||||
);
|
||||
|
||||
let fields = unsafe { std::slice::from_raw_parts(field_ptr, field_len * FIELD_SIZE) };
|
||||
|
||||
let fields = match fields
|
||||
.chunks(FIELD_SIZE)
|
||||
.map(|chunk| chunk[..32].try_into())
|
||||
.collect::<Result<Vec<[u8; 32]>, TryFromSliceError>>()
|
||||
{
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let msg = match Message::from_bytes_slice(&fields) {
|
||||
Ok(msg) => msg,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let result = mina::verify(&signature, &pubkey, &msg, network_id);
|
||||
|
||||
unsafe { *output_ptr = result };
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::*;
|
||||
use num_bigint::BigUint;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PoseidonTestVector {
|
||||
input: Vec<String>,
|
||||
output: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PoseidonTestVectors {
|
||||
test_vectors: Vec<PoseidonTestVector>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn poseidon_test_vectors() {
|
||||
let test_vectors: PoseidonTestVectors =
|
||||
serde_json::from_str(include_str!("test/poseidon_test_vectors.json")).unwrap();
|
||||
|
||||
for test_vector in test_vectors.test_vectors {
|
||||
let mut output = [0u8; 32];
|
||||
|
||||
let input = test_vector
|
||||
.input
|
||||
.iter()
|
||||
.flat_map(|input| BaseField::from_hex(input).unwrap().to_bytes())
|
||||
.collect::<Vec<u8>>();
|
||||
|
||||
unsafe {
|
||||
assert!(poseidon(
|
||||
0x02,
|
||||
input.as_ptr(),
|
||||
test_vector.input.len(),
|
||||
output.as_mut_ptr()
|
||||
))
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
BaseField::from_bytes(&output).unwrap().to_hex(),
|
||||
test_vector.output
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct SignerTestVector {
|
||||
pub_key_x: String,
|
||||
pub_key_y: String,
|
||||
sig_rx: String,
|
||||
sig_s: String,
|
||||
fields: Vec<String>,
|
||||
output: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct SignerTestVectors {
|
||||
test_vectors: Vec<SignerTestVector>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_signer() {
|
||||
let test_vectors: SignerTestVectors =
|
||||
serde_json::from_str(include_str!("test/signer_test_vectors.json")).unwrap();
|
||||
|
||||
for test_vector in test_vectors.test_vectors {
|
||||
let mut output = false;
|
||||
|
||||
let pub_key_x =
|
||||
BaseField::from_biguint(&BigUint::from_str(&test_vector.pub_key_x).unwrap())
|
||||
.unwrap()
|
||||
.to_bytes();
|
||||
let pub_key_y =
|
||||
BaseField::from_biguint(&BigUint::from_str(&test_vector.pub_key_y).unwrap())
|
||||
.unwrap()
|
||||
.to_bytes();
|
||||
let sig_rx = BaseField::from_biguint(&BigUint::from_str(&test_vector.sig_rx).unwrap())
|
||||
.unwrap()
|
||||
.to_bytes();
|
||||
let sig_s = ScalarField::from_biguint(&BigUint::from_str(&test_vector.sig_s).unwrap())
|
||||
.unwrap()
|
||||
.to_bytes();
|
||||
let fields = test_vector
|
||||
.fields
|
||||
.iter()
|
||||
.flat_map(|input| {
|
||||
BaseField::from_biguint(&BigUint::from_str(input).unwrap())
|
||||
.unwrap()
|
||||
.to_bytes()
|
||||
})
|
||||
.collect::<Vec<u8>>();
|
||||
|
||||
unsafe {
|
||||
assert!(verify(
|
||||
0x01,
|
||||
pub_key_x.as_ptr(),
|
||||
pub_key_y.as_ptr(),
|
||||
sig_rx.as_ptr(),
|
||||
sig_s.as_ptr(),
|
||||
fields.as_ptr(),
|
||||
test_vector.fields.len(),
|
||||
&mut output
|
||||
))
|
||||
};
|
||||
|
||||
assert_eq!(output, test_vector.output);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn null_pointer() {
|
||||
unsafe {
|
||||
assert!(!poseidon(0x00, std::ptr::null(), 1, std::ptr::null_mut()));
|
||||
assert!(!verify(
|
||||
0x00,
|
||||
std::ptr::null(),
|
||||
std::ptr::null(),
|
||||
std::ptr::null(),
|
||||
std::ptr::null(),
|
||||
std::ptr::null(),
|
||||
0,
|
||||
std::ptr::null_mut()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
76
mina/src/mina.rs
Normal file
76
mina/src/mina.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
use mina_hasher::{DomainParameter, Hashable, Hasher, ROInput};
|
||||
use mina_signer::{BaseField, PubKey, Signature, Signer};
|
||||
use o1_utils::{field_helpers::FieldHelpersError, FieldHelpers};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum HashParameter {
|
||||
Mainnet = 0x00,
|
||||
Testnet = 0x01,
|
||||
Empty = 0x02,
|
||||
TransactionCommitment = 0x03,
|
||||
}
|
||||
|
||||
impl From<HashParameter> for u8 {
|
||||
fn from(id: HashParameter) -> u8 {
|
||||
id as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DomainParameter for HashParameter {
|
||||
fn into_bytes(self) -> Vec<u8> {
|
||||
vec![self as u8]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Message {
|
||||
pub fields: Vec<BaseField>,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn from_bytes_slice(fields_bytes: &[[u8; 32]]) -> Result<Self, FieldHelpersError> {
|
||||
Ok(Self {
|
||||
fields: fields_bytes
|
||||
.iter()
|
||||
.map(|bytes| BaseField::from_bytes(bytes))
|
||||
.collect::<Result<Vec<BaseField>, FieldHelpersError>>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Hashable for Message {
|
||||
type D = HashParameter;
|
||||
|
||||
fn to_roinput(&self) -> ROInput {
|
||||
self.fields
|
||||
.iter()
|
||||
.fold(ROInput::new(), |roi, field| roi.append_field(*field))
|
||||
}
|
||||
|
||||
fn domain_string(network_id: HashParameter) -> Option<String> {
|
||||
match network_id {
|
||||
HashParameter::Mainnet => "MinaSignatureMainnet".to_string().into(),
|
||||
HashParameter::Testnet => "CodaSignature".to_string().into(),
|
||||
HashParameter::TransactionCommitment => "MinaAcctUpdateCons".to_string().into(),
|
||||
HashParameter::Empty => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poseidon(msg: &Message, network_id: HashParameter) -> BaseField {
|
||||
let mut hasher = mina_hasher::create_kimchi::<Message>(network_id);
|
||||
|
||||
hasher.hash(msg)
|
||||
}
|
||||
|
||||
pub fn verify(
|
||||
signature: &Signature,
|
||||
pubkey: &PubKey,
|
||||
msg: &Message,
|
||||
network_id: HashParameter,
|
||||
) -> bool {
|
||||
let mut signer = mina_signer::create_kimchi::<Message>(network_id);
|
||||
|
||||
signer.verify(signature, pubkey, msg)
|
||||
}
|
||||
47
mina/src/test/poseidon_test_vectors.json
Normal file
47
mina/src/test/poseidon_test_vectors.json
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"name": "kimchi",
|
||||
"test_vectors": [
|
||||
{
|
||||
"input": [],
|
||||
"output": "a8eb9ee0f30046308abbfa5d20af73c81bbdabc25b459785024d045228bead2f"
|
||||
},
|
||||
{
|
||||
"input": ["f2eee8d8f6e5fb182c610cae6c5393fce69dc4d900e7b4923b074e54ad00fb36"],
|
||||
"output": "fb5992f65c07f9335995f43fd791d39012ad466717729e61045c297507054f3d"
|
||||
},
|
||||
{
|
||||
"input": [
|
||||
"bd3f1c8f183ceedea15080edbe79d30bd7d613b86bf2ba12007091c60ae39337",
|
||||
"65e4f04ab87706bab06d13c7eee0a7807d0b8ce268b4ece6aab1e0508ec9c42f"
|
||||
],
|
||||
"output": "fe2436f2027620a11233318b55d0a117086f09674826d1b7ce08d48ad0736c33"
|
||||
},
|
||||
{
|
||||
"input": [
|
||||
"f5ea61ce47773495363dc4f6a41c3e2da14b13d6dd173acf87c9ca7357fb2400",
|
||||
"f28573f49c658b4ba151e82ed0bd6aaab045311d1a72df58c21eed462bede018",
|
||||
"73cf45c39285f17ccea99e0daeb547430cf7921218fe3726010f608e682a841a"
|
||||
],
|
||||
"output": "9b1b94444a54af49a7623d1fe1ca72649f0a098daf5704925f024eb6ab0e4b3f"
|
||||
},
|
||||
{
|
||||
"input": [
|
||||
"4c28b87198e0012207f93cdbdaa35355ec8213fa97a60e62701f62602d465920",
|
||||
"0787a40fc046c4dd0ff3cad0e54006577fece871c774707494984f1c7d334727",
|
||||
"1504ffe48e4e6dfcc4ded439edd386cf271b69d94afae83079f3ee3e7c04d52d",
|
||||
"290b6506516fe7588b5100f8db2e871427c6d74e7a60ab656f43dd9bc687c312"
|
||||
],
|
||||
"output": "47ecd3bf2eed86dcf8d2cef3d7667104689dba4d9bcb54006e0c66f6ec8c5a16"
|
||||
},
|
||||
{
|
||||
"input": [
|
||||
"da99182b35f2cd9f8a137052c4262576377a16deb83652db459a74893a0cf73c",
|
||||
"9805573990c4028292c9db171cd2b97902f9fc494983f6f7e0a0c184bc55df1b",
|
||||
"90ff1001b9dab21358aad1f6b7906a56d0c039502c1590c3ef9921a8951e4409",
|
||||
"88b56238a0eda34576db959fecd1c3790bb5311fdb231753243c5085974a5b37",
|
||||
"896a7727e511a4c30d99082bf3542623fb702afab0b62ebbf301ed51e38f6812"
|
||||
],
|
||||
"output": "09a2d55277908b7c8214f745b3605f0f9055dcd4c9b594cdd759292c34c3a20c"
|
||||
}
|
||||
]
|
||||
}
|
||||
72
mina/src/test/signer_test_vectors.json
Normal file
72
mina/src/test/signer_test_vectors.json
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"test_vectors": [
|
||||
{
|
||||
"pub_key_x": "5749528645515407352164834780408435992604865487588794690727207227268864389887",
|
||||
"pub_key_y": "961123686654787572379844019641929632619233203965678030693512890434590233589",
|
||||
"sig_rx": "21936703768608309712712286678384212721667043165509057046476743727602317531457",
|
||||
"sig_s": "700244403784750329046343352585969728434513601583367350022979202621496307135",
|
||||
"fields": ["4312143217416119453149054021680295703515035791870532431847656061436158469703"],
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"pub_key_x": "7042208129527677077861348888492606461956846197792817644260213199747289065652",
|
||||
"pub_key_y": "10558926836583110251042002010080745706359112066577139056638753279976447906000",
|
||||
"sig_rx": "16079692606027161177880995922609222716277493656983184336617842262008786419582",
|
||||
"sig_s": "26519020815623540666020017924931679489835794248279750040849654719218653085849",
|
||||
"fields": [
|
||||
"3081943907937102890466321349086512568672738229687175831440974884688704210203",
|
||||
"13581532047510445467277570462258108561396477004644819735095763123534482739016",
|
||||
"3048822856514015646580881400214404144660523787797871598232610379373617426012",
|
||||
"21660741932862358360736636215811102042484175487489560833468895032615023667514"
|
||||
],
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"pub_key_x": "13100040091688310466504835329210079551770129473582830476827447762924491321023",
|
||||
"pub_key_y": "22407096231914635758535978488910840638440068134091954456802730574700708250299",
|
||||
"sig_rx": "27354556051988045756232951201922658662417395660561896688145248213905143733108",
|
||||
"sig_s": "10007084982746413426116958072671171608413225743556423925802350318023121051002",
|
||||
"fields": [
|
||||
"26883907960994343248721672123600111927912732275633851101666934083556914846115",
|
||||
"15530614225213312579256518680413347727953796927384451546410690799125628951482",
|
||||
"14938482801295869243888529448769259929444998690971476813418451846255531696047"
|
||||
],
|
||||
"output": true
|
||||
},
|
||||
{
|
||||
"pub_key_x": "13100040091688310466504835329210079551770129473582830476827447762924491321023",
|
||||
"pub_key_y": "22407096231914635758535978488910840638440068134091954456802730574700708250299",
|
||||
"sig_rx": "27354556051988045756232951201922658662417395660561896688145248213905143733108",
|
||||
"sig_s": "10007084982746413426116958072671171608413225743556423925802350318023121051002",
|
||||
"fields": [
|
||||
"26883907960994343248721672123600111927912732275633851101666934083556914846115",
|
||||
"15530614225213312579256518680413347727953796927384451546410690799125628951482"
|
||||
],
|
||||
"output": false
|
||||
},
|
||||
{
|
||||
"pub_key_x": "7042208129527677077861348888492606461956846197792817644260213199747289065652",
|
||||
"pub_key_y": "22407096231914635758535978488910840638440068134091954456802730574700708250299",
|
||||
"sig_rx": "27354556051988045756232951201922658662417395660561896688145248213905143733108",
|
||||
"sig_s": "10007084982746413426116958072671171608413225743556423925802350318023121051002",
|
||||
"fields": [
|
||||
"26883907960994343248721672123600111927912732275633851101666934083556914846115",
|
||||
"15530614225213312579256518680413347727953796927384451546410690799125628951482",
|
||||
"14938482801295869243888529448769259929444998690971476813418451846255531696047"
|
||||
],
|
||||
"output": false
|
||||
},
|
||||
{
|
||||
"pub_key_x": "13100040091688310466504835329210079551770129473582830476827447762924491321023",
|
||||
"pub_key_y": "22407096231914635758535978488910840638440068134091954456802730574700708250299",
|
||||
"sig_rx": "27354556051988045756232951201922658662417395660561896688145248213905143733108",
|
||||
"sig_s": "700244403784750329046343352585969728434513601583367350022979202621496307135",
|
||||
"fields": [
|
||||
"26883907960994343248721672123600111927912732275633851101666934083556914846115",
|
||||
"15530614225213312579256518680413347727953796927384451546410690799125628951482",
|
||||
"14938482801295869243888529448769259929444998690971476813418451846255531696047"
|
||||
],
|
||||
"output": false
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue