This commit is contained in:
Simon 2017-10-09 10:13:40 -07:00
parent 856c9fe43e
commit 62cb9e5508
10 changed files with 887 additions and 4 deletions

View File

@ -12,7 +12,7 @@
GOBIN = build/bin GOBIN = build/bin
GO ?= latest GO ?= latest
geth: geth: zsl
build/env.sh go run build/ci.go install ./cmd/geth build/env.sh go run build/ci.go install ./cmd/geth
@echo "Done building." @echo "Done building."
@echo "Run \"$(GOBIN)/geth\" to launch geth." @echo "Run \"$(GOBIN)/geth\" to launch geth."
@ -22,7 +22,7 @@ evm:
@echo "Done building." @echo "Done building."
@echo "Run \"$(GOBIN)/evm to start the evm." @echo "Run \"$(GOBIN)/evm to start the evm."
all: all: zsl
build/env.sh go run build/ci.go install build/env.sh go run build/ci.go install
test: all test: all
@ -30,6 +30,11 @@ test: all
clean: clean:
rm -fr build/_workspace/pkg/ Godeps/_workspace/pkg $(GOBIN)/* rm -fr build/_workspace/pkg/ Godeps/_workspace/pkg $(GOBIN)/*
cd vendor/github.com/jpmorganchase/zsl-q/zsl-golang/zsl/snark/ ; $(MAKE) clean
zsl:
cd vendor/github.com/jpmorganchase/zsl-q/zsl-golang/zsl/snark/ ; $(MAKE)
@echo "Done building libzsl.a"
# Cross Compilation Targets (xgo) # Cross Compilation Targets (xgo)

View File

@ -1,3 +1,9 @@
# ZSL on Quorum
This branch of Quorum 1.5 supports [ZSL on Quroum](https://github.com/jpmorganchase/zsl-q/blob/master/README.md).
Original README follows.
# Quorum # Quorum
Quorum is an Ethereum-based distributed ledger protocol with transaction/contract privacy and a new consensus mechanism. Quorum is an Ethereum-based distributed ledger protocol with transaction/contract privacy and a new consensus mechanism.

View File

@ -17,6 +17,8 @@
package vm package vm
import ( import (
"encoding/binary"
"encoding/hex"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -24,8 +26,18 @@ import (
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
// ZSL START
sha256compress "github.com/jpmorganchase/zsl-q/zsl-golang/zsl/sha256"
"github.com/jpmorganchase/zsl-q/zsl-golang/zsl/snark"
// ZSL END
) )
// ZSL START
const ZSL_PROOF_SIZE uint64 = 584
// ZSL END
// PrecompiledAccount represents a native ethereum contract // PrecompiledAccount represents a native ethereum contract
type PrecompiledAccount struct { type PrecompiledAccount struct {
Gas func(l int) *big.Int Gas func(l int) *big.Int
@ -69,6 +81,38 @@ func PrecompiledContracts() map[string]*PrecompiledAccount {
return n.Add(n, params.IdentityGas) return n.Add(n, params.IdentityGas)
}, memCpy}, }, memCpy},
// ZSL START
// Sha256Compress
string(common.LeftPadBytes([]byte{0x88, 0x01}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32)
n.Mul(n, params.Sha256CompressWordGas)
return n.Add(n, params.Sha256CompressGas)
}, sha256CompressFunc},
// Verify Shielded Transfer
string(common.LeftPadBytes([]byte{0x88, 0x02}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32)
n.Mul(n, params.VerifyZKProofWordGas)
return n.Add(n, params.VerifyZKProofGas)
}, verifyShieldedTransferFunc},
// Verify Shielding
string(common.LeftPadBytes([]byte{0x88, 0x03}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32)
n.Mul(n, params.VerifyZKProofWordGas)
return n.Add(n, params.VerifyZKProofGas)
}, verifyShieldingFunc},
// Verify Unshielding
string(common.LeftPadBytes([]byte{0x88, 0x04}, 20)): &PrecompiledAccount{func(l int) *big.Int {
n := big.NewInt(int64(l+31) / 32)
n.Mul(n, params.VerifyZKProofWordGas)
return n.Add(n, params.VerifyZKProofGas)
}, verifyUnshieldingFunc},
// ZSL END
} }
} }
@ -117,3 +161,178 @@ func ecrecoverFunc(in []byte) []byte {
func memCpy(in []byte) []byte { func memCpy(in []byte) []byte {
return in return in
} }
// ZSL START
/*
Input bytes when the precompile is called with string "hello":
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000005
68656c6c6f000000000000000000000000000000000000000000000000000000
*/
func sha256CompressFunc(in []byte) []byte {
// ignore keccac
in = in[4:]
// ignore next 32 bytes
in = in[32:]
// check payload size
n := binary.BigEndian.Uint64(in[24:32])
if n != 64 {
glog.Errorln("ZSL input must have size of 64 bytes (512 bits)")
return nil
}
// skip payload size
in = in[32:]
c := sha256compress.NewCompress()
c.Write(in[0:n])
return c.Compress()
}
/**
In geth:
zslprecompile.VerifyShielding("0x001122", "0x08dbb5c1357d05e5178c9f8b88b590e0728d36f1a2e04ae93e963d5174fc4d35", "0xff2c9bdc59089c8d3aa313e9394a19ea17dbfa6f8b2520c7165734b6da615dc4", 12345)
Data passed into function:
4e320263000000000000000000000000000000000000000000000000000000000000000808dbb5c1357d05e5178c9f8b88b590e0728d36f1a2e04ae93e963d5174fc4d35ff2c9bdc59089c8d3aa313e9394a19ea17dbfa6f8b2520c7165734b6da615dc400000000000000000000000000000000000000000000000000000000000030390000000000000000000000000000000000000000000000000000000000000003001122
*/
func verifyShieldingFunc(in []byte) []byte {
snark.Init()
// ignore keccac
in = in[4:]
// ignore next 32 bytes
in = in[32:]
var send_nf [32]byte
var cm [32]byte
copy(send_nf[:], in[:32])
copy(cm[:], in[32:64])
noteValue := binary.BigEndian.Uint64(in[88:96])
proofSize := binary.BigEndian.Uint64(in[120:128]) // should be 584
if proofSize != ZSL_PROOF_SIZE {
glog.Errorf("ZSL error, proof must have size of %d bytes, not %d.\n", ZSL_PROOF_SIZE, proofSize)
return nil
}
var proof [ZSL_PROOF_SIZE]byte
copy(proof[:], in[128:])
result := snark.VerifyShielding(proof, send_nf, cm, noteValue)
var b byte
if result {
b = 1
}
glog.Errorln("verifyShieldingFunc: ", hex.EncodeToString(in))
glog.Errorln("send_nf: ", hex.EncodeToString(send_nf[:]))
glog.Errorln(" cm: ", hex.EncodeToString(cm[:]))
glog.Errorln(" value: ", noteValue)
glog.Errorln(" size: ", proofSize)
glog.Errorln(" proof: ", hex.EncodeToString(in[128:]))
glog.Errorln(" result: ", result)
return []byte{b}
}
func verifyUnshieldingFunc(in []byte) []byte {
snark.Init()
// ignore keccac
in = in[4:]
// ignore next 32 bytes
in = in[32:]
var spend_nf [32]byte
var rt [32]byte
copy(spend_nf[:], in[:32])
copy(rt[:], in[32:64])
noteValue := binary.BigEndian.Uint64(in[88:96])
proofSize := binary.BigEndian.Uint64(in[120:128]) // should be 584
if proofSize != ZSL_PROOF_SIZE {
glog.Errorf("ZSL error, proof must have size of %d bytes, not %d.\n", ZSL_PROOF_SIZE, proofSize)
return nil
}
var proof [ZSL_PROOF_SIZE]byte
copy(proof[:], in[128:])
result := snark.VerifyUnshielding(proof, spend_nf, rt, noteValue)
var b byte
if result {
b = 1
}
glog.Errorln("verifyUnshieldingFunc: ", hex.EncodeToString(in))
glog.Errorln("spend_nf: ", hex.EncodeToString(spend_nf[:]))
glog.Errorln(" rt: ", hex.EncodeToString(rt[:]))
glog.Errorln(" value: ", noteValue)
glog.Errorln(" size: ", proofSize)
glog.Errorln(" proof: ", hex.EncodeToString(in[128:]))
glog.Errorln(" result: ", result)
return []byte{b}
}
func verifyShieldedTransferFunc(in []byte) []byte {
// ignore keccac
in = in[4:]
// ignore next 32 bytes
in = in[32:]
var anchor [32]byte
var spend_nf_1 [32]byte
var spend_nf_2 [32]byte
var send_nf_1 [32]byte
var send_nf_2 [32]byte
var cm_1 [32]byte
var cm_2 [32]byte
copy(anchor[:], in[:32])
copy(spend_nf_1[:], in[32:64])
copy(spend_nf_2[:], in[64:96])
copy(send_nf_1[:], in[96:128])
copy(send_nf_2[:], in[128:160])
copy(cm_1[:], in[160:192])
copy(cm_2[:], in[192:224])
proofSize := binary.BigEndian.Uint64(in[248:256]) // should be 584
if proofSize != ZSL_PROOF_SIZE {
glog.Errorf("ZSL error, proof must have size of %d bytes, not %d.\n", ZSL_PROOF_SIZE, proofSize)
return nil
}
var proof [ZSL_PROOF_SIZE]byte
copy(proof[:], in[256:])
snark.Init()
result := snark.VerifyTransfer(proof, anchor, spend_nf_1, spend_nf_2, send_nf_1, send_nf_2, cm_1, cm_2)
var b byte
if result {
b = 1
}
glog.Errorln("verifyShieldedTransferFunc: ", hex.EncodeToString(in))
glog.Errorln("spend_nf_1: ", hex.EncodeToString(spend_nf_1[:]))
glog.Errorln("spend_nf_2: ", hex.EncodeToString(spend_nf_2[:]))
glog.Errorln(" send_nf_1: ", hex.EncodeToString(send_nf_1[:]))
glog.Errorln(" send_nf_2: ", hex.EncodeToString(send_nf_2[:]))
glog.Errorln(" cm_1: ", hex.EncodeToString(cm_1[:]))
glog.Errorln(" cm_2: ", hex.EncodeToString(cm_2[:]))
glog.Errorln(" anchor: ", hex.EncodeToString(anchor[:]))
glog.Errorln(" size: ", proofSize)
glog.Errorln(" proof: ", hex.EncodeToString(proof[:]))
glog.Errorln(" result: ", result)
return []byte{b}
}
// ZSL END

543
core/zsl/api.go Normal file
View File

@ -0,0 +1,543 @@
package zsl
import (
"crypto/rand"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"strings"
"github.com/jpmorganchase/zsl-q/zsl-golang/zsl/snark"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
const (
ZSL_PROOF_SIZE int = 584
ZSL_TREE_DEPTH = 29
)
type PublicZSLAPI struct {
}
func NewPublicZSLAPI() *PublicZSLAPI {
return &PublicZSLAPI{}
}
// Note: API function names should match those defined in web3ext.go, first character upper case as external function.
func (api *PublicZSLAPI) LoadTracker(filename string) (string, error) {
data, err := ioutil.ReadFile(filename)
return string(data[:]), err
}
// TODO: Post-demo, sanitize filenames and check exiting files before over-writing.
func (api *PublicZSLAPI) SaveTracker(filename string, data string) bool {
b := []byte(data)
err := ioutil.WriteFile(filename, b, 0644)
return err == nil
}
// Convert proof hex string from javascript to correct format. Trims leading 0x if present.
func getProofFromHex(s string) ([ZSL_PROOF_SIZE]byte, error) {
var proof [ZSL_PROOF_SIZE]byte
buf, err := hex.DecodeString(strings.TrimPrefix(s, "0x"))
if err != nil {
return proof, err
}
proofSize := len(buf)
if proofSize != ZSL_PROOF_SIZE {
return proof, errors.New(fmt.Sprintf("ZSL error, proof must have size of %d bytes, not %d.\n", ZSL_PROOF_SIZE, proofSize))
}
copy(proof[:], buf[:ZSL_PROOF_SIZE])
return proof, nil
}
// send nullifier, SHA256(0x00 || rho)
func computeSendNullifier(rho []byte) []byte {
h := sha256.New()
h.Write([]byte{0x00})
h.Write(rho)
return h.Sum(nil)
}
// spend nullifier SHA256(0x01 || rho || sk)
func computeSpendNullifier(rho []byte, sk [32]byte) []byte {
h := sha256.New()
h.Write([]byte{0x01})
h.Write(rho)
h.Write(sk[:])
return h.Sum(nil)
}
// cm = SHA256(rho || pk || v) where v is in little endian byte order
func computeCommitment(rho [32]byte, pk [32]byte, v uint64) []byte {
vbuf := make([]byte, 8)
binary.LittleEndian.PutUint64(vbuf, v)
h := sha256.New()
h.Write(rho[:])
h.Write(pk[:])
h.Write(vbuf)
return h.Sum(nil)
}
func (api *PublicZSLAPI) GetCommitment(rho common.Hash, pk common.Hash, value float64) common.Hash {
return common.BytesToHash(computeCommitment(rho, pk, uint64(value)))
}
func (api *PublicZSLAPI) GetSendNullifier(rho common.Hash) common.Hash {
return common.BytesToHash(computeSendNullifier(rho[:]))
}
func (api *PublicZSLAPI) GetSpendNullifier(rho common.Hash, sk common.Hash) common.Hash {
return common.BytesToHash(computeSpendNullifier(rho[:], sk))
}
/**
Example to generate a proof in geth:
sk = "0xf0f0f0f00f0f0ffffffffff000000f0f0f0f0f00f0000f0f00f00f0f0f0f00ff"
pk = "0xe8e55f617b4b693083f883f70926dd5673fa434cefa3660828759947e2276348"
rho = "0xdedeffdddedeffdddedeffdddedeffdddedeffdddedeffdddedeffdddedeffdd"
value = 2378237
zsl.createShielding(rho, pk, value);
Results in:
cm = "0x58e38183982c6f7981e9f3ce0a735fdd4ca2f0cd88db6ee608c2fe1e84142d0d"
send_nf = "0xc813e257232fae0fee5244aadf98d7ab7a676724c128cd3c0d52d3a01739a3da"
*/
func (api *PublicZSLAPI) CreateShielding(rho common.Hash, pk common.Hash, value float64) (map[string]interface{}, error) {
result := make(map[string]interface{})
snark.Init()
proof := snark.ProveShielding(rho, pk, uint64(value))
send_nf := computeSendNullifier(rho[:])
cm := computeCommitment(rho, pk, uint64(value))
result["proof"] = "0x" + hex.EncodeToString(proof[:])
result["cm"] = common.BytesToHash(cm)
result["send_nf"] = common.BytesToHash(send_nf)
return result, nil
}
/**
Continuing example above...
ztoken.addCommitment(cm, {from:eth.accounts[0], gas:470000})
rt = ztoken.root()
treeIndex = ztoken.getWitness(cm)[0]
authPath = ztoken.getWitness(cm)[1]
zsl.createUnshielding(rho, sk, value, treeIndex, authPath)
Verify with:
zsl.verifyUnshielding(proof, spend_nf, rt, value)
*/
func (api *PublicZSLAPI) CreateUnshielding(rho common.Hash, sk common.Hash, value float64, treeIndex float64, authPath []string) (map[string]interface{}, error) {
result := make(map[string]interface{})
// copy authentication path array into two dimensional array (as required by snark.ProveUnshielding())
if len(authPath) != ZSL_TREE_DEPTH {
return result, errors.New(fmt.Sprintf("Authentiction path must be %d in length", ZSL_TREE_DEPTH))
}
var authenticationPath [ZSL_TREE_DEPTH][32]byte
for i := 0; i < ZSL_TREE_DEPTH; i++ {
b, err := hex.DecodeString(strings.TrimPrefix(authPath[i], "0x"))
if err != nil {
return result, err
}
var uncle [32]byte
copy(uncle[:], b[:32])
authenticationPath[i] = uncle
}
snark.Init()
proof := snark.ProveUnshielding(rho, sk, uint64(value), uint64(treeIndex), authenticationPath)
send_nf := computeSendNullifier(rho[:])
spend_nf := computeSpendNullifier(rho[:], sk)
result["proof"] = "0x" + hex.EncodeToString(proof[:])
result["send_nf"] = common.BytesToHash(send_nf)
result["spend_nf"] = common.BytesToHash(spend_nf)
return result, nil
}
/*
Dummy inputs:
sk = "0xf0f0f0f00f0f0ffffffffff000000f0f0f0f0f00f0000f0f00f00f0f0f0f00ff";
pk = "0xe8e55f617b4b693083f883f70926dd5673fa434cefa3660828759947e2276348";
rho = "0xdedeffdddedeffdddedeffdddedeffdddedeffdddedeffdddedeffdddedeffdd";
val = 2378237;
uncles = ["0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100","0x8000000000000000000000000000000000000000000000000000000000000100"]
Dummy outputs:
o_rho = "0xfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbac";
o_pk = "0xacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfbacfb";
o_val = 2378237;
Dummy anchor:
anchor = "0x8610652739ac0c6bb6b5353649bb822b26543f0ebe88f32a489a56843cd04f03";
Result:
{
in_spend_nf_1: "0x45ccb210613318d0d127e9947c2ce6b1b246c5c2dd53489c1f39397843410c1a",
in_spend_nf_2: "0x45ccb210613318d0d127e9947c2ce6b1b246c5c2dd53489c1f39397843410c1a",
out_cm_1: "0xd6218a07714dd9fac92bdeefd3f4c0d769f40f4b043ad7e67e7375edc498e45c",
out_cm_2: "0xd6218a07714dd9fac92bdeefd3f4c0d769f40f4b043ad7e67e7375edc498e45c",
out_send_nf_1: "0x35f7ff845e4786d644c9c905fe68fd0f602fea0beb2c341bc5d2defc17c32e86",
out_send_nf_2: "0x35f7ff845e4786d644c9c905fe68fd0f602fea0beb2c341bc5d2defc17c32e86",
proof: "0x301fbec0db39fb81073593813ae45a2031588e3937181fbbb698cd8df2142ac426acb739456f2ea1561b352bb562b9af4835cd7a2f8943440ab014b5b98c6edf0730f645add2ac7940fa32d2bc097b81353193a1ca58fd30ec81fad3eec7acfcca1c2f1c0291b8b5d0fd22819262a15a2d71e92ac04ebb469fa29e43c5cd6b7de40730e7e92d6da23f93d575444eddd38c89fdec8f94a6294afef4aa9da9c2f20035141cf4efb334c820d5e0a98ffe01492e7dba547cf433d7e8521ed3e7aaec64a20f96d60b2c23d0ba18f0ac383ae186caa3f445dc522c21d4f6a0a931933729c210c57f8c6a1d51fce2e2d0cc5cb6b3afbdbfb922d158fa85bdc78b9dbc44d78e12306d1b53090d8937e79cd58f544131ad56b11806cb60c1fa759674dc2c3dde4b041370ea7a21c4ba6f64b03b2d7fc57ae609b09685a5c61b9048a84dbf768bc92b304fe96c28c7b59093fad132f7c259a41f0318203e6fa8c3d00b2fc72605c3120bd270ab8a548caf964457cf48256cb95238ce0faa021c7c5e821d0974289e602430711fec13a9b59a3f6bd805e12561730dce6c72de82b7b6a817d26c6608e0ad1ec88185e209d12512c44f86692eae0b8316f516192ce513471644d5a31bfde01d303a2c3de7c50316adf5b84d0014a17c46f479d7ed75e2458a785958011601e9088013ad9b663738a830c5cbfe8c95424eb26bf5d5aaa6b71f7bdfe4735494c50630658ed6d800d7ad42810e500f8713fef2447a39b71062f2bbcc996c19b2892c2f6ae038042c418d2610acf0a7a571a5a7d1d0a18b0769e92b6c50d72204c8df1d"
}
*/
func (api *PublicZSLAPI) CreateShieldedTransfer(
rho_1 common.Hash, sk_1 common.Hash, value_1 float64, treeIndex_1 float64, authPath_1 []string,
rho_2 common.Hash, sk_2 common.Hash, value_2 float64, treeIndex_2 float64, authPath_2 []string,
out_rho_1 common.Hash, out_pk_1 common.Hash, out_value_1 float64,
out_rho_2 common.Hash, out_pk_2 common.Hash, out_value_2 float64,
) (map[string]interface{}, error) {
result := make(map[string]interface{})
// copy authentication path array into two dimensional array (as required by snark.ProveUnshielding())
if len(authPath_1) != ZSL_TREE_DEPTH {
return result, errors.New(fmt.Sprintf("Authentication path 1 must be %d in length", ZSL_TREE_DEPTH))
}
var authenticationPath_1 [ZSL_TREE_DEPTH][32]byte
for i := 0; i < ZSL_TREE_DEPTH; i++ {
b, err := hex.DecodeString(strings.TrimPrefix(authPath_1[i], "0x"))
if err != nil {
return result, err
}
var uncle [32]byte
copy(uncle[:], b[:32])
authenticationPath_1[i] = uncle
}
if len(authPath_2) != ZSL_TREE_DEPTH {
return result, errors.New(fmt.Sprintf("Authentication path 2 must be %d in length", ZSL_TREE_DEPTH))
}
var authenticationPath_2 [ZSL_TREE_DEPTH][32]byte
for i := 0; i < ZSL_TREE_DEPTH; i++ {
b, err := hex.DecodeString(strings.TrimPrefix(authPath_2[i], "0x"))
if err != nil {
return result, err
}
var uncle [32]byte
copy(uncle[:], b[:32])
authenticationPath_2[i] = uncle
}
snark.Init()
proof := snark.ProveTransfer(
rho_1, sk_1, uint64(value_1), uint64(treeIndex_1), authenticationPath_1,
rho_2, sk_2, uint64(value_2), uint64(treeIndex_2), authenticationPath_2,
out_rho_1, out_pk_1, uint64(out_value_1),
out_rho_2, out_pk_2, uint64(out_value_2),
)
send_nf_1 := computeSendNullifier(out_rho_1[:])
send_nf_2 := computeSendNullifier(out_rho_2[:])
spend_nf_1 := computeSpendNullifier(rho_1[:], sk_1)
spend_nf_2 := computeSpendNullifier(rho_2[:], sk_2)
cm_1 := computeCommitment(out_rho_1, out_pk_1, uint64(out_value_1))
cm_2 := computeCommitment(out_rho_2, out_pk_2, uint64(out_value_2))
result["proof"] = "0x" + hex.EncodeToString(proof[:])
result["out_send_nf_1"] = common.BytesToHash(send_nf_1)
result["out_send_nf_2"] = common.BytesToHash(send_nf_2)
result["in_spend_nf_1"] = common.BytesToHash(spend_nf_1)
result["in_spend_nf_2"] = common.BytesToHash(spend_nf_2)
result["out_cm_1"] = common.BytesToHash(cm_1)
result["out_cm_2"] = common.BytesToHash(cm_2)
return result, nil
}
// geth: zsl.verifyShielding(proof, send_nf, cm, value);
// Javascript numbers are floats, there is no support for 64-bit integers.
func (api *PublicZSLAPI) VerifyShielding(proofHex string, send_nf common.Hash, cm common.Hash, value float64) (bool, error) {
proof, err := getProofFromHex(proofHex)
if err != nil {
return false, err
}
snark.Init()
result := snark.VerifyShielding(proof, send_nf, cm, uint64(value))
return result, nil
}
// geth: zsl.verifyShielding(proof, spend_nf, rt, value);
// Javascript numbers are floats, there is no support for 64-bit integers.
func (api *PublicZSLAPI) VerifyUnshielding(proofHex string, spend_nf common.Hash, rt common.Hash, value float64) (bool, error) {
proof, err := getProofFromHex(proofHex)
if err != nil {
return false, err
}
snark.Init()
result := snark.VerifyUnshielding(proof, spend_nf, rt, uint64(value))
return result, nil
}
func (api *PublicZSLAPI) VerifyShieldedTransfer(
proofHex string,
anchor common.Hash,
spend_nf_1 common.Hash,
spend_nf_2 common.Hash,
send_nf_1 common.Hash,
send_nf_2 common.Hash,
cm_1 common.Hash,
cm_2 common.Hash) (bool, error) {
proof, err := getProofFromHex(proofHex)
if err != nil {
return false, err
}
snark.Init()
result := snark.VerifyTransfer(proof, anchor, spend_nf_1, spend_nf_2, send_nf_1, send_nf_2, cm_1, cm_2)
return result, nil
}
// Generate 32 bytes of randomness for use with private contracts i.e. r_alice, r_bob.
func (api *PublicZSLAPI) GetRandomness() (common.Hash, error) {
buf := make([]byte, 32)
_, err := rand.Read(buf)
if err != nil {
return common.BytesToHash(buf), err
}
return common.BytesToHash(buf), nil
}
// Create a shielded address and return all components: a_sk, a_pk
func (api *PublicZSLAPI) GetNewAddress() (map[string]interface{}, error) {
result := make(map[string]interface{})
buf := make([]byte, 32)
_, err := rand.Read(buf)
if err != nil {
return result, err
}
result["a_sk"] = common.BytesToHash(buf)
result["a_pk"] = common.BytesToHash(crypto.Sha256(buf))
return result, nil
}
// Test copied from from snark_test.go
func (api *PublicZSLAPI) DebugShielding() (bool, error) {
snark.Init()
proof := snark.ProveShielding(
[32]byte{0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac},
[32]byte{0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb},
2378237)
result := snark.VerifyShielding(proof,
[32]byte{0x35, 0xf7, 0xff, 0x84, 0x5e, 0x47, 0x86, 0xd6, 0x44, 0xc9, 0xc9, 0x05, 0xfe, 0x68, 0xfd, 0x0f, 0x60, 0x2f, 0xea, 0x0b, 0xeb, 0x2c, 0x34, 0x1b, 0xc5, 0xd2, 0xde, 0xfc, 0x17, 0xc3, 0x2e, 0x86},
[32]byte{0xd6, 0x21, 0x8a, 0x07, 0x71, 0x4d, 0xd9, 0xfa, 0xc9, 0x2b, 0xde, 0xef, 0xd3, 0xf4, 0xc0, 0xd7, 0x69, 0xf4, 0x0f, 0x4b, 0x04, 0x3a, 0xd7, 0xe6, 0x7e, 0x73, 0x75, 0xed, 0xc4, 0x98, 0xe4, 0x5c},
2378237)
if !result {
return false, errors.New("proof was not valid as expected")
}
result = snark.VerifyShielding(proof,
[32]byte{0x35, 0xf7, 0xff, 0x84, 0x5e, 0x47, 0x86, 0xd6, 0x44, 0xc9, 0xc9, 0x05, 0xfe, 0x68, 0xfd, 0x0f, 0x60, 0x2f, 0xea, 0x0b, 0xeb, 0x2c, 0x34, 0x1b, 0xc5, 0xd2, 0xde, 0xfc, 0x17, 0xc3, 0x2e, 0x86},
[32]byte{0xd6, 0x21, 0x8a, 0x07, 0x71, 0x4d, 0xd9, 0xfa, 0xc9, 0x2b, 0xde, 0xef, 0xd3, 0xf4, 0xc0, 0xd7, 0x69, 0xf4, 0x0f, 0x4b, 0x04, 0x3a, 0xd7, 0xe6, 0x7e, 0x73, 0x75, 0xed, 0xc4, 0x98, 0xe4, 0x5c},
2378236)
if result {
return false, errors.New("proof was not invalid as expected")
}
result = snark.VerifyShielding(proof,
[32]byte{0x34, 0xf7, 0xff, 0x84, 0x5e, 0x47, 0x86, 0xd6, 0x44, 0xc9, 0xc9, 0x05, 0xfe, 0x68, 0xfd, 0x0f, 0x60, 0x2f, 0xea, 0x0b, 0xeb, 0x2c, 0x34, 0x1b, 0xc5, 0xd2, 0xde, 0xfc, 0x17, 0xc3, 0x2e, 0x86},
[32]byte{0xd6, 0x21, 0x8a, 0x07, 0x71, 0x4d, 0xd9, 0xfa, 0xc9, 0x2b, 0xde, 0xef, 0xd3, 0xf4, 0xc0, 0xd7, 0x69, 0xf4, 0x0f, 0x4b, 0x04, 0x3a, 0xd7, 0xe6, 0x7e, 0x73, 0x75, 0xed, 0xc4, 0x98, 0xe4, 0x5c},
2378237)
if result {
return false, errors.New("proof was not invalid as expected")
}
return true, nil
}
// Test copied from from snark_test.go
func (api *PublicZSLAPI) DebugUnshielding() (bool, error) {
snark.Init()
proof := snark.ProveUnshielding(
[32]byte{0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd},
[32]byte{0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff},
2378237,
0,
[29][32]byte{
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00}})
result := snark.VerifyUnshielding(proof,
[32]byte{0x45, 0xcc, 0xb2, 0x10, 0x61, 0x33, 0x18, 0xd0, 0xd1, 0x27, 0xe9, 0x94, 0x7c, 0x2c, 0xe6, 0xb1, 0xb2, 0x46, 0xc5, 0xc2, 0xdd, 0x53, 0x48, 0x9c, 0x1f, 0x39, 0x39, 0x78, 0x43, 0x41, 0x0c, 0x1a},
[32]byte{0x86, 0x10, 0x65, 0x27, 0x39, 0xac, 0x0c, 0x6b, 0xb6, 0xb5, 0x35, 0x36, 0x49, 0xbb, 0x82, 0x2b, 0x26, 0x54, 0x3f, 0x0e, 0xbe, 0x88, 0xf3, 0x2a, 0x48, 0x9a, 0x56, 0x84, 0x3c, 0xd0, 0x4f, 0x03},
2378237)
if !result {
return false, errors.New("proof was not valid as expected")
}
result = snark.VerifyUnshielding(proof,
[32]byte{0x45, 0xcc, 0xb2, 0x10, 0x61, 0x33, 0x18, 0xd0, 0xd1, 0x27, 0xe9, 0x94, 0x7c, 0x2c, 0xe6, 0xb1, 0xb2, 0x46, 0xc5, 0xc2, 0xdd, 0x53, 0x48, 0x9c, 0x1f, 0x39, 0x39, 0x78, 0x43, 0x41, 0x0c, 0x1a},
[32]byte{0x86, 0x10, 0x65, 0x27, 0x39, 0xac, 0x0c, 0x6b, 0xb6, 0xb5, 0x35, 0x36, 0x49, 0xbb, 0x82, 0x2b, 0x26, 0x54, 0x3f, 0x0e, 0xbe, 0x88, 0xf3, 0x2a, 0x48, 0x9a, 0x56, 0x84, 0x3c, 0xd0, 0x4f, 0x03},
2378236)
if result {
return false, errors.New("proof was not invalid as expected")
}
result = snark.VerifyUnshielding(proof,
[32]byte{0x44, 0xcc, 0xb2, 0x10, 0x61, 0x33, 0x18, 0xd0, 0xd1, 0x27, 0xe9, 0x94, 0x7c, 0x2c, 0xe6, 0xb1, 0xb2, 0x46, 0xc5, 0xc2, 0xdd, 0x53, 0x48, 0x9c, 0x1f, 0x39, 0x39, 0x78, 0x43, 0x41, 0x0c, 0x1a},
[32]byte{0x86, 0x10, 0x65, 0x27, 0x39, 0xac, 0x0c, 0x6b, 0xb6, 0xb5, 0x35, 0x36, 0x49, 0xbb, 0x82, 0x2b, 0x26, 0x54, 0x3f, 0x0e, 0xbe, 0x88, 0xf3, 0x2a, 0x48, 0x9a, 0x56, 0x84, 0x3c, 0xd0, 0x4f, 0x03},
2378237)
if result {
return false, errors.New("proof was not invalid as expected")
}
result = snark.VerifyUnshielding(proof,
[32]byte{0x45, 0xcc, 0xb2, 0x10, 0x61, 0x33, 0x18, 0xd0, 0xd1, 0x27, 0xe9, 0x94, 0x7c, 0x2c, 0xe6, 0xb1, 0xb2, 0x46, 0xc5, 0xc2, 0xdd, 0x53, 0x48, 0x9c, 0x1f, 0x39, 0x39, 0x78, 0x43, 0x41, 0x0c, 0x1a},
[32]byte{0x88, 0x10, 0x65, 0x27, 0x39, 0xac, 0x0c, 0x6b, 0xb6, 0xb5, 0x35, 0x36, 0x49, 0xbb, 0x82, 0x2b, 0x26, 0x54, 0x3f, 0x0e, 0xbe, 0x88, 0xf3, 0x2a, 0x48, 0x9a, 0x56, 0x84, 0x3c, 0xd0, 0x4f, 0x03},
2378237)
if result {
return false, errors.New("proof was not invalid as expected")
}
return true, nil
}
// Test copied from from snark_test.go
func (api *PublicZSLAPI) DebugShieldedTransfer() (bool, error) {
snark.Init()
proof := snark.ProveTransfer(
[32]byte{0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd},
[32]byte{0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff},
2378237,
0,
[29][32]byte{
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00}},
[32]byte{0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd, 0xde, 0xde, 0xff, 0xdd},
[32]byte{0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff},
2378237,
0,
[29][32]byte{
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x00}},
[32]byte{0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac},
[32]byte{0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb},
2378237,
[32]byte{0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac},
[32]byte{0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb, 0xac, 0xfb},
2378237)
result := snark.VerifyTransfer(proof,
[32]byte{0x86, 0x10, 0x65, 0x27, 0x39, 0xac, 0x0c, 0x6b, 0xb6, 0xb5, 0x35, 0x36, 0x49, 0xbb, 0x82, 0x2b, 0x26, 0x54, 0x3f, 0x0e, 0xbe, 0x88, 0xf3, 0x2a, 0x48, 0x9a, 0x56, 0x84, 0x3c, 0xd0, 0x4f, 0x03},
[32]byte{0x45, 0xcc, 0xb2, 0x10, 0x61, 0x33, 0x18, 0xd0, 0xd1, 0x27, 0xe9, 0x94, 0x7c, 0x2c, 0xe6, 0xb1, 0xb2, 0x46, 0xc5, 0xc2, 0xdd, 0x53, 0x48, 0x9c, 0x1f, 0x39, 0x39, 0x78, 0x43, 0x41, 0x0c, 0x1a},
[32]byte{0x45, 0xcc, 0xb2, 0x10, 0x61, 0x33, 0x18, 0xd0, 0xd1, 0x27, 0xe9, 0x94, 0x7c, 0x2c, 0xe6, 0xb1, 0xb2, 0x46, 0xc5, 0xc2, 0xdd, 0x53, 0x48, 0x9c, 0x1f, 0x39, 0x39, 0x78, 0x43, 0x41, 0x0c, 0x1a},
[32]byte{0x35, 0xf7, 0xff, 0x84, 0x5e, 0x47, 0x86, 0xd6, 0x44, 0xc9, 0xc9, 0x05, 0xfe, 0x68, 0xfd, 0x0f, 0x60, 0x2f, 0xea, 0x0b, 0xeb, 0x2c, 0x34, 0x1b, 0xc5, 0xd2, 0xde, 0xfc, 0x17, 0xc3, 0x2e, 0x86},
[32]byte{0x35, 0xf7, 0xff, 0x84, 0x5e, 0x47, 0x86, 0xd6, 0x44, 0xc9, 0xc9, 0x05, 0xfe, 0x68, 0xfd, 0x0f, 0x60, 0x2f, 0xea, 0x0b, 0xeb, 0x2c, 0x34, 0x1b, 0xc5, 0xd2, 0xde, 0xfc, 0x17, 0xc3, 0x2e, 0x86},
[32]byte{0xd6, 0x21, 0x8a, 0x07, 0x71, 0x4d, 0xd9, 0xfa, 0xc9, 0x2b, 0xde, 0xef, 0xd3, 0xf4, 0xc0, 0xd7, 0x69, 0xf4, 0x0f, 0x4b, 0x04, 0x3a, 0xd7, 0xe6, 0x7e, 0x73, 0x75, 0xed, 0xc4, 0x98, 0xe4, 0x5c},
[32]byte{0xd6, 0x21, 0x8a, 0x07, 0x71, 0x4d, 0xd9, 0xfa, 0xc9, 0x2b, 0xde, 0xef, 0xd3, 0xf4, 0xc0, 0xd7, 0x69, 0xf4, 0x0f, 0x4b, 0x04, 0x3a, 0xd7, 0xe6, 0x7e, 0x73, 0x75, 0xed, 0xc4, 0x98, 0xe4, 0x5c})
if !result {
return false, errors.New("proof was not valid as expected")
}
result = snark.VerifyTransfer(proof,
[32]byte{0x85, 0x10, 0x65, 0x27, 0x39, 0xac, 0x0c, 0x6b, 0xb6, 0xb5, 0x35, 0x36, 0x49, 0xbb, 0x82, 0x2b, 0x26, 0x54, 0x3f, 0x0e, 0xbe, 0x88, 0xf3, 0x2a, 0x48, 0x9a, 0x56, 0x84, 0x3c, 0xd0, 0x4f, 0x03},
[32]byte{0x45, 0xcc, 0xb2, 0x10, 0x61, 0x33, 0x18, 0xd0, 0xd1, 0x27, 0xe9, 0x94, 0x7c, 0x2c, 0xe6, 0xb1, 0xb2, 0x46, 0xc5, 0xc2, 0xdd, 0x53, 0x48, 0x9c, 0x1f, 0x39, 0x39, 0x78, 0x43, 0x41, 0x0c, 0x1a},
[32]byte{0x45, 0xcc, 0xb2, 0x10, 0x61, 0x33, 0x18, 0xd0, 0xd1, 0x27, 0xe9, 0x94, 0x7c, 0x2c, 0xe6, 0xb1, 0xb2, 0x46, 0xc5, 0xc2, 0xdd, 0x53, 0x48, 0x9c, 0x1f, 0x39, 0x39, 0x78, 0x43, 0x41, 0x0c, 0x1a},
[32]byte{0x35, 0xf7, 0xff, 0x84, 0x5e, 0x47, 0x86, 0xd6, 0x44, 0xc9, 0xc9, 0x05, 0xfe, 0x68, 0xfd, 0x0f, 0x60, 0x2f, 0xea, 0x0b, 0xeb, 0x2c, 0x34, 0x1b, 0xc5, 0xd2, 0xde, 0xfc, 0x17, 0xc3, 0x2e, 0x86},
[32]byte{0x35, 0xf7, 0xff, 0x84, 0x5e, 0x47, 0x86, 0xd6, 0x44, 0xc9, 0xc9, 0x05, 0xfe, 0x68, 0xfd, 0x0f, 0x60, 0x2f, 0xea, 0x0b, 0xeb, 0x2c, 0x34, 0x1b, 0xc5, 0xd2, 0xde, 0xfc, 0x17, 0xc3, 0x2e, 0x86},
[32]byte{0xd6, 0x21, 0x8a, 0x07, 0x71, 0x4d, 0xd9, 0xfa, 0xc9, 0x2b, 0xde, 0xef, 0xd3, 0xf4, 0xc0, 0xd7, 0x69, 0xf4, 0x0f, 0x4b, 0x04, 0x3a, 0xd7, 0xe6, 0x7e, 0x73, 0x75, 0xed, 0xc4, 0x98, 0xe4, 0x5c},
[32]byte{0xd6, 0x21, 0x8a, 0x07, 0x71, 0x4d, 0xd9, 0xfa, 0xc9, 0x2b, 0xde, 0xef, 0xd3, 0xf4, 0xc0, 0xd7, 0x69, 0xf4, 0x0f, 0x4b, 0x04, 0x3a, 0xd7, 0xe6, 0x7e, 0x73, 0x75, 0xed, 0xc4, 0x98, 0xe4, 0x5c})
if result {
return false, errors.New("proof was not invalid as expected")
}
return true, nil
}

View File

@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/common/registrar/ethreg" "github.com/ethereum/go-ethereum/common/registrar/ethreg"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/quorum" "github.com/ethereum/go-ethereum/core/quorum"
"github.com/ethereum/go-ethereum/core/zsl"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
@ -327,6 +328,12 @@ func (s *Ethereum) APIs() []rpc.API {
Version: "1.0", Version: "1.0",
Service: quorum.NewPublicQuorumAPI(s.blockVoting), Service: quorum.NewPublicQuorumAPI(s.blockVoting),
}, },
{
Namespace: "zsl",
Version: "1.0",
Service: zsl.NewPublicZSLAPI(),
Public: true,
},
}...) }...)
} }

View File

@ -32,6 +32,7 @@ var Modules = map[string]string{
"rpc": RPC_JS, "rpc": RPC_JS,
"shh": Shh_JS, "shh": Shh_JS,
"txpool": TxPool_JS, "txpool": TxPool_JS,
"zsl": ZSL_JS,
} }
const Bzz_JS = ` const Bzz_JS = `
@ -683,6 +684,95 @@ web3._extend({
}); });
` `
const ZSL_JS = `
web3._extend({
property: 'zsl',
methods:
[
new web3._extend.Method({
name: 'loadTracker',
call: 'zsl_loadTracker',
params: 1
}),
new web3._extend.Method({
name: 'saveTracker',
call: 'zsl_saveTracker',
params: 2
}),
new web3._extend.Method({
name: 'getCommitment',
call: 'zsl_getCommitment',
params: 3
}),
new web3._extend.Method({
name: 'getSendNullifier',
call: 'zsl_getSendNullifier',
params: 1
}),
new web3._extend.Method({
name: 'getSpendNullifier',
call: 'zsl_getSpendNullifier',
params: 2
}),
new web3._extend.Method({
name: 'createShielding',
call: 'zsl_createShielding',
params: 3
}),
new web3._extend.Method({
name: 'createUnshielding',
call: 'zsl_createUnshielding',
params: 5
}),
new web3._extend.Method({
name: 'createShieldedTransfer',
call: 'zsl_createShieldedTransfer',
params: 16
}),
new web3._extend.Method({
name: 'verifyShieldedTransfer',
call: 'zsl_verifyShieldedTransfer',
params: 8
}),
new web3._extend.Method({
name: 'verifyShielding',
call: 'zsl_verifyShielding',
params: 4
}),
new web3._extend.Method({
name: 'verifyUnshielding',
call: 'zsl_verifyUnshielding',
params: 4
}),
new web3._extend.Method({
name: 'getNewAddress',
call: 'zsl_getNewAddress',
params: 0
}),
new web3._extend.Method({
name: 'getRandomness',
call: 'zsl_getRandomness',
params: 0
}),
new web3._extend.Method({
name: 'debugShielding',
call: 'zsl_debugShielding',
params: 0
}),
new web3._extend.Method({
name: 'debugUnshielding',
call: 'zsl_debugUnshielding',
params: 0
}),
new web3._extend.Method({
name: 'debugShieldedTransfer',
call: 'zsl_debugShieldedTransfer',
params: 0
}),
]
});
`
const Quorum_JS = ` const Quorum_JS = `
web3._extend({ web3._extend({
property: 'quorum', property: 'quorum',

View File

@ -40,6 +40,14 @@ var (
EcrecoverGas = big.NewInt(3000) // EcrecoverGas = big.NewInt(3000) //
Sha256WordGas = big.NewInt(12) // Sha256WordGas = big.NewInt(12) //
// ZSL START
// For now, let's just use the same gas as built-in function sha256
Sha256CompressGas = Sha256Gas
Sha256CompressWordGas = Sha256WordGas
VerifyZKProofGas = Sha256Gas
VerifyZKProofWordGas = Sha256WordGas
// ZSL END
MinGasLimit = big.NewInt(700000000) // Minimum the gas limit may ever be. MinGasLimit = big.NewInt(700000000) // Minimum the gas limit may ever be.
GenesisGasLimit = big.NewInt(800000000) // Gas limit of the Genesis block. GenesisGasLimit = big.NewInt(800000000) // Gas limit of the Genesis block.
TargetGasLimit = new(big.Int).Set(GenesisGasLimit) // The artificial target TargetGasLimit = new(big.Int).Set(GenesisGasLimit) // The artificial target

View File

@ -32,8 +32,8 @@ const (
notificationBufferSize = 10000 // max buffered notifications before codec is closed notificationBufferSize = 10000 // max buffered notifications before codec is closed
MetadataApi = "rpc" MetadataApi = "rpc"
DefaultIPCApis = "admin,debug,eth,net,personal,quorum,raft,shh,txpool,web3" DefaultIPCApis = "admin,debug,eth,net,personal,quorum,raft,shh,txpool,web3,zsl"
DefaultHTTPApis = "eth,net,web3" DefaultHTTPApis = "zsl,eth,net,web3"
) )
// CodecOption specifies which type of messages this codec supports // CodecOption specifies which type of messages this codec supports

View File

@ -37,6 +37,10 @@ gopkg.in/natefinch/npipe.v2 c1b8fa8
gopkg.in/sourcemap.v1 v1.0.3 gopkg.in/sourcemap.v1 v1.0.3
gopkg.in/urfave/cli.v1 v1.18.1 gopkg.in/urfave/cli.v1 v1.18.1
# ZSL dependencies
github.com/jpmorganchase/zsl-q/zsl-golang/zsl/sha256 75ceb401fac752b602ba461193a71ae0a131d47f
github.com/jpmorganchase/zsl-q/zsl-golang/zsl/snark 75ceb401fac752b602ba461193a71ae0a131d47f
# raft dependencies # raft dependencies
# TODO: overlay our modifications over latest release, and use the versions for their deps listed in their glide config # TODO: overlay our modifications over latest release, and use the versions for their deps listed in their glide config
github.com/coreos/etcd v3.1.0 # With aa899a37086c4b2a839bf06d927d72d64de manually added github.com/coreos/etcd v3.1.0 # With aa899a37086c4b2a839bf06d927d72d64de manually added

1
vendor/github.com/jpmorganchase/zsl-q generated vendored Submodule

@ -0,0 +1 @@
Subproject commit 75ceb401fac752b602ba461193a71ae0a131d47f