Commit 4bf5547c authored by mdj33's avatar mdj33 Committed by vipwzw

update circuits

parent 45ec8646
......@@ -295,10 +295,11 @@ txFee=100000000
#私对私token转账,花费token(true)还是BTY(false),
tokenFee=false
#curve H point
pointHX="10190477835300927557649934238820360529458681672073866116232821892325659279502"
pointHY="7969140283216448215269095418467361784159407896899334866715345504515077887397"
pointHX="9252662952969393856711468743327022054484546162727338092576697495684140272191"
pointHY="8220002160263982499510761441032261960817037857915665984040705585999508400744"
#电路最大支持1024个叶子hash,10 level, 配置可以小于1024,但不能大于
maxTreeLeaves=1024
hashSeed="seed"
[metrics]
#是否使能发送metrics数据的发送
......
......@@ -12,6 +12,8 @@ require (
github.com/bitly/go-simplejson v0.5.0
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/btcsuite/btcd v0.22.0-beta
github.com/consensys/gnark v0.5.0
github.com/consensys/gnark-crypto v0.5.0
github.com/coreos/etcd v3.3.15+incompatible
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/davecgh/go-spew v1.1.1
......
......@@ -9,7 +9,7 @@ OUT_DIR="${1}/$strapp"
mkdir -p "${OUT_DIR}"/gnark
# shellcheck disable=SC2086
cp ./build/* "${OUT_DIR}"
cp -r ./gnark/circuit "${OUT_DIR}"/gnark
cp -r ./gnark/* "${OUT_DIR}"/gnark
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
......
This diff is collapsed.
package main
import (
util "github.com/33cn/plugin/plugin/dapp/mix/cmd/gnark/circuit"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/gadgets/hash/mimc"
"github.com/consensys/gurvy"
)
func main() {
circuit := NewAuth()
gob.Write("circuit_auth.r1cs", circuit, gurvy.BN256)
}
//spend commit hash the circuit implementing
/*
public:
treeRootHash
authorizeHash(=hash(authpubkey+noterandom))
authorizeSpendHash(=hash(spendpub+value+noterandom))
private:
amount
receiverPubKey
returnPubKey
authorizePubKey
authorizePriKey
spendFlag
noteRandom
noteHash
path...
helper...
valid...
*/
func NewAuth() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
amount := circuit.SECRET_INPUT("Amount")
//spend pubkey
receiverPubKey := circuit.SECRET_INPUT("ReceiverPubKey")
returnPubKey := circuit.SECRET_INPUT("ReturnPubKey")
authorizePriKey := circuit.SECRET_INPUT("AuthorizePriKey")
noteRandom := circuit.SECRET_INPUT("NoteRandom")
authPubKey := circuit.SECRET_INPUT("AuthorizePubKey")
authorizeHash := circuit.PUBLIC_INPUT("AuthorizeHash")
// hash function
mimc, _ := mimc.NewMiMCGadget("seed", gurvy.BN256)
calcAuthPubKey := mimc.Hash(&circuit, authorizePriKey)
circuit.MUSTBE_EQ(authPubKey, calcAuthPubKey)
circuit.MUSTBE_EQ(authorizeHash, mimc.Hash(&circuit, authPubKey, noteRandom))
//note hash random
authSpendHash := circuit.PUBLIC_INPUT("AuthorizeSpendHash")
//spend_flag 0:return_pubkey, 1: spend_pubkey
spendFlag := circuit.SECRET_INPUT("SpendFlag")
circuit.MUSTBE_BOOLEAN(spendFlag)
targetPubHash := circuit.SELECT(spendFlag, receiverPubKey, returnPubKey)
calcAuthSpendHash := mimc.Hash(&circuit, targetPubHash, amount, noteRandom)
circuit.MUSTBE_EQ(authSpendHash, calcAuthSpendHash)
//通过merkle tree保证noteHash存在,即便return,auth都是null也是存在的,则可以不经过授权即可消费
// specify note hash constraint
preImage := mimc.Hash(&circuit, receiverPubKey, returnPubKey, authPubKey, amount, noteRandom)
noteHash := circuit.SECRET_INPUT("NoteHash")
circuit.MUSTBE_EQ(noteHash, preImage)
util.MerkelPathPart(&circuit, mimc, preImage)
r1cs := circuit.ToR1CS()
return r1cs
}
package main
import (
"testing"
backend_bn256 "github.com/consensys/gnark/backend/bn256"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/bn256/groth16"
)
/*
public:
treeRootHash
authorizePubKey
authorizeHash(=hash(authpubkey+noterandom))
authorizeSpendHash(=hash(spendpub+value+noterandom))
private:
amount
receiverPubKey
returnPubKey
authorizePriKey
spendFlag
noteRandom
path...
helper...
valid...
*/
func TestAuthorizeSpend(t *testing.T) {
assert := groth16.NewAssert(t)
r1cs := NewAuth()
r1csBN256 := backend_bn256.Cast(r1cs)
{
good := backend.NewAssignment()
good.Assign(backend.Public, "TreeRootHash", "10531321614990797034921282585661869614556487056951485265320464926630499341310")
good.Assign(backend.Public, "AuthorizePubKey", "13519883267141251871527102103999205179714486518503885909948192364772977661583")
good.Assign(backend.Public, "AuthorizeHash", "1267825436937766239630340333349685320927256968591056373125946583184548355070")
good.Assign(backend.Public, "AuthorizeSpendHash", "14468512365438613046028281588661351435476168610934165547900473609197783547663")
good.Assign(backend.Secret, "Amount", "28242048")
good.Assign(backend.Secret, "ReceiverPubKey", "13735985067536865723202617343666111332145536963656464451727087263423649028705")
good.Assign(backend.Secret, "ReturnPubKey", "16067249407809359746114321133992130903102335882983385972747813693681808870497")
good.Assign(backend.Secret, "AuthorizePriKey", "17822967620457187568904804290291537271142779717280482398091401115827760898835")
good.Assign(backend.Secret, "SpendFlag", "1")
good.Assign(backend.Secret, "NoteRandom", "2824204835")
good.Assign(backend.Secret, "NoteHash", "16308793397024662832064523892418908145900866571524124093537199035808550255649")
good.Assign(backend.Secret, "Path0", "19561523370160677851616596032513161448778901506614020103852017946679781620105")
good.Assign(backend.Secret, "Path1", "13898857070666440684265042188056372750257678232709763835292910585848522658637")
good.Assign(backend.Secret, "Path2", "15019169196974879571470243100379529757970866395477207575033769902587972032431")
good.Assign(backend.Secret, "Path3", "0")
good.Assign(backend.Secret, "Path4", "0")
good.Assign(backend.Secret, "Path5", "0")
good.Assign(backend.Secret, "Path6", "0")
good.Assign(backend.Secret, "Path7", "0")
good.Assign(backend.Secret, "Path8", "0")
good.Assign(backend.Secret, "Path9", "0")
good.Assign(backend.Secret, "Helper0", "1")
good.Assign(backend.Secret, "Helper1", "1")
good.Assign(backend.Secret, "Helper2", "1")
good.Assign(backend.Secret, "Helper3", "0")
good.Assign(backend.Secret, "Helper4", "0")
good.Assign(backend.Secret, "Helper5", "0")
good.Assign(backend.Secret, "Helper6", "0")
good.Assign(backend.Secret, "Helper7", "0")
good.Assign(backend.Secret, "Helper8", "0")
good.Assign(backend.Secret, "Helper9", "0")
good.Assign(backend.Secret, "Valid0", "1")
good.Assign(backend.Secret, "Valid1", "1")
good.Assign(backend.Secret, "Valid2", "1")
good.Assign(backend.Secret, "Valid3", "0")
good.Assign(backend.Secret, "Valid4", "0")
good.Assign(backend.Secret, "Valid5", "0")
good.Assign(backend.Secret, "Valid6", "0")
good.Assign(backend.Secret, "Valid7", "0")
good.Assign(backend.Secret, "Valid8", "0")
good.Assign(backend.Secret, "Valid9", "0")
assert.Solved(&r1csBN256, good, nil)
}
}
public, TreeRootHash,10531321614990797034921282585661869614556487056951485265320464926630499341310
public, AuthorizeHash,1267825436937766239630340333349685320927256968591056373125946583184548355070
public, AuthorizeSpendHash,14468512365438613046028281588661351435476168610934165547900473609197783547663
secret, Amount,28242048
secret, ReceiverPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, ReturnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
public, AuthorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
secret, AuthorizePriKey,17822967620457187568904804290291537271142779717280482398091401115827760898835
secret, SpendFlag,1
secret, NoteRandom,2824204835
secret, NoteHash,3649361563603415612447884923592927672484439983354650489908367088830561161361
secret, Path0,19561523370160677851616596032513161448778901506614020103852017946679781620105
secret, Path1,13898857070666440684265042188056372750257678232709763835292910585848522658637
secret, Path2,15019169196974879571470243100379529757970866395477207575033769902587972032431
secret, Path3,0
secret, Path4,0
secret, Path5,0
secret, Path6,0
secret, Path7,0
secret, Path8,0
secret, Path9,0
secret, Helper0,1
secret, Helper1,1
secret, Helper2,1
secret, Helper3,1
secret, Helper4,1
secret, Helper5,1
secret, Helper6,1
secret, Helper7,1
secret, Helper8,1
secret, Helper9,1
secret, Valid0,1
secret, Valid1,1
secret, Valid2,1
secret, Valid3,0
secret, Valid4,0
secret, Valid5,0
secret, Valid6,0
secret, Valid7,0
secret, Valid8,0
secret, Valid9,0
package main
import (
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/gadgets/hash/mimc"
"github.com/consensys/gurvy"
)
func main() {
circuit := NewDeposit()
gob.Write("circuit_deposit.r1cs", circuit, gurvy.BN256)
}
//spend commit hash the circuit implementing
/*
public:
NoteHash
Amount
private:
ReceiverPubKey
ReturnPubKey
AuthorizePubKey
NoteRandom
*/
func NewDeposit() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
//公共输入以验证
amount := circuit.PUBLIC_INPUT("Amount")
//spend pubkey
receiverPubKey := circuit.SECRET_INPUT("ReceiverPubKey")
returnPubkey := circuit.SECRET_INPUT("ReturnPubKey")
authPubkey := circuit.SECRET_INPUT("AuthorizePubKey")
// hash function
mimc, _ := mimc.NewMiMCGadget("seed", gurvy.BN256)
//note hash random
noteRandom := circuit.SECRET_INPUT("NoteRandom")
//通过merkle tree保证noteHash存在,即便return,auth都是null也是存在的,则可以不经过授权即可消费
//preImage=hash(spendPubkey, returnPubkey,AuthPubkey,spendValue,noteRandom)
noteHash := circuit.PUBLIC_INPUT("NoteHash")
// specify note hash constraint
preImage := mimc.Hash(&circuit, receiverPubKey, returnPubkey, authPubkey, amount, noteRandom)
circuit.MUSTBE_EQ(noteHash, preImage)
r1cs := circuit.ToR1CS()
return r1cs
}
package main
import (
"testing"
backend_bn256 "github.com/consensys/gnark/backend/bn256"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/bn256/groth16"
)
/*
public:
nodeHash
amount
private:
receiverPubKey
returnPubkey
authorizePubkey
noteRandom
*/
func TestDeposit(t *testing.T) {
assert := groth16.NewAssert(t)
//spend prikey="10190477835300927557649934238820360529458681672073866116232821892325659279502"
//spend pubkey="13735985067536865723202617343666111332145536963656464451727087263423649028705"
//return prikey="7969140283216448215269095418467361784159407896899334866715345504515077887397"
//return pubkey="16067249407809359746114321133992130903102335882983385972747813693681808870497"
//authorize prikey="17822967620457187568904804290291537271142779717280482398091401115827760898835"
//authorize pubkey="13519883267141251871527102103999205179714486518503885909948192364772977661583"
//spend prikey="10407830929890509544473717262275616077696950294748419792758056545898949331744"
//spend pubkey="12419942056983622012214804185935674735538011812395392042541464417352183370586"
r1cs := NewDeposit()
r1csBN256 := backend_bn256.Cast(r1cs)
{
good := backend.NewAssignment()
good.Assign(backend.Public, "noteHash", "16308793397024662832064523892418908145900866571524124093537199035808550255649")
good.Assign(backend.Public, "amount", "28242048")
good.Assign(backend.Secret, "receiverPubKey", "13735985067536865723202617343666111332145536963656464451727087263423649028705")
good.Assign(backend.Secret, "returnPubKey", "16067249407809359746114321133992130903102335882983385972747813693681808870497")
good.Assign(backend.Secret, "authorizePubKey", "13519883267141251871527102103999205179714486518503885909948192364772977661583")
good.Assign(backend.Secret, "noteRandom", "2824204835")
assert.Solved(&r1csBN256, good, nil)
}
}
public, NoteHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
public, Amount,28242048
secret, ReceiverPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, ReturnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
secret, AuthorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
secret, NoteRandom,2824204835
public, TreeRootHash,10531321614990797034921282585661869614556487056951485265320464926630499341310
public, ShieldAmountX,14087975867275911077371231345227824611951436822132762463787130558957838320348
public, ShieldAmountY,15113519960384204624879642069520481336224311978035289236693658603675385299879
public, AuthorizeSpendHash,14468512365438613046028281588661351435476168610934165547900473609197783547663
public, NullifierHash,6747518781649068310795677405858353007442326529625450860668944156162052335195
secret, Amount,28242048
secret, AmountRandom,35
secret, ReceiverPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, ReturnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
secret, AuthorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
secret, SpendPriKey,10190477835300927557649934238820360529458681672073866116232821892325659279502
secret, SpendFlag,1
secret, AuthorizeFlag,1
secret, NoteRandom,2824204835
secret, NoteHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
secret, Path0,19561523370160677851616596032513161448778901506614020103852017946679781620105
secret, Path1,13898857070666440684265042188056372750257678232709763835292910585848522658637
secret, Path2,15019169196974879571470243100379529757970866395477207575033769902587972032431
secret, Path3,0
secret, Path4,0
secret, Path5,0
secret, Path6,0
secret, Path7,0
secret, Path8,0
secret, Path9,0
secret, Helper0,1
secret, Helper1,1
secret, Helper2,1
secret, Helper3,1
secret, Helper4,1
secret, Helper5,1
secret, Helper6,1
secret, Helper7,1
secret, Helper8,1
secret, Helper9,1
secret, Valid0,1
secret, Valid1,1
secret, Valid2,1
secret, Valid3,0
secret, Valid4,0
secret, Valid5,0
secret, Valid6,0
secret, Valid7,0
secret, Valid8,0
secret, Valid9,0
package main
import (
util "github.com/33cn/plugin/plugin/dapp/mix/cmd/gnark/circuit"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/gadgets/hash/mimc"
"github.com/consensys/gurvy"
)
func main() {
circuit := NewTransferInput()
gob.Write("circuit_transfer_input.r1cs", circuit, gurvy.BN256)
}
//spend commit hash the circuit implementing
/*
public:
treeRootHash
shieldAmountX
shieldAmountY
authorizeSpendHash
nullifierHash
private:
amount
amountRandom
receiverPubKey
returnPubKey
authorizePubKey
spendPriKey
spendFlag
authorizeFlag
noteRandom
path...
helper...
valid...
*/
func NewTransferInput() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
spendValue := circuit.SECRET_INPUT("Amount")
//spend pubkey
spendPubkey := circuit.SECRET_INPUT("ReceiverPubKey")
returnPubkey := circuit.SECRET_INPUT("ReturnPubKey")
authPubkey := circuit.SECRET_INPUT("AuthorizePubKey")
spendPrikey := circuit.SECRET_INPUT("SpendPriKey")
//spend_flag 0:return_pubkey, 1: spend_pubkey
spendFlag := circuit.SECRET_INPUT("SpendFlag")
circuit.MUSTBE_BOOLEAN(spendFlag)
//auth_check 0: not need auth check, 1:need check
authFlag := circuit.SECRET_INPUT("AuthorizeFlag")
circuit.MUSTBE_BOOLEAN(authFlag)
// hash function
mimc, _ := mimc.NewMiMCGadget("seed", gurvy.BN256)
calcPubHash := mimc.Hash(&circuit, spendPrikey)
targetPubHash := circuit.SELECT(spendFlag, spendPubkey, returnPubkey)
circuit.MUSTBE_EQ(targetPubHash, calcPubHash)
//note hash random
noteRandom := circuit.SECRET_INPUT("NoteRandom")
//need check in database if not null
authHash := circuit.PUBLIC_INPUT("AuthorizeSpendHash")
nullValue := circuit.ALLOCATE(0)
//// specify auth hash constraint
calcAuthSpendHash := mimc.Hash(&circuit, targetPubHash, spendValue, noteRandom)
targetAuthHash := circuit.SELECT(authFlag, calcAuthSpendHash, nullValue)
circuit.MUSTBE_EQ(authHash, targetAuthHash)
//need check in database if not null
nullifierHash := circuit.PUBLIC_INPUT("NullifierHash")
calcNullifierHash := mimc.Hash(&circuit, noteRandom)
circuit.MUSTBE_EQ(nullifierHash, calcNullifierHash)
//通过merkle tree保证noteHash存在,即便return,auth都是null也是存在的,则可以不经过授权即可消费
noteHash := circuit.SECRET_INPUT("NoteHash")
calcReturnPubkey := circuit.SELECT(authFlag, returnPubkey, nullValue)
calcAuthPubkey := circuit.SELECT(authFlag, authPubkey, nullValue)
// specify note hash constraint
preImage := mimc.Hash(&circuit, spendPubkey, calcReturnPubkey, calcAuthPubkey, spendValue, noteRandom)
circuit.MUSTBE_EQ(noteHash, preImage)
util.CommitValuePart(&circuit, spendValue)
util.MerkelPathPart(&circuit, mimc, preImage)
r1cs := circuit.ToR1CS()
return r1cs
}
public, shieldAmountX,14087975867275911077371231345227824611951436822132762463787130558957838320348
public, shieldAmountY,15113519960384204624879642069520481336224311978035289236693658603675385299879
public, noteHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
secret, amount,28242048
secret, amountRandom,35
secret, receiverPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, returnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
secret, authorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
secret, noteRandom,2824204835
package main
import (
util "github.com/33cn/plugin/plugin/dapp/mix/cmd/gnark/circuit"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/gadgets/hash/mimc"
"github.com/consensys/gurvy"
)
func main() {
circuit := NewTransferOutput()
gob.Write("circuit_transfer_output.r1cs", circuit, gurvy.BN256)
}
//spend commit hash the circuit implementing
/*
public:
shieldAmountX
shieldAmountY
noteHash
private:
amount
amountRandom
receiverPubKey
returnPubKey
authorizePubKey
noteRandom
*/
func NewTransferOutput() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
spendValue := circuit.SECRET_INPUT("Amount")
//spend pubkey
spendPubkey := circuit.SECRET_INPUT("ReceiverPubKey")
returnPubkey := circuit.SECRET_INPUT("ReturnPubKey")
authPubkey := circuit.SECRET_INPUT("AuthorizePubKey")
// hash function
mimc, _ := mimc.NewMiMCGadget("seed", gurvy.BN256)
//note hash random
noteRandom := circuit.SECRET_INPUT("NoteRandom")
//通过merkle tree保证noteHash存在,即便return,auth都是null也是存在的,则可以不经过授权即可消费
//preImage=hash(spendPubkey, returnPubkey,AuthPubkey,spendValue,noteRandom)
noteHash := circuit.PUBLIC_INPUT("NoteHash")
// specify note hash constraint
preImage := mimc.Hash(&circuit, spendPubkey, returnPubkey, authPubkey, spendValue, noteRandom)
circuit.MUSTBE_EQ(noteHash, preImage)
util.CommitValuePart(&circuit, spendValue)
r1cs := circuit.ToR1CS()
return r1cs
}
package main
import (
"testing"
backend_bn256 "github.com/consensys/gnark/backend/bn256"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/bn256/groth16"
)
/*
public:
shieldAmountX
shieldAmountY
noteHash
private:
amount
amountRandom
receiverPubKey
returnPubKey
authorizePubKey
noteRandom
*/
func TestTransferOutput(t *testing.T) {
assert := groth16.NewAssert(t)
r1cs := NewTransferOutput()
r1csBN256 := backend_bn256.Cast(r1cs)
{
good := backend.NewAssignment()
good.Assign(backend.Public, "shieldAmountX", "14087975867275911077371231345227824611951436822132762463787130558957838320348")
good.Assign(backend.Public, "shieldAmountY", "15113519960384204624879642069520481336224311978035289236693658603675385299879")
good.Assign(backend.Public, "noteHash", "16308793397024662832064523892418908145900866571524124093537199035808550255649")
good.Assign(backend.Secret, "amount", "28242048")
good.Assign(backend.Secret, "amountRandom", "35")
good.Assign(backend.Secret, "receiverPubKey", "13735985067536865723202617343666111332145536963656464451727087263423649028705")
good.Assign(backend.Secret, "returnPubKey", "16067249407809359746114321133992130903102335882983385972747813693681808870497")
good.Assign(backend.Secret, "authorizePubKey", "13519883267141251871527102103999205179714486518503885909948192364772977661583")
good.Assign(backend.Secret, "noteRandom", "2824204835")
assert.Solved(&r1csBN256, good, nil)
}
}
func TestTransferOutputTemp(t *testing.T) {
assert := groth16.NewAssert(t)
r1cs := NewTransferOutput()
r1csBN256 := backend_bn256.Cast(r1cs)
{
good := backend.NewAssignment()
good.Assign(backend.Public, "shieldAmountX", "3403754862862244121869403834818720211897208891381676574399662060838495940078")
good.Assign(backend.Public, "shieldAmountY", "21401902064308935591303802598664246616585474010691469717860664156067228175223")
good.Assign(backend.Public, "noteHash", "13610259753835165822431524149670478281864477297016371975012414049080268826331")
good.Assign(backend.Secret, "amount", "300000000")
good.Assign(backend.Secret, "amountRandom", "17199160520698273243343882915453578587")
good.Assign(backend.Secret, "receiverPubKey", "18829345085195922012068709111582461121107908772422825655963168999800303848486")
good.Assign(backend.Secret, "returnPubKey", "0")
good.Assign(backend.Secret, "authorizePubKey", "0")
good.Assign(backend.Secret, "noteRandom", "5029847585956946251661044349066579681630691396824473307862642244158835326399")
assert.Solved(&r1csBN256, good, nil)
}
}
func TestTransferOutputChange(t *testing.T) {
assert := groth16.NewAssert(t)
r1cs := NewTransferOutput()
r1csBN256 := backend_bn256.Cast(r1cs)
{
good := backend.NewAssignment()
good.Assign(backend.Public, "shieldAmountX", "10703086269439751873106176219875739041896146845566831131812760688039385779519")
good.Assign(backend.Public, "shieldAmountY", "19139103177181062461420753508628290808191900352948606822559796252948653071734")
good.Assign(backend.Public, "noteHash", "13134546856103113099750783399130805737503059294172727906371169345876474249458")
good.Assign(backend.Secret, "amount", "199900000")
good.Assign(backend.Secret, "amountRandom", "86450085302571105354912213444290224646")
good.Assign(backend.Secret, "receiverPubKey", "7244551457692363731356498279463138379576484998878425864678733206990733443457")
good.Assign(backend.Secret, "returnPubKey", "0")
good.Assign(backend.Secret, "authorizePubKey", "0")
good.Assign(backend.Secret, "noteRandom", "7266395330102686861165120582739238575545854195882356283931287331463151808870")
assert.Solved(&r1csBN256, good, nil)
}
}
package circuit
import (
"strconv"
"github.com/consensys/gnark/frontend"
twistededwards_gadget "github.com/consensys/gnark/gadgets/algebra/twistededwards"
"github.com/consensys/gnark/gadgets/hash/mimc"
"github.com/consensys/gurvy"
fr_bn256 "github.com/consensys/gurvy/bn256/fr"
)
func MerkelPathPart(circuit *frontend.CS, mimc mimc.MiMCGadget, noteHash *frontend.Constraint) {
var proofSet, helper, valid []*frontend.Constraint
merkleRoot := circuit.PUBLIC_INPUT("TreeRootHash")
proofSet = append(proofSet, noteHash)
//helper[0],valid[0]占位, 方便接口只设置有效值
helper = append(helper, circuit.ALLOCATE("1"))
valid = append(valid, circuit.ALLOCATE("1"))
//depth:10, path num need be 9
for i := 0; i < 10; i++ {
proofSet = append(proofSet, circuit.SECRET_INPUT("Path"+strconv.Itoa(i)))
helper = append(helper, circuit.SECRET_INPUT("Helper"+strconv.Itoa(i)))
valid = append(valid, circuit.SECRET_INPUT("Valid"+strconv.Itoa(i)))
}
VerifyMerkleProof(circuit, mimc, merkleRoot, proofSet, helper, valid)
}
func VerifyMerkleProof(circuit *frontend.CS, h mimc.MiMCGadget, merkleRoot *frontend.Constraint, proofSet, helper, valid []*frontend.Constraint) {
sum := leafSum(circuit, h, proofSet[0])
for i := 1; i < len(proofSet); i++ {
circuit.MUSTBE_BOOLEAN(helper[i])
d1 := circuit.SELECT(helper[i], sum, proofSet[i])
d2 := circuit.SELECT(helper[i], proofSet[i], sum)
rst := nodeSum(circuit, h, d1, d2)
sum = circuit.SELECT(valid[i], rst, sum)
}
// Compare our calculated Merkle root to the desired Merkle root.
circuit.MUSTBE_EQ(sum, merkleRoot)
}
// nodeSum returns the hash created from data inserted to form a leaf.
// Without domain separation.
func nodeSum(circuit *frontend.CS, h mimc.MiMCGadget, a, b *frontend.Constraint) *frontend.Constraint {
res := h.Hash(circuit, a, b)
return res
}
// leafSum returns the hash created from data inserted to form a leaf.
// Without domain separation.
func leafSum(circuit *frontend.CS, h mimc.MiMCGadget, data *frontend.Constraint) *frontend.Constraint {
res := h.Hash(circuit, data)
return res
}
func CommitValuePart(circuit *frontend.CS, spendValue *frontend.Constraint) {
//cmt=transfer_value*G + random_value*H
cmtvalueX := circuit.PUBLIC_INPUT("ShieldAmountX")
cmtvalueY := circuit.PUBLIC_INPUT("ShieldAmountY")
// set curve parameters
edgadget, _ := twistededwards_gadget.NewEdCurveGadget(gurvy.BN256)
// set point G in the circuit
pointGSnark := twistededwards_gadget.NewPointGadget(circuit, nil, nil)
//to avoid <0 values input
//negOne := circuit.ALLOCATE("-1")
//negSpendVal := circuit.MUL(spendValue,negOne)
//circuit.MUSTBE_LESS_OR_EQ(negSpendVal, 0, 256)
circuit.MUSTBE_LESS_OR_EQ(spendValue, 1000000000000000000, 256)
// set point G in the circuit
pointGSnark.ScalarMulFixedBase(circuit, edgadget.BaseX, edgadget.BaseY, spendValue, edgadget)
pointGSnark.X.Tag("xg")
pointGSnark.Y.Tag("yg")
transfer_random := circuit.SECRET_INPUT("AmountRandom")
//circuit.MUSTBE_LESS_OR_EQ(random_value,10000000000,256)
//H is not G, H should be a point that no one know the prikey
var baseX_H, baseY_H fr_bn256.Element
baseX_H.SetString("10190477835300927557649934238820360529458681672073866116232821892325659279502")
baseY_H.SetString("7969140283216448215269095418467361784159407896899334866715345504515077887397")
pointHSnark := twistededwards_gadget.NewPointGadget(circuit, nil, nil)
// add points in circuit (the method updates the underlying plain points as well)
pointHSnark.ScalarMulFixedBase(circuit, baseX_H, baseY_H, transfer_random, edgadget)
pointHSnark.X.Tag("xh")
pointHSnark.Y.Tag("yh")
pointSumSnark := twistededwards_gadget.NewPointGadget(circuit, nil, nil)
pointSumSnark.AddGeneric(circuit, &pointGSnark, &pointHSnark, edgadget)
//cmtvalue=transfer_value*G + random_value*H
circuit.MUSTBE_EQ(cmtvalueX, pointSumSnark.X)
circuit.MUSTBE_EQ(cmtvalueY, pointSumSnark.Y)
}
public, TreeRootHash,10531321614990797034921282585661869614556487056951485265320464926630499341310
public, AuthorizeSpendHash,14468512365438613046028281588661351435476168610934165547900473609197783547663
public, NullifierHash,6747518781649068310795677405858353007442326529625450860668944156162052335195
public, Amount,28242048
secret, ReceiverPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, ReturnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
secret, AuthorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
secret, SpendPriKey,10190477835300927557649934238820360529458681672073866116232821892325659279502
secret, SpendFlag,1
secret, AuthorizeFlag,1
secret, NoteRandom,2824204835
secret, NoteHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
secret, Path0,19561523370160677851616596032513161448778901506614020103852017946679781620105
secret, Path1,13898857070666440684265042188056372750257678232709763835292910585848522658637
secret, Path2,15019169196974879571470243100379529757970866395477207575033769902587972032431
secret, Path3,0
secret, Path4,0
secret, Path5,0
secret, Path6,0
secret, Path7,0
secret, Path8,0
secret, Path9,0
secret, Helper0,1
secret, Helper1,1
secret, Helper2,1
secret, Helper3,1
secret, Helper4,1
secret, Helper5,1
secret, Helper6,1
secret, Helper7,1
secret, Helper8,1
secret, Helper9,1
secret, Valid0,1
secret, Valid1,1
secret, Valid2,1
secret, Valid3,0
secret, Valid4,0
secret, Valid5,0
secret, Valid6,0
secret, Valid7,0
secret, Valid8,0
secret, Valid9,0
package main
import (
util "github.com/33cn/plugin/plugin/dapp/mix/cmd/gnark/circuit"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/gadgets/hash/mimc"
"github.com/consensys/gurvy"
)
func main() {
circuit := NewWithdraw()
gob.Write("circuit_withdraw.r1cs", circuit, gurvy.BN256)
}
//withdraw commit hash the circuit implementing
/*
public:
treeRootHash
authorizeSpendHash
nullifierHash
amount
private:
receiverPubKey
returnPubKey
authorizePubKey
spendPriKey
spendFlag
authorizeFlag
noteRandom
noteHash
path...
helper...
valid...
*/
func NewWithdraw() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
spendValue := circuit.PUBLIC_INPUT("Amount")
//spend pubkey
receiverPubKey := circuit.SECRET_INPUT("ReceiverPubKey")
returnPubkey := circuit.SECRET_INPUT("ReturnPubKey")
authPubkey := circuit.SECRET_INPUT("AuthorizePubKey")
spendPrikey := circuit.SECRET_INPUT("SpendPriKey")
//spend_flag 0:return_pubkey, 1: spend_pubkey
spendFlag := circuit.SECRET_INPUT("SpendFlag")
circuit.MUSTBE_BOOLEAN(spendFlag)
//auth_check 0: not need auth check, 1:need check
authFlag := circuit.SECRET_INPUT("AuthorizeFlag")
circuit.MUSTBE_BOOLEAN(authFlag)
// hash function
mimc, _ := mimc.NewMiMCGadget("seed", gurvy.BN256)
calcPubHash := mimc.Hash(&circuit, spendPrikey)
targetPubHash := circuit.SELECT(spendFlag, receiverPubKey, returnPubkey)
circuit.MUSTBE_EQ(targetPubHash, calcPubHash)
//note hash random
noteRandom := circuit.SECRET_INPUT("NoteRandom")
//need check in database if not null
authHash := circuit.PUBLIC_INPUT("AuthorizeSpendHash")
nullValue := circuit.ALLOCATE(0)
// specify auth hash constraint
calcAuthHash := mimc.Hash(&circuit, targetPubHash, spendValue, noteRandom)
targetAuthHash := circuit.SELECT(authFlag, calcAuthHash, nullValue)
circuit.MUSTBE_EQ(authHash, targetAuthHash)
//need check in database if not null
nullifierHash := circuit.PUBLIC_INPUT("NullifierHash")
calcNullifierHash := mimc.Hash(&circuit, noteRandom)
circuit.MUSTBE_EQ(nullifierHash, calcNullifierHash)
//通过merkle tree保证noteHash存在,即便return,auth都是null也是存在的,则可以不经过授权即可消费
//preImage=hash(spendPubkey, returnPubkey,AuthPubkey,spendValue,noteRandom)
noteHash := circuit.SECRET_INPUT("NoteHash")
calcReturnPubkey := circuit.SELECT(authFlag, returnPubkey, nullValue)
calcAuthPubkey := circuit.SELECT(authFlag, authPubkey, nullValue)
// specify note hash constraint
preImage := mimc.Hash(&circuit, receiverPubKey, calcReturnPubkey, calcAuthPubkey, spendValue, noteRandom)
circuit.MUSTBE_EQ(noteHash, preImage)
util.MerkelPathPart(&circuit, mimc, preImage)
r1cs := circuit.ToR1CS()
return r1cs
}
package main
import (
"testing"
backend_bn256 "github.com/consensys/gnark/backend/bn256"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/bn256/groth16"
)
/*
public:
treeRootHash
authorizeHash
nullifierHash
amount
private:
receiverPubKey
returnPubKey
authorizePubKey
spendPriKey
spendFlag
authorizeFlag
noteRandom
path...
helper...
valid...
*/
func TestWithdraw(t *testing.T) {
assert := groth16.NewAssert(t)
r1cs := NewWithdraw()
r1csBN256 := backend_bn256.Cast(r1cs)
{
good := backend.NewAssignment()
good.Assign(backend.Public, "TreeRootHash", "10531321614990797034921282585661869614556487056951485265320464926630499341310")
good.Assign(backend.Public, "AuthorizeSpendHash", "14468512365438613046028281588661351435476168610934165547900473609197783547663")
good.Assign(backend.Public, "NullifierHash", "6747518781649068310795677405858353007442326529625450860668944156162052335195")
good.Assign(backend.Public, "Amount", "28242048")
good.Assign(backend.Secret, "ReceiverPubKey", "13735985067536865723202617343666111332145536963656464451727087263423649028705")
good.Assign(backend.Secret, "ReturnPubKey", "16067249407809359746114321133992130903102335882983385972747813693681808870497")
good.Assign(backend.Secret, "AuthorizePubKey", "13519883267141251871527102103999205179714486518503885909948192364772977661583")
good.Assign(backend.Secret, "SpendPriKey", "10190477835300927557649934238820360529458681672073866116232821892325659279502")
good.Assign(backend.Secret, "SpendFlag", "1")
good.Assign(backend.Secret, "AuthorizeFlag", "1")
good.Assign(backend.Secret, "NoteRandom", "2824204835")
good.Assign(backend.Secret, "NoteHash", "16308793397024662832064523892418908145900866571524124093537199035808550255649")
//nodehash="16308793397024662832064523892418908145900866571524124093537199035808550255649"
good.Assign(backend.Secret, "Path0", "19561523370160677851616596032513161448778901506614020103852017946679781620105")
good.Assign(backend.Secret, "Path1", "13898857070666440684265042188056372750257678232709763835292910585848522658637")
good.Assign(backend.Secret, "Path2", "15019169196974879571470243100379529757970866395477207575033769902587972032431")
good.Assign(backend.Secret, "Path3", "0")
good.Assign(backend.Secret, "Path4", "0")
good.Assign(backend.Secret, "Path5", "0")
good.Assign(backend.Secret, "Path6", "0")
good.Assign(backend.Secret, "Path7", "0")
good.Assign(backend.Secret, "Path8", "0")
good.Assign(backend.Secret, "Path9", "0")
good.Assign(backend.Secret, "Helper0", "1")
good.Assign(backend.Secret, "Helper1", "1")
good.Assign(backend.Secret, "Helper2", "1")
good.Assign(backend.Secret, "Helper3", "0")
good.Assign(backend.Secret, "Helper4", "0")
good.Assign(backend.Secret, "Helper5", "0")
good.Assign(backend.Secret, "Helper6", "0")
good.Assign(backend.Secret, "Helper7", "0")
good.Assign(backend.Secret, "Helper8", "0")
good.Assign(backend.Secret, "Helper9", "0")
good.Assign(backend.Secret, "Valid0", "1")
good.Assign(backend.Secret, "Valid1", "1")
good.Assign(backend.Secret, "Valid2", "1")
good.Assign(backend.Secret, "Valid3", "0")
good.Assign(backend.Secret, "Valid4", "0")
good.Assign(backend.Secret, "Valid5", "0")
good.Assign(backend.Secret, "Valid6", "0")
good.Assign(backend.Secret, "Valid7", "0")
good.Assign(backend.Secret, "Valid8", "0")
good.Assign(backend.Secret, "Valid9", "0")
assert.Solved(&r1csBN256, good, nil)
}
}
func TestWithdraw2(t *testing.T) {
assert := groth16.NewAssert(t)
r1cs := NewWithdraw()
r1csBN256 := backend_bn256.Cast(r1cs)
{
good := backend.NewAssignment()
good.Assign(backend.Public, "TreeRootHash", "7407373673604276152801354004851383461539317977307945198624806503955302548700")
good.Assign(backend.Public, "AuthorizeSpendHash", "0")
good.Assign(backend.Public, "NullifierHash", "3911774040567972872956008387141175001419649692949203140089059098956773329188")
good.Assign(backend.Public, "Amount", "500000000")
good.Assign(backend.Secret, "ReceiverPubKey", "7244551457692363731356498279463138379576484998878425864678733206990733443457")
good.Assign(backend.Secret, "ReturnPubKey", "0")
good.Assign(backend.Secret, "AuthorizePubKey", "0")
good.Assign(backend.Secret, "SpendPriKey", "19115616183616714814727844928908633989028519974595353009754871398745087846141")
good.Assign(backend.Secret, "SpendFlag", "1")
good.Assign(backend.Secret, "AuthorizeFlag", "0")
good.Assign(backend.Secret, "NoteRandom", "13093524699504167542220418896875211339267114119238016501132859435646426190390")
good.Assign(backend.Secret, "NoteHash", "6441981280327245191543878922302235060888201984279829017462503030039593719666")
//nodehash="16308793397024662832064523892418908145900866571524124093537199035808550255649"
good.Assign(backend.Secret, "Path0", "16592081253758169453601069427813166612800474003570537799829885686701266956141")
good.Assign(backend.Secret, "Path1", "0")
good.Assign(backend.Secret, "Path2", "0")
good.Assign(backend.Secret, "Path3", "0")
good.Assign(backend.Secret, "Path4", "0")
good.Assign(backend.Secret, "Path5", "0")
good.Assign(backend.Secret, "Path6", "0")
good.Assign(backend.Secret, "Path7", "0")
good.Assign(backend.Secret, "Path8", "0")
good.Assign(backend.Secret, "Path9", "0")
good.Assign(backend.Secret, "Helper0", "0")
good.Assign(backend.Secret, "Helper1", "0")
good.Assign(backend.Secret, "Helper2", "0")
good.Assign(backend.Secret, "Helper3", "0")
good.Assign(backend.Secret, "Helper4", "0")
good.Assign(backend.Secret, "Helper5", "0")
good.Assign(backend.Secret, "Helper6", "0")
good.Assign(backend.Secret, "Helper7", "0")
good.Assign(backend.Secret, "Helper8", "0")
good.Assign(backend.Secret, "Helper9", "0")
good.Assign(backend.Secret, "Valid0", "1")
good.Assign(backend.Secret, "Valid1", "0")
good.Assign(backend.Secret, "Valid2", "0")
good.Assign(backend.Secret, "Valid3", "0")
good.Assign(backend.Secret, "Valid4", "0")
good.Assign(backend.Secret, "Valid5", "0")
good.Assign(backend.Secret, "Valid6", "0")
good.Assign(backend.Secret, "Valid7", "0")
good.Assign(backend.Secret, "Valid8", "0")
good.Assign(backend.Secret, "Valid9", "0")
assert.Solved(&r1csBN256, good, nil)
}
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"os"
mimcbn256 "github.com/consensys/gnark/crypto/hash/mimc/bn256"
fr_bn256 "github.com/consensys/gurvy/bn256/fr"
"github.com/consensys/gurvy/bn256/twistededwards"
)
// verifyCmd represents the verify command
var calcCmd = &cobra.Command{
Use: "calc",
Short: "calc",
Version: Version,
}
var (
fCommit string
fRandom string
)
func init() {
calcCmd.AddCommand(hashCmd)
calcCmd.AddCommand(commitCmd)
rootCmd.AddCommand(calcCmd)
commitCmd.PersistentFlags().StringVar(&fCommit, "value", "", "specifies commit value")
commitCmd.PersistentFlags().StringVar(&fRandom, "random", "", "specifies random value")
_ = commitCmd.MarkPersistentFlagRequired("value")
_ = commitCmd.MarkPersistentFlagRequired("random")
}
var hashCmd = &cobra.Command{
Use: "hash ...",
Short: "read strings to calc hash",
Run: hash,
Version: Version,
}
func hash(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println("missing input strings")
os.Exit(-1)
}
var sum []byte
for _, k := range args {
fmt.Println("input:", k)
sum = append(sum, getByte(k)...)
}
hash := mimcbn256.Sum("seed", sum)
fmt.Println("hash=", getFrString(hash))
}
func getByte(v string) []byte {
var fr fr_bn256.Element
fr.SetString(v)
return fr.Bytes()
}
func getFrString(v []byte) string {
var f fr_bn256.Element
f.SetBytes(v)
return f.String()
}
var commitCmd = &cobra.Command{
Use: "commit",
Short: "commit value",
Run: commit,
Version: Version,
}
func commit(cmd *cobra.Command, args []string) {
//if len(args) < 1 {
// fmt.Println("missing input strings")
// os.Exit(-1)
//}
var basex, basey, baseHx, baseHy fr_bn256.Element
basex.SetString("5299619240641551281634865583518297030282874472190772894086521144482721001553")
basey.SetString("16950150798460657717958625567821834550301663161624707787222815936182638968203")
baseHx.SetString("10190477835300927557649934238820360529458681672073866116232821892325659279502")
baseHy.SetString("7969140283216448215269095418467361784159407896899334866715345504515077887397")
basePoint := twistededwards.NewPoint(basex, basey)
baseHPoint := twistededwards.NewPoint(baseHx, baseHy)
var frCommit, frRandom fr_bn256.Element
frCommit.SetString(fCommit).FromMont()
frRandom.SetString(fRandom).FromMont()
fmt.Println("commit", fCommit, "random", fRandom)
var commitPoint, randomPoint, finalPoint twistededwards.Point
commitPoint.ScalarMul(&basePoint, frCommit)
randomPoint.ScalarMul(&baseHPoint, frRandom)
finalPoint.Add(&commitPoint, &randomPoint)
fmt.Println("finalPoint X:", finalPoint.X.String())
fmt.Println("finalPoint Y:", finalPoint.Y.String())
//
//fmt.Println("commitX:",commitPoint.X.String())
//fmt.Println("commitY:",commitPoint.Y.String())
//
//fmt.Println("randomX:",randomPoint.X.String())
//fmt.Println("randomY:",randomPoint.Y.String())
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import "errors"
var (
errNotFound = errors.New("file not found")
errUnknownCurve = errors.New("unknown curve id")
)
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/consensys/gnark/backend"
backend_bls377 "github.com/consensys/gnark/backend/bls377"
groth16_bls377 "github.com/consensys/gnark/backend/bls377/groth16"
backend_bls381 "github.com/consensys/gnark/backend/bls381"
groth16_bls381 "github.com/consensys/gnark/backend/bls381/groth16"
backend_bn256 "github.com/consensys/gnark/backend/bn256"
groth16_bn256 "github.com/consensys/gnark/backend/bn256/groth16"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gurvy"
"github.com/spf13/cobra"
)
// proveCmd represents the prove command
var proveCmd = &cobra.Command{
Use: "prove [circuit.r1cs]",
Short: "creates a (zk)proof for provided circuit and solution",
Run: cmdProve,
Version: Version,
}
var (
fProofPath string
fInputPath string
fCount uint
)
func init() {
rootCmd.AddCommand(proveCmd)
proveCmd.PersistentFlags().StringVar(&fProofPath, "proof", "", "specifies full path for proof -- default is ./[circuit].proof")
proveCmd.PersistentFlags().StringVar(&fPkPath, "pk", "", "specifies full path for proving key")
proveCmd.PersistentFlags().StringVar(&fInputPath, "input", "", "specifies full path for input file")
proveCmd.PersistentFlags().UintVar(&fCount, "count", 1, "specifies number of times the prover algorithm is ran (benchmarking purposes)")
_ = proveCmd.MarkPersistentFlagRequired("pk")
_ = proveCmd.MarkPersistentFlagRequired("input")
}
func cmdProve(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println("missing circuit path -- gnark prove -h for help")
os.Exit(-1)
}
circuitPath := filepath.Clean(args[0])
circuitName := filepath.Base(circuitPath)
circuitExt := filepath.Ext(circuitName)
circuitName = circuitName[0 : len(circuitName)-len(circuitExt)]
// ensure pk and input flags are set and valid
if fPkPath == "" {
fmt.Println("please specify proving key path")
_ = cmd.Usage()
os.Exit(-1)
}
if fInputPath == "" {
fmt.Println("please specify input file path")
_ = cmd.Usage()
os.Exit(-1)
}
fPkPath = filepath.Clean(fPkPath)
if !fileExists(fPkPath) {
fmt.Println(fPkPath, errNotFound)
os.Exit(-1)
}
fInputPath = filepath.Clean(fInputPath)
if !fileExists(fInputPath) {
fmt.Println(fInputPath, errNotFound)
os.Exit(-1)
}
// load circuit
if !fileExists(circuitPath) {
fmt.Println("error:", errNotFound)
os.Exit(-1)
}
// check curve ID
curveID, err := gob.PeekCurveID(circuitPath)
if err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
// TODO clean that up with interfaces and type casts
var bigIntR1cs frontend.R1CS
switch curveID {
case gurvy.BLS377:
if err := gob.Read(circuitPath, &bigIntR1cs, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
r1cs := backend_bls377.Cast(&bigIntR1cs)
fmt.Printf("%-30s %-30s %-d constraints\n", "loaded circuit", circuitPath, r1cs.NbConstraints)
// run setup
var pk groth16_bls377.ProvingKey
if err := gob.Read(fPkPath, &pk, curveID); err != nil {
fmt.Println("can't load proving key")
fmt.Println(err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s\n", "loaded proving key", fPkPath)
// parse input file
r1csInput := backend.NewAssignment()
err = r1csInput.ReadFile(fInputPath)
if err != nil {
fmt.Println("can't parse input", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-d inputs\n", "loaded input", fInputPath, len(r1csInput))
// compute proof
start := time.Now()
proof, err := groth16_bls377.Prove(&r1cs, &pk, r1csInput)
if err != nil {
fmt.Println("Error proof generation", err)
os.Exit(-1)
}
for i := uint(1); i < fCount; i++ {
_, _ = groth16_bls377.Prove(&r1cs, &pk, r1csInput)
}
duration := time.Since(start)
if fCount > 1 {
duration = time.Duration(int64(duration) / int64(fCount))
}
// default proof path
proofPath := filepath.Join(".", circuitName+".proof")
if fProofPath != "" {
proofPath = fProofPath
}
if err := gob.Write(proofPath, proof, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-30s\n", "generated proof", proofPath, duration)
case gurvy.BLS381:
if err := gob.Read(circuitPath, &bigIntR1cs, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
r1cs := backend_bls381.Cast(&bigIntR1cs)
fmt.Printf("%-30s %-30s %-d constraints\n", "loaded circuit", circuitPath, r1cs.NbConstraints)
// run setup
var pk groth16_bls381.ProvingKey
if err := gob.Read(fPkPath, &pk, curveID); err != nil {
fmt.Println("can't load proving key")
fmt.Println(err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s\n", "loaded proving key", fPkPath)
// parse input file
r1csInput := backend.NewAssignment()
err = r1csInput.ReadFile(fInputPath)
if err != nil {
fmt.Println("can't parse input", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-d inputs\n", "loaded input", fInputPath, len(r1csInput))
// compute proof
start := time.Now()
proof, err := groth16_bls381.Prove(&r1cs, &pk, r1csInput)
if err != nil {
fmt.Println("Error proof generation", err)
os.Exit(-1)
}
for i := uint(1); i < fCount; i++ {
_, _ = groth16_bls381.Prove(&r1cs, &pk, r1csInput)
}
duration := time.Since(start)
if fCount > 1 {
duration = time.Duration(int64(duration) / int64(fCount))
}
// default proof path
proofPath := filepath.Join(".", circuitName+".proof")
if fProofPath != "" {
proofPath = fProofPath
}
if err := gob.Write(proofPath, proof, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-30s\n", "generated proof", proofPath, duration)
case gurvy.BN256:
if err := gob.Read(circuitPath, &bigIntR1cs, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
r1cs := backend_bn256.Cast(&bigIntR1cs)
fmt.Printf("%-30s %-30s %-d constraints\n", "loaded circuit", circuitPath, r1cs.NbConstraints)
// run setup
var pk groth16_bn256.ProvingKey
if err := gob.Read(fPkPath, &pk, curveID); err != nil {
fmt.Println("can't load proving key")
fmt.Println(err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s\n", "loaded proving key", fPkPath)
// parse input file
r1csInput := backend.NewAssignment()
err = r1csInput.ReadFile(fInputPath)
if err != nil {
fmt.Println("can't parse input", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-d inputs\n", "loaded input", fInputPath, len(r1csInput))
// compute proof
start := time.Now()
proof, err := groth16_bn256.Prove(&r1cs, &pk, r1csInput)
if err != nil {
fmt.Println("Error proof generation", err)
os.Exit(-1)
}
for i := uint(1); i < fCount; i++ {
_, _ = groth16_bn256.Prove(&r1cs, &pk, r1csInput)
}
duration := time.Since(start)
if fCount > 1 {
duration = time.Duration(int64(duration) / int64(fCount))
}
// default proof path
proofPath := filepath.Join(".", circuitName+".proof")
if fProofPath != "" {
proofPath = fProofPath
}
if err := gob.Write(proofPath, proof, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-30s\n", "generated proof", proofPath, duration)
default:
fmt.Println("error:", errUnknownCurve)
os.Exit(-1)
}
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bufio"
"bytes"
"encoding/csv"
"errors"
"encoding/hex"
"encoding/json"
"github.com/consensys/gnark/backend"
"strings"
"fmt"
"io"
"github.com/spf13/cobra"
"os"
"path/filepath"
)
// verifyCmd represents the verify command
var readCmd = &cobra.Command{
Use: "read [file] --flags",
Short: "read a file and show to hex string",
Run: cmdRead,
Version: Version,
}
var (
fType int32
)
func init() {
rootCmd.AddCommand(readCmd)
readCmd.PersistentFlags().Int32VarP(&fType, "type", "t", 0, "0: proof or vk file, 1: input file, default 0")
}
func cmdRead(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println("missing read file path -- gnark read -h for help")
os.Exit(-1)
}
filePath := filepath.Clean(args[0])
if fType == 1 {
readInput2(filePath)
return
}
readProof(filePath)
}
func readProof(file string) {
// open file
f, err := os.Open(file)
if err != nil {
fmt.Println("err", err)
}
defer f.Close()
var buff bytes.Buffer
buff.ReadFrom(f)
fmt.Println("proof", hex.EncodeToString(buff.Bytes()))
}
func readInput2(fInputPath string) {
// parse input file
csvFile, err := os.Open(fInputPath)
if err != nil {
fmt.Println("open", err)
return
}
defer csvFile.Close()
toRead, err := readPublic(csvFile)
if err != nil {
fmt.Println("read", err)
return
}
fmt.Println("json code =", toRead)
}
func readPublic(r io.Reader) (string, error) {
toRead := make(map[string]interface{})
reader := csv.NewReader(bufio.NewReader(r))
for {
line, err := reader.Read()
if err == io.EOF {
break
} else if err != nil {
return "", err
} else if len(line) != 3 {
return "", errors.New("ErrInvalidInputFormat")
}
visibility := strings.ToLower(strings.TrimSpace(line[0]))
name := strings.TrimSpace(line[1])
value := strings.TrimSpace(line[2])
if backend.Visibility(visibility) == backend.Public {
if strings.HasPrefix(value, "0x") {
bytes, err := hex.DecodeString(value[2:])
if err != nil {
return "", err
}
toRead[name] = bytes
}
toRead[name] = value
}
}
//marshal 可以被unmarshal 和json.decode同时解析
out, err := json.Marshal(toRead)
if err != nil {
return "", err
}
return hex.EncodeToString(out), nil
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "gnark",
Short: "gnark is a framework to execute (and verify) algorithms in zero-knowledge",
Version: Version,
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if Version == "" {
fmt.Println("/!\\ running gnark in DEV mode /!\\")
}
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
cobra.OnInitialize(initConfig)
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
// config file business, if needed.
}
func fileExists(filePath string) bool {
fInfo, err := os.Stat(filePath)
return !os.IsNotExist(err) && !fInfo.IsDir()
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"os"
"path/filepath"
"time"
backend_bls377 "github.com/consensys/gnark/backend/bls377"
groth16_bls377 "github.com/consensys/gnark/backend/bls377/groth16"
backend_bls381 "github.com/consensys/gnark/backend/bls381"
groth16_bls381 "github.com/consensys/gnark/backend/bls381/groth16"
backend_bn256 "github.com/consensys/gnark/backend/bn256"
groth16_bn256 "github.com/consensys/gnark/backend/bn256/groth16"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gurvy"
"github.com/spf13/cobra"
)
// setupCmd represents the setup command
var setupCmd = &cobra.Command{
Use: "setup [circuit.r1cs]",
Short: "outputs proving and verifying keys for a given circuit",
Run: cmdSetup,
Version: Version,
}
var (
fVkPath, fPkPath string
)
func init() {
rootCmd.AddCommand(setupCmd)
setupCmd.PersistentFlags().StringVar(&fVkPath, "vk", "", "specifies full path for verifying key -- default is ./[circuit].vk")
setupCmd.PersistentFlags().StringVar(&fPkPath, "pk", "", "specifies full path for proving key -- default is ./[circuit].pk")
}
func cmdSetup(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println("missing circuit path -- gnark setup -h for help")
os.Exit(-1)
}
circuitPath := filepath.Clean(args[0])
circuitName := filepath.Base(circuitPath)
circuitExt := filepath.Ext(circuitName)
circuitName = circuitName[0 : len(circuitName)-len(circuitExt)]
vkPath := filepath.Join(".", circuitName+".vk")
pkPath := filepath.Join(".", circuitName+".pk")
if fVkPath != "" {
vkPath = fVkPath
}
if fPkPath != "" {
pkPath = fPkPath
}
// load circuit
if !fileExists(circuitPath) {
fmt.Println("error:", errNotFound)
os.Exit(-1)
}
// check curve ID (TODO is curve.ID necessary now? Because the circuits are serialized with big.Int, here the curve.ID is "unknown")
curveID, err := gob.PeekCurveID(circuitPath)
fmt.Println("test-----" + curveID.String())
if err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
// TODO clean that up with interfaces and type casts
var bigIntR1cs frontend.R1CS
switch curveID {
case gurvy.BLS377:
if err := gob.Read(circuitPath, &bigIntR1cs, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
r1cs := backend_bls377.Cast(&bigIntR1cs)
fmt.Printf("%-30s %-30s %-d constraints\n", "loaded circuit", circuitPath, r1cs.NbConstraints)
// run setup
var pk groth16_bls377.ProvingKey
var vk groth16_bls377.VerifyingKey
start := time.Now()
groth16_bls377.Setup(&r1cs, &pk, &vk)
duration := time.Since(start)
fmt.Printf("%-30s %-30s %-30s\n", "setup completed", "", duration)
if err := gob.Write(vkPath, &vk, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %s\n", "generated verifying key", vkPath)
if err := gob.Write(pkPath, &pk, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %s\n", "generated proving key", pkPath)
case gurvy.BLS381:
if err := gob.Read(circuitPath, &bigIntR1cs, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
r1cs := backend_bls381.Cast(&bigIntR1cs)
fmt.Printf("%-30s %-30s %-d constraints\n", "loaded circuit", circuitPath, r1cs.NbConstraints)
// run setup
var pk groth16_bls381.ProvingKey
var vk groth16_bls381.VerifyingKey
start := time.Now()
groth16_bls381.Setup(&r1cs, &pk, &vk)
duration := time.Since(start)
fmt.Printf("%-30s %-30s %-30s\n", "setup completed", "", duration)
if err := gob.Write(vkPath, &vk, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %s\n", "generated verifying key", vkPath)
if err := gob.Write(pkPath, &pk, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %s\n", "generated proving key", pkPath)
case gurvy.BN256:
if err := gob.Read(circuitPath, &bigIntR1cs, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
r1cs := backend_bn256.Cast(&bigIntR1cs)
fmt.Printf("%-30s %-30s %-d constraints\n", "loaded circuit", circuitPath, r1cs.NbConstraints)
// run setup
var pk groth16_bn256.ProvingKey
var vk groth16_bn256.VerifyingKey
start := time.Now()
groth16_bn256.Setup(&r1cs, &pk, &vk)
duration := time.Since(start)
fmt.Printf("%-30s %-30s %-30s\n", "setup completed", "", duration)
if err := gob.Write(vkPath, &vk, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %s\n", "generated verifying key", vkPath)
if err := gob.Write(pkPath, &pk, curveID); err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
fmt.Printf("%-30s %s\n", "generated proving key", pkPath)
default:
fmt.Println("error:", errUnknownCurve)
os.Exit(-1)
}
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/consensys/gnark/backend"
groth16_bls377 "github.com/consensys/gnark/backend/bls377/groth16"
groth16_bls381 "github.com/consensys/gnark/backend/bls381/groth16"
groth16_bn256 "github.com/consensys/gnark/backend/bn256/groth16"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gurvy"
"github.com/spf13/cobra"
)
// verifyCmd represents the verify command
var verifyCmd = &cobra.Command{
Use: "verify [proof]",
Short: "verifies a proof against a verifying key and a partial / public solution",
Run: cmdVerify,
Version: Version,
}
func init() {
rootCmd.AddCommand(verifyCmd)
verifyCmd.PersistentFlags().StringVar(&fVkPath, "vk", "", "specifies full path for verifying key")
verifyCmd.PersistentFlags().StringVar(&fInputPath, "input", "", "specifies full path for input file")
_ = verifyCmd.MarkPersistentFlagRequired("vk")
_ = verifyCmd.MarkPersistentFlagRequired("input")
}
func cmdVerify(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Println("missing proof path -- gnark verify -h for help")
os.Exit(-1)
}
proofPath := filepath.Clean(args[0])
// ensure vk and input flags are set and valid
if fVkPath == "" {
fmt.Println("please specify verifying key path")
_ = cmd.Usage()
os.Exit(-1)
}
if fInputPath == "" {
fmt.Println("please specify input file path")
_ = cmd.Usage()
os.Exit(-1)
}
fVkPath = filepath.Clean(fVkPath)
if !fileExists(fVkPath) {
fmt.Println(fVkPath, errNotFound)
os.Exit(-1)
}
fInputPath = filepath.Clean(fInputPath)
if !fileExists(fInputPath) {
fmt.Println(fInputPath, errNotFound)
os.Exit(-1)
}
// parse verifying key
if !fileExists(fVkPath) {
fmt.Println("error:", errNotFound)
os.Exit(-1)
}
// check curve ID
curveID, err := gob.PeekCurveID(fVkPath)
if err != nil {
fmt.Println("error:", err)
os.Exit(-1)
}
// TODO clean that up with interfaces and type casts
switch curveID {
case gurvy.BLS377:
var vk groth16_bls377.VerifyingKey
if err := gob.Read(fVkPath, &vk, curveID); err != nil {
fmt.Println("can't load verifying key")
fmt.Println(err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s\n", "loaded verifying key", fVkPath)
// parse input file
r1csInput := backend.NewAssignment()
err := r1csInput.ReadFile(fInputPath)
if err != nil {
fmt.Println("can't parse input", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-d inputs\n", "loaded input", fInputPath, len(r1csInput))
// load proof
var proof groth16_bls377.Proof
if err := gob.Read(proofPath, &proof, curveID); err != nil {
fmt.Println("can't parse proof", err)
os.Exit(-1)
}
// verify proof
start := time.Now()
result, err := groth16_bls377.Verify(&proof, &vk, r1csInput)
if err != nil || !result {
fmt.Printf("%-30s %-30s %-30s\n", "proof is invalid", proofPath, time.Since(start))
if err != nil {
fmt.Println(err)
}
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-30s\n", "proof is valid", proofPath, time.Since(start))
case gurvy.BLS381:
var vk groth16_bls381.VerifyingKey
if err := gob.Read(fVkPath, &vk, curveID); err != nil {
fmt.Println("can't load verifying key")
fmt.Println(err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s\n", "loaded verifying key", fVkPath)
// parse input file
r1csInput := backend.NewAssignment()
err := r1csInput.ReadFile(fInputPath)
if err != nil {
fmt.Println("can't parse input", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-d inputs\n", "loaded input", fInputPath, len(r1csInput))
// load proof
var proof groth16_bls381.Proof
if err := gob.Read(proofPath, &proof, curveID); err != nil {
fmt.Println("can't parse proof", err)
os.Exit(-1)
}
// verify proof
start := time.Now()
result, err := groth16_bls381.Verify(&proof, &vk, r1csInput)
if err != nil || !result {
fmt.Printf("%-30s %-30s %-30s\n", "proof is invalid", proofPath, time.Since(start))
if err != nil {
fmt.Println(err)
}
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-30s\n", "proof is valid", proofPath, time.Since(start))
case gurvy.BN256:
var vk groth16_bn256.VerifyingKey
if err := gob.Read(fVkPath, &vk, curveID); err != nil {
fmt.Println("can't load verifying key")
fmt.Println(err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s\n", "loaded verifying key", fVkPath)
// parse input file
r1csInput := backend.NewAssignment()
err := r1csInput.ReadFile(fInputPath)
if err != nil {
fmt.Println("can't parse input", err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-d inputs\n", "loaded input", fInputPath, len(r1csInput))
// load proof
var proof groth16_bn256.Proof
if err := gob.Read(proofPath, &proof, curveID); err != nil {
fmt.Println("can't parse proof", err)
os.Exit(-1)
}
// verify proof
start := time.Now()
result, err := groth16_bn256.Verify(&proof, &vk, r1csInput)
if err != nil || !result {
fmt.Printf("%-30s %-30s %-30s\n", "proof is invalid", proofPath, time.Since(start))
if err != nil {
fmt.Println(err)
}
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-30s\n", "proof is valid", proofPath, time.Since(start))
default:
fmt.Println("error:", errUnknownCurve)
os.Exit(-1)
}
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"os"
"time"
"github.com/consensys/gnark/backend"
groth16_bn256 "github.com/consensys/gnark/backend/bn256/groth16"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gurvy"
"github.com/spf13/cobra"
)
// verifyCmd represents the verify command
var verifyInputCmd = &cobra.Command{
Use: "verifystr",
Short: "verifies a proof against a verifying key and a partial / public solution",
Run: cmdVerifyStr,
Version: Version,
}
var (
fProofStr, fInputStr, fVerifyStr string
)
func init() {
rootCmd.AddCommand(verifyInputCmd)
verifyInputCmd.PersistentFlags().StringVar(&fVerifyStr, "vk", "", "specifies full path for verifying key")
verifyInputCmd.PersistentFlags().StringVar(&fInputStr, "input", "", "specifies full path for input file")
verifyInputCmd.PersistentFlags().StringVar(&fProofStr, "proof", "", "specifies full path for input file")
_ = verifyInputCmd.MarkPersistentFlagRequired("vk")
_ = verifyInputCmd.MarkPersistentFlagRequired("input")
_ = verifyInputCmd.MarkPersistentFlagRequired("proof")
}
func cmdVerifyStr(cmd *cobra.Command, args []string) {
curveID := gurvy.BN256
//verify key
var buffVk bytes.Buffer
res, err := hex.DecodeString(fVerifyStr)
if err != nil {
log.Fatal(err)
}
buffVk.Write(res)
var vk groth16_bn256.VerifyingKey
if err := gob.Deserialize(&buffVk, &vk, curveID); err != nil {
fmt.Println("can't load verifying key")
fmt.Println(err)
os.Exit(-1)
}
fmt.Printf("%-30s %-30s\n", "loaded verifying key", fVkPath)
//public input
rst, err := deserializeInput(fInputStr)
if err != nil {
log.Fatal(err)
}
r1csInput := backend.NewAssignment()
for k, v := range rst {
r1csInput.Assign(backend.Public, k, v)
}
// load proof
var proof groth16_bn256.Proof
var buffProof bytes.Buffer
res, err = hex.DecodeString(fProofStr)
if err != nil {
log.Fatal(err)
}
buffProof.Write(res)
if err := gob.Deserialize(&buffProof, &proof, curveID); err != nil {
fmt.Println("can't parse proof", err)
os.Exit(-1)
}
// verify proof
start := time.Now()
result, err := groth16_bn256.Verify(&proof, &vk, r1csInput)
if err != nil || !result {
fmt.Printf("%-30s %-30s %-30s\n", "proof is invalid", "proofPath", time.Since(start))
if err != nil {
fmt.Println(err)
}
os.Exit(-1)
}
fmt.Printf("%-30s %-30s %-30s\n", "proof is valid", "proofPath", time.Since(start))
}
func deserializeInput(input string) (map[string]interface{}, error) {
var buffInput bytes.Buffer
res, err := hex.DecodeString(input)
if err != nil {
log.Fatal(err)
}
buffInput.Write(res)
decoder := json.NewDecoder(&buffInput)
toRead := make(map[string]interface{})
if err := decoder.Decode(&toRead); err != nil {
return nil, err
}
return toRead, nil
}
// Copyright 2020 ConsenSys AG
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by gnark/internal/generators/version DO NOT EDIT
package cmd
const Version = "v0.2.0-alpha"
package cmd
import (
"os/exec"
"strings"
"testing"
)
func TestVersionIsGenerated(t *testing.T) {
// goal of this test is to ensure version.go contains up to date Version string
// that is: if a new SemVer tag is pushed, go generate should run to re-generate version.go
v, err := exec.Command("git", "describe", "--abbrev=0").CombinedOutput()
if err != nil {
panic(err)
}
version := strings.TrimSpace(string(v))
if version != Version {
t.Fatal("version was not generated, need to run go generate ./... at root of repo", "got", Version, "expected", version)
}
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package gnark is a framework to execute (and verify) algorithms in zero-knowledge
package main
import "github.com/33cn/plugin/plugin/dapp/mix/cmd/gnark/cmd"
func main() {
cmd.Execute()
}
This diff is collapsed.
......@@ -5,8 +5,7 @@
package executor
import (
"encoding/hex"
"encoding/json"
"github.com/consensys/gnark/frontend"
"github.com/33cn/chain33/types"
......@@ -15,54 +14,36 @@ import (
"github.com/pkg/errors"
)
func (a *action) authParamCheck(exec, symbol string, input *mixTy.AuthorizePublicInput) error {
func (a *action) authParamCheck(exec, symbol string, input *mixTy.AuthorizeCircuit) error {
//check tree rootHash exist
exist, err := checkTreeRootHashExist(a.db, exec, symbol, mixTy.Str2Byte(input.TreeRootHash))
treeRootHash := frontend.FromInterface(frontend.GetAssignedValue(input.TreeRootHash))
exist, err := checkTreeRootHashExist(a.db, exec, symbol, mixTy.Str2Byte(treeRootHash.String()))
if err != nil {
return errors.Wrapf(err, "roothash=%s not found,exec=%s,symbol=%s", input.TreeRootHash, exec, symbol)
return errors.Wrapf(err, "roothash=%s not found,exec=%s,symbol=%s", treeRootHash.String(), exec, symbol)
}
if !exist {
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", input.TreeRootHash)
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", treeRootHash.String())
}
//authorize key should not exist
authKey := calcAuthorizeHashKey(input.AuthorizeHash)
authHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeHash))
authKey := calcAuthorizeHashKey(authHash.String())
_, err = a.db.Get(authKey)
if err == nil {
return errors.Wrapf(mixTy.ErrAuthorizeHashExist, "auth=%s", input.AuthorizeHash)
return errors.Wrapf(mixTy.ErrAuthorizeHashExist, "auth=%s", authHash.String())
}
if !isNotFound(err) {
return errors.Wrapf(err, "get auth=%s", input.AuthorizeHash)
return errors.Wrapf(err, "get auth=%s", authHash.String())
}
//authPubKeys, err := a.getAuthKeys()
//if err != nil {
// return errors.Wrap(err, "get AuthPubkey")
//}
//
////authorize pubkey hash should be configured already
//var found bool
//for _, k := range authPubKeys.Keys {
// if input.AuthorizePubKey == k {
// found = true
// break
// }
//}
//if !found {
// return errors.Wrapf(types.ErrNotFound, "authPubkey=%s", input.AuthorizePubKey)
//}
return nil
}
func (a *action) authorizeVerify(exec, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.AuthorizePublicInput, error) {
var input mixTy.AuthorizePublicInput
data, err := hex.DecodeString(proof.PublicInput)
func (a *action) authorizePubInputs(exec, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.AuthorizeCircuit, error) {
var input mixTy.AuthorizeCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return nil, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
err = json.Unmarshal(data, &input)
if err != nil {
return nil, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput)
return nil, errors.Wrapf(err, "setCircuitPubInput")
}
err = a.authParamCheck(exec, symbol, &input)
......@@ -70,12 +51,6 @@ func (a *action) authorizeVerify(exec, symbol string, proof *mixTy.ZkProofInfo)
return nil, err
}
//zk-proof校验
err = zkProofVerify(a.db, proof, mixTy.VerifyType_AUTHORIZE)
if err != nil {
return nil, err
}
return &input, nil
}
......@@ -88,26 +63,27 @@ func (a *action) authorizeVerify(exec, symbol string, proof *mixTy.ZkProofInfo)
5. set authorize hash and authorize_spend hash
*/
func (a *action) Authorize(authorize *mixTy.MixAuthorizeAction) (*types.Receipt, error) {
var inputs []*mixTy.AuthorizePublicInput
execer, symbol := mixTy.GetAssetExecSymbol(a.api.GetConfig(), authorize.AssetExec, authorize.AssetSymbol)
in, err := a.authorizeVerify(execer, symbol, authorize.Proof)
input, err := a.authorizePubInputs(execer, symbol, authorize.ProofInfo)
if err != nil {
return nil, err
}
inputs = append(inputs, in)
receipt := &types.Receipt{Ty: types.ExecOk}
var auths, authSpends []string
for _, in := range inputs {
r := makeReceipt(calcAuthorizeHashKey(in.AuthorizeHash), mixTy.TyLogAuthorizeSet, &mixTy.ExistValue{Nullifier: in.AuthorizeHash, Exist: true})
mergeReceipt(receipt, r)
r = makeReceipt(calcAuthorizeSpendHashKey(in.AuthorizeSpendHash), mixTy.TyLogAuthorizeSpendSet, &mixTy.ExistValue{Nullifier: in.AuthorizeSpendHash, Exist: true})
mergeReceipt(receipt, r)
auths = append(auths, in.AuthorizeHash)
authSpends = append(authSpends, in.AuthorizeSpendHash)
//zk-proof校验
err = zkProofVerify(a.db, authorize.ProofInfo, mixTy.VerifyType_AUTHORIZE)
if err != nil {
return nil, err
}
receipt := &types.Receipt{Ty: types.ExecOk}
authNullHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeHash))
r := makeReceipt(calcAuthorizeHashKey(authNullHash.String()), mixTy.TyLogAuthorizeSet, &mixTy.ExistValue{Nullifier: authNullHash.String(), Exist: true})
mergeReceipt(receipt, r)
authSpendHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeSpendHash))
r = makeReceipt(calcAuthorizeSpendHashKey(authSpendHash.String()), mixTy.TyLogAuthorizeSpendSet, &mixTy.ExistValue{Nullifier: authSpendHash.String(), Exist: true})
mergeReceipt(receipt, r)
return receipt, nil
}
......@@ -12,7 +12,7 @@ import (
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/mix/executor/merkletree"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark/crypto/hash/mimc/bn256"
"github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
)
......@@ -95,7 +95,7 @@ func getArchiveRoots(db dbm.KV, exec, symbol string, seq uint64) (*mixTy.CommitT
//TODO seed config
func getNewTree() *merkletree.Tree {
return merkletree.New(bn256.NewMiMC("seed"))
return merkletree.New(mimc.NewMiMC("seed"))
}
func calcTreeRoot(leaves *mixTy.CommitTreeLeaves) []byte {
......
......@@ -7,24 +7,25 @@ package executor
import (
"testing"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/stretchr/testify/assert"
)
/*
leaf0 = "16308793397024662832064523892418908145900866571524124093537199035808550255649"
hexstr 240e732fc90c3a88a11f3f60bbbe412f6b4b56d007cf34fdb2500195071c7c21
hash 4010939160279929375357088561050093294975728828994381439611270589357856115894
leaf1 = 21467822781369104390668289189963532506973289112396605437823854946060028754354
leaf hash 17799daf83d82530d70343bc44578bdabafcb134332d4949883695a1ec9d1ba9
leaf hash 19846868408490658463513283235031798083935100648624648285566873440653365397815
leaf2= 4178471437305290899835614805415999986197321812505352791035422725360758750328
leaf hash 29ded1ba9ed45d829f458ce511e013a8d11058db9d6f03fea14267082087b151
leaf hash 4062509694129705639089082212179777344962624935939361647381392834235969534831
leaf3= 10407830929890509544473717262275616077696950294748419792758056545898949331744
leaf hash 1b757026b07fd17150c5d23081bddd52e77dc26b0c7c46b4e0150ca7ccfed35a
leaf hash 3656010751855274388516368747583374746848682779395325737100877017850943546836
leaf4= 11032604436245646157001636966356016502073301224837385665550497706958264582086
leaf hash 24a8d61af8e16abaf9ccb1051c882799121c6ece1094655b5b93f837aead2f30
leaf hash 5949485921924623528448830799540295699445001672535082168235329176256394356669
merkleroot= 6988991286454436061784929049510388415076132311642532433013500389938249229356
0 proof str= 21467822781369104390668289189963532506973289112396605437823854946060028754354
......@@ -44,25 +45,25 @@ func TestGetProveData(t *testing.T) {
proves := []string{
"21467822781369104390668289189963532506973289112396605437823854946060028754354",
"12096317366724227951683802305909172775715878134489527031786909074403605889217",
"14541527209424185878803689752018034974129079647509824805270353433359922459228",
"16581570556767364549626991605903512613557832602774591000372759906303762837296",
"4010939160279929375357088561050093294975728828994381439611270589357856115894",
"19203142125680456902129919467753534834062383756119332074615431762320316227830",
"5949485921924623528448830799540295699445001672535082168235329176256394356669",
}
var leave [][]byte
for _, l := range leaves {
leave = append(leave, transferFr2Bytes(l))
leave = append(leave, mixTy.Str2Byte(l))
}
ret, err := getProveData(leave[1], leave)
assert.Nil(t, err)
assert.Equal(t, uint32(5), ret.NumLeaves)
assert.Equal(t, uint32(1), ret.ProofIndex)
assert.Equal(t, "6988991286454436061784929049510388415076132311642532433013500389938249229356", ret.RootHash)
assert.Equal(t, "12154966389094759868987627011400429400046999538507894392248611367616715657246", ret.RootHash)
assert.Equal(t, len(proves), len(ret.ProofSet))
for i, k := range proves {
assert.Equal(t, k, ret.ProofSet[i])
}
assert.Equal(t, "0,1,1", ret.Helpers)
assert.Equal(t, []uint32([]uint32{0, 1, 1}), ret.Helpers)
}
......@@ -45,7 +45,7 @@ func (a *action) Config(config *mixTy.MixConfigAction) (*types.Receipt, error) {
}
case mixTy.MixConfigType_Payment:
//个人配置,个人负责,可重配
return a.ConfigPaymentPubKey(config.GetPaymentKey())
return a.ConfigPaymentPubKey(config.GetNoteAccountKey())
}
return nil, errors.Wrapf(types.ErrNotFound, "ty=%d", config.Ty)
......@@ -157,7 +157,7 @@ func (a *action) ConfigDeleteAuthPubKey(key string) (*types.Receipt, error) {
return makeConfigAuthKeyReceipt(&newKeys), nil
}
func makeConfigPaymentKeyReceipt(data *mixTy.PaymentKey) *types.Receipt {
func makeConfigPaymentKeyReceipt(data *mixTy.NoteAccountKey) *types.Receipt {
key := calcReceivingKey(data.Addr)
return &types.Receipt{
Ty: types.ExecOk,
......@@ -171,13 +171,13 @@ func makeConfigPaymentKeyReceipt(data *mixTy.PaymentKey) *types.Receipt {
}
func GetPaymentPubKey(db dbm.KV, addr string) (*mixTy.PaymentKey, error) {
func GetPaymentPubKey(db dbm.KV, addr string) (*mixTy.NoteAccountKey, error) {
key := calcReceivingKey(addr)
v, err := db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db")
}
var keys mixTy.PaymentKey
var keys mixTy.NoteAccountKey
err = types.Decode(v, &keys)
if err != nil {
return nil, errors.Wrapf(err, "decode db key")
......@@ -186,8 +186,8 @@ func GetPaymentPubKey(db dbm.KV, addr string) (*mixTy.PaymentKey, error) {
return &keys, nil
}
func (a *action) ConfigPaymentPubKey(paykey *mixTy.PaymentKey) (*types.Receipt, error) {
if paykey == nil || len(paykey.ReceiverKey) == 0 || len(paykey.EncryptKey) == 0 || len(paykey.Addr) == 0 {
func (a *action) ConfigPaymentPubKey(paykey *mixTy.NoteAccountKey) (*types.Receipt, error) {
if paykey == nil || len(paykey.NoteReceiveAddr) == 0 || len(paykey.SecretReceiveKey) == 0 || len(paykey.Addr) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "pubkey=%v", paykey)
}
//检查用户使用对应的addr的key,但不能确保key就是对应addr
......@@ -195,9 +195,9 @@ func (a *action) ConfigPaymentPubKey(paykey *mixTy.PaymentKey) (*types.Receipt,
return nil, errors.Wrapf(types.ErrInvalidParam, "register addr=%s not match with sign=%s", paykey.Addr, a.fromaddr)
}
//直接覆盖
return makeConfigPaymentKeyReceipt(&mixTy.PaymentKey{
Addr: a.fromaddr,
ReceiverKey: paykey.ReceiverKey,
EncryptKey: paykey.EncryptKey}), nil
return makeConfigPaymentKeyReceipt(&mixTy.NoteAccountKey{
Addr: a.fromaddr,
NoteReceiveAddr: paykey.NoteReceiveAddr,
SecretReceiveKey: paykey.SecretReceiveKey}), nil
}
......@@ -5,15 +5,10 @@
package executor
import (
"encoding/hex"
"encoding/json"
"strconv"
"github.com/33cn/chain33/common/address"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/mix/executor/zksnark"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark/frontend"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
......@@ -24,55 +19,20 @@ func makeNullifierSetReceipt(hash string, data proto.Message) *types.Receipt {
}
func zkProofVerify(db dbm.KV, proof *mixTy.ZkProofInfo, ty mixTy.VerifyType) error {
keys, err := getVerifyKeys(db, int32(ty))
if err != nil {
return err
}
var pass bool
for _, verifyKey := range keys.Data {
ok, err := zksnark.Verify(verifyKey.Value, proof.Proof, proof.PublicInput)
if err != nil {
return err
}
if !ok {
continue
}
pass = true
break
}
if !pass {
return errors.Wrap(mixTy.ErrZkVerifyFail, "verify")
}
return nil
}
func (a *action) depositVerify(proof *mixTy.ZkProofInfo) (*mixTy.DepositCircuit, error) {
var input mixTy.DepositCircuit
func (a *action) depositVerify(proof *mixTy.ZkProofInfo) (string, uint64, error) {
var input mixTy.DepositPublicInput
data, err := hex.DecodeString(proof.PublicInput)
if err != nil {
return "", 0, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
err = json.Unmarshal(data, &input)
if err != nil {
return "", 0, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput)
}
val, err := strconv.ParseUint(input.Amount, 10, 64)
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return "", 0, errors.Wrapf(err, "parseUint=%s", input.Amount)
}
if val <= 0 {
return "", 0, errors.Wrapf(err, "amount=%d should >0", val)
return nil, errors.Wrapf(err, "setCircuitPubInput")
}
err = zkProofVerify(a.db, proof, mixTy.VerifyType_DEPOSIT)
if err != nil {
return "", 0, err
return nil, errors.Wrapf(err, "verify fail for input=%s", proof.PublicInput)
}
return input.NoteHash, val, nil
return &input, nil
}
......@@ -87,12 +47,14 @@ func (a *action) Deposit(deposit *mixTy.MixDepositAction) (*types.Receipt, error
var sum uint64
//1. zk-proof校验
for _, p := range deposit.Proofs {
noteHash, amount, err := a.depositVerify(p)
input, err := a.depositVerify(p)
if err != nil {
return nil, errors.Wrapf(err, "verify fail for input=%s", p.PublicInput)
return nil, errors.Wrap(err, "get pub input")
}
sum += amount
notes = append(notes, noteHash)
v := frontend.FromInterface(frontend.GetAssignedValue(input.Amount))
sum += v.Uint64()
noteHash := frontend.FromInterface(frontend.GetAssignedValue(input.NoteHash))
notes = append(notes, noteHash.String())
}
//存款
......
......@@ -3,7 +3,6 @@
package merkletree
import (
"encoding/hex"
"errors"
"fmt"
"hash"
......@@ -198,7 +197,7 @@ func (t *Tree) Push(data []byte) {
t.head.sum = data
} else {
t.head.sum = leafSum(t.hash, data)
fmt.Println("leaf hash", hex.EncodeToString(t.head.sum))
//fmt.Println("leaf hash", mixTy.Byte2Str(t.head.sum))
}
// Join subTrees if possible.
......
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package merkletree
import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc"
)
func TestLeafHash(t *testing.T) {
leaves := []string{
"16308793397024662832064523892418908145900866571524124093537199035808550255649",
}
h := mimc.NewMiMC("seed")
s := leafSum(h, mixTy.Str2Byte(leaves[0]))
assert.Equal(t, "4010939160279929375357088561050093294975728828994381439611270589357856115894", mixTy.Byte2Str(s))
leaves = []string{
"4062509694129705639089082212179777344962624935939361647381392834235969534831",
"3656010751855274388516368747583374746848682779395325737100877017850943546836",
}
h.Reset()
s = nodeSum(h, mixTy.Str2Byte(leaves[0]), mixTy.Str2Byte(leaves[1]))
assert.Equal(t, "19203142125680456902129919467753534834062383756119332074615431762320316227830", mixTy.Byte2Str(s))
proves := []string{
"21467822781369104390668289189963532506973289112396605437823854946060028754354",
"4010939160279929375357088561050093294975728828994381439611270589357856115894",
"19203142125680456902129919467753534834062383756119332074615431762320316227830",
"5949485921924623528448830799540295699445001672535082168235329176256394356669",
}
var sum []byte
for i, l := range proves {
if len(sum) == 0 {
sum = leafSum(h, mixTy.Str2Byte(l))
continue
}
//第0个leaf在第一个leaf的右侧,需要调整顺序
if i < 2 {
sum = nodeSum(h, mixTy.Str2Byte(l), sum)
continue
}
sum = nodeSum(h, sum, mixTy.Str2Byte(l))
}
fmt.Println("sum", mixTy.Byte2Str(sum))
}
......@@ -5,14 +5,13 @@
package executor
import (
"encoding/hex"
"encoding/json"
"github.com/consensys/gnark/frontend"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gurvy/bn256/twistededwards"
"github.com/consensys/gnark-crypto/ecc/bn254/twistededwards"
dbm "github.com/33cn/chain33/common/db"
"github.com/pkg/errors"
......@@ -23,18 +22,17 @@ import (
2. check if exist in authorize pool and nullifier pool
*/
func transferInputVerify(db dbm.KV, execer, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.TransferInputPublicInput, error) {
var input mixTy.TransferInputPublicInput
data, err := hex.DecodeString(proof.PublicInput)
func transferInput(db dbm.KV, execer, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.TransferInputCircuit, error) {
var input mixTy.TransferInputCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return nil, errors.Wrapf(err, "transferInput verify decode string=%s", proof.PublicInput)
}
err = json.Unmarshal(data, &input)
if err != nil {
return nil, errors.Wrapf(err, "transferInput verify unmarshal string=%s", proof.PublicInput)
return nil, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
err = spendVerify(db, execer, symbol, input.TreeRootHash, input.NullifierHash, input.AuthorizeSpendHash)
treeRootHash := frontend.FromInterface(frontend.GetAssignedValue(input.TreeRootHash))
nullifierHash := frontend.FromInterface(frontend.GetAssignedValue(input.NullifierHash))
authSpendHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeSpendHash))
err = spendVerify(db, execer, symbol, treeRootHash.String(), nullifierHash.String(), authSpendHash.String())
if err != nil {
return nil, errors.Wrap(err, "transferInput verify spendVerify")
}
......@@ -53,17 +51,12 @@ func transferInputVerify(db dbm.KV, execer, symbol string, proof *mixTy.ZkProofI
2. check if exist in authorize pool and nullifier pool
*/
func transferOutputVerify(db dbm.KV, proof *mixTy.ZkProofInfo) (*mixTy.TransferOutputPublicInput, error) {
var input mixTy.TransferOutputPublicInput
data, err := hex.DecodeString(proof.PublicInput)
if err != nil {
return nil, errors.Wrapf(err, "Output verify decode string=%s", proof.PublicInput)
}
err = json.Unmarshal(data, &input)
func transferOutputVerify(db dbm.KV, proof *mixTy.ZkProofInfo) (*mixTy.TransferOutputCircuit, error) {
var input mixTy.TransferOutputCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return nil, errors.Wrapf(err, "Output verify unmarshal string=%s", proof.PublicInput)
return nil, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
err = zkProofVerify(db, proof, mixTy.VerifyType_TRANSFEROUTPUT)
if err != nil {
return nil, errors.Wrap(err, "Output verify proof verify")
......@@ -73,19 +66,19 @@ func transferOutputVerify(db dbm.KV, proof *mixTy.ZkProofInfo) (*mixTy.TransferO
}
func VerifyCommitValues(inputs []*mixTy.TransferInputPublicInput, outputs []*mixTy.TransferOutputPublicInput, txFee uint64) bool {
var inputPoints, outputPoints []*twistededwards.Point
func VerifyCommitValues(inputs []*mixTy.TransferInputCircuit, outputs []*mixTy.TransferOutputCircuit, txFee uint64) bool {
var inputPoints, outputPoints []*twistededwards.PointAffine
for _, in := range inputs {
var p twistededwards.Point
p.X.SetString(in.ShieldAmountX)
p.Y.SetString(in.ShieldAmountY)
var p twistededwards.PointAffine
p.X.SetInterface(frontend.GetAssignedValue(in.ShieldAmountX))
p.Y.SetInterface(frontend.GetAssignedValue(in.ShieldAmountY))
inputPoints = append(inputPoints, &p)
}
for _, out := range outputs {
var p twistededwards.Point
p.X.SetString(out.ShieldAmountX)
p.Y.SetString(out.ShieldAmountY)
var p twistededwards.PointAffine
p.X.SetInterface(frontend.GetAssignedValue(out.ShieldAmountX))
p.Y.SetInterface(frontend.GetAssignedValue(out.ShieldAmountY))
outputPoints = append(outputPoints, &p)
}
//out value add fee
......@@ -109,19 +102,20 @@ func VerifyCommitValues(inputs []*mixTy.TransferInputPublicInput, outputs []*mix
return false
}
func MixTransferInfoVerify(cfg *types.Chain33Config, db dbm.KV, transfer *mixTy.MixTransferAction) ([]*mixTy.TransferInputPublicInput, []*mixTy.TransferOutputPublicInput, error) {
var inputs []*mixTy.TransferInputPublicInput
var outputs []*mixTy.TransferOutputPublicInput
func MixTransferInfoVerify(cfg *types.Chain33Config, db dbm.KV, transfer *mixTy.MixTransferAction) ([]*mixTy.TransferInputCircuit, []*mixTy.TransferOutputCircuit, error) {
var inputs []*mixTy.TransferInputCircuit
var outputs []*mixTy.TransferOutputCircuit
execer, symbol := mixTy.GetAssetExecSymbol(cfg, transfer.AssetExec, transfer.AssetSymbol)
txFee := mixTy.GetTransferTxFee(cfg, execer)
//inputs
for _, i := range transfer.Inputs {
in, err := transferInputVerify(db, execer, symbol, i)
in, err := transferInput(db, execer, symbol, i)
if err != nil {
return nil, nil, err
}
inputs = append(inputs, in)
}
//output
......@@ -196,14 +190,16 @@ func (a *action) Transfer(transfer *mixTy.MixTransferAction) (*types.Receipt, er
mergeReceipt(receipt, rTxFee)
for _, k := range inputs {
r := makeNullifierSetReceipt(k.NullifierHash, &mixTy.ExistValue{Nullifier: k.NullifierHash, Exist: true})
nullHash := frontend.FromInterface(frontend.GetAssignedValue(k.NullifierHash))
r := makeNullifierSetReceipt(nullHash.String(), &mixTy.ExistValue{Nullifier: nullHash.String(), Exist: true})
mergeReceipt(receipt, r)
}
//push new commit to merkle tree
var leaves [][]byte
for _, h := range outputs {
leaves = append(leaves, mixTy.Str2Byte(h.NoteHash))
noteHash := frontend.FromInterface(frontend.GetAssignedValue(h.NoteHash))
leaves = append(leaves, mixTy.Str2Byte(noteHash.String()))
}
conf := types.ConfSub(a.api.GetConfig(), mixTy.MixX)
......
......@@ -5,130 +5,112 @@
package executor
import (
"math/big"
"testing"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gurvy/bn256/fr"
bn256 "github.com/consensys/gurvy/bn256/twistededwards"
"github.com/consensys/gnark-crypto/ecc/bn254/twistededwards"
"github.com/stretchr/testify/assert"
)
const (
baseHX = "10190477835300927557649934238820360529458681672073866116232821892325659279502"
baseHY = "7969140283216448215269095418467361784159407896899334866715345504515077887397"
baseHX = "9252662952969393856711468743327022054484546162727338092576697495684140272191"
baseHY = "8220002160263982499510761441032261960817037857915665984040705585999508400744"
fee = 100000
)
func TestVerifyCommitValuesBasePoint(t *testing.T) {
var in44, out10, out34, rIn100, rOut40, rOut60 fr.Element
var in44, out10, out34 big.Int
//calc p1=44*G+100*G, p2=10*G+30*G,p3=34*G+70*G, p1=p2+p3+fee
in44.SetUint64(4400000).FromMont()
out10.SetUint64(1000000).FromMont()
out34.SetUint64(3400000 - fee).FromMont()
rIn100.SetUint64(10000000).FromMont()
rOut40.SetUint64(3000000).FromMont()
rOut60.SetUint64(7000000).FromMont()
ed := bn256.GetEdwardsCurve()
var p1, p2, p3, r1, r2, r3 bn256.Point
p1.ScalarMul(&ed.Base, in44)
p2.ScalarMul(&ed.Base, out10)
p3.ScalarMul(&ed.Base, out34)
r1.ScalarMul(&ed.Base, rIn100)
r2.ScalarMul(&ed.Base, rOut40)
r3.ScalarMul(&ed.Base, rOut60)
//p1.Add(&p1,&r1)
//p2.Add(&p2,&r2)
//p3.Add(&p3,&r3)
t.Log("p1.x", p1.X.String())
t.Log("p1.y", p1.Y.String())
t.Log("p2.x", p2.X.String())
t.Log("p2.y", p2.Y.String())
t.Log("p3.x", p3.X.String())
t.Log("p3.y", p3.Y.String())
input1 := &mixTy.TransferInputPublicInput{
ShieldAmountX: p1.X.String(),
ShieldAmountY: p1.Y.String(),
}
var inputs []*mixTy.TransferInputPublicInput
inputs = append(inputs, input1)
output1 := &mixTy.TransferOutputPublicInput{
ShieldAmountX: p2.X.String(),
ShieldAmountY: p2.Y.String(),
}
output2 := &mixTy.TransferOutputPublicInput{
ShieldAmountX: p3.X.String(),
ShieldAmountY: p3.Y.String(),
}
var outputs []*mixTy.TransferOutputPublicInput
outputs = append(outputs, output1)
outputs = append(outputs, output2)
ret := VerifyCommitValues(inputs, outputs)
in44.SetUint64(4400000)
out10.SetUint64(1000000)
out34.SetUint64(3400000 - fee)
ed := twistededwards.GetEdwardsCurve()
var p1, p2, p3 twistededwards.PointAffine
p1.ScalarMul(&ed.Base, &in44)
p2.ScalarMul(&ed.Base, &out10)
p3.ScalarMul(&ed.Base, &out34)
//t.Log("p1.x", p1.X.String())
//t.Log("p1.y", p1.Y.String())
//t.Log("p2.x", p2.X.String())
//t.Log("p2.y", p2.Y.String())
//t.Log("p3.x", p3.X.String())
//t.Log("p3.y", p3.Y.String())
var input1 mixTy.TransferInputCircuit
input1.ShieldAmountX.Assign(p1.X.String())
input1.ShieldAmountY.Assign(p1.Y.String())
var inputs []*mixTy.TransferInputCircuit
inputs = append(inputs, &input1)
var output1, output2 mixTy.TransferOutputCircuit
output1.ShieldAmountX.Assign(p2.X.String())
output1.ShieldAmountY.Assign(p2.Y.String())
output2.ShieldAmountX.Assign(p3.X.String())
output2.ShieldAmountY.Assign(p3.Y.String())
var outputs []*mixTy.TransferOutputCircuit
outputs = append(outputs, &output1)
outputs = append(outputs, &output2)
ret := VerifyCommitValues(inputs, outputs, fee)
assert.Equal(t, true, ret)
}
func TestVerifyCommitValuesBaseAddHPoint(t *testing.T) {
var in44, out10, out34 fr.Element
in44.SetUint64(4400000).FromMont()
out10.SetUint64(1000000).FromMont()
out34.SetUint64(3400000 - fee).FromMont()
var in44, out10, out34 big.Int
in44.SetUint64(4400000)
out10.SetUint64(1000000)
out34.SetUint64(3400000 - fee)
//random value
var rIn100, rOut40, rOut60 fr.Element
rIn100.SetUint64(10000000).FromMont()
rOut40.SetUint64(3000000).FromMont()
rOut60.SetUint64(7000000).FromMont()
var rIn100, rOut40, rOut60 big.Int
rIn100.SetUint64(10000000)
rOut40.SetUint64(3000000)
rOut60.SetUint64(7000000)
var baseH bn256.Point
var baseH twistededwards.PointAffine
baseH.X.SetString(baseHX)
baseH.Y.SetString(baseHY)
ed := bn256.GetEdwardsCurve()
var p1, p2, p3, r1, r2, r3 bn256.Point
p1.ScalarMul(&ed.Base, in44)
p2.ScalarMul(&ed.Base, out10)
p3.ScalarMul(&ed.Base, out34)
r1.ScalarMul(&baseH, rIn100)
r2.ScalarMul(&baseH, rOut40)
r3.ScalarMul(&baseH, rOut60)
ed := twistededwards.GetEdwardsCurve()
var p1, p2, p3, r1, r2, r3 twistededwards.PointAffine
p1.ScalarMul(&ed.Base, &in44)
p2.ScalarMul(&ed.Base, &out10)
p3.ScalarMul(&ed.Base, &out34)
r1.ScalarMul(&baseH, &rIn100)
r2.ScalarMul(&baseH, &rOut40)
r3.ScalarMul(&baseH, &rOut60)
p1.Add(&p1, &r1)
p2.Add(&p2, &r2)
p3.Add(&p3, &r3)
input1 := &mixTy.TransferInputPublicInput{
ShieldAmountX: p1.X.String(),
ShieldAmountY: p1.Y.String(),
}
var input1 mixTy.TransferInputCircuit
input1.ShieldAmountX.Assign(p1.X.String())
input1.ShieldAmountY.Assign(p1.Y.String())
var inputs []*mixTy.TransferInputPublicInput
inputs = append(inputs, input1)
var inputs []*mixTy.TransferInputCircuit
inputs = append(inputs, &input1)
output1 := &mixTy.TransferOutputPublicInput{
ShieldAmountX: p2.X.String(),
ShieldAmountY: p2.Y.String(),
}
var output1, output2 mixTy.TransferOutputCircuit
output1.ShieldAmountX.Assign(p2.X.String())
output1.ShieldAmountY.Assign(p2.Y.String())
output2 := &mixTy.TransferOutputPublicInput{
ShieldAmountX: p3.X.String(),
ShieldAmountY: p3.Y.String(),
}
output2.ShieldAmountX.Assign(p3.X.String())
output2.ShieldAmountY.Assign(p3.Y.String())
var outputs []*mixTy.TransferOutputPublicInput
outputs = append(outputs, output1)
outputs = append(outputs, output2)
var outputs []*mixTy.TransferOutputCircuit
outputs = append(outputs, &output1)
outputs = append(outputs, &output2)
ret := VerifyCommitValues(inputs, outputs)
ret := VerifyCommitValues(inputs, outputs, fee)
assert.Equal(t, true, ret)
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package executor
import (
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/plugin/plugin/dapp/mix/executor/zksnark"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
func zkProofVerify(db dbm.KV, proof *mixTy.ZkProofInfo, ty mixTy.VerifyType) error {
keys, err := getVerifyKeys(db, int32(ty))
if err != nil {
return err
}
var pass bool
for _, verifyKey := range keys.Data {
ok, err := zksnark.Verify(verifyKey.Value, proof.Proof, proof.PublicInput)
if err != nil {
return err
}
if !ok {
continue
}
pass = true
break
}
if !pass {
return errors.Wrap(mixTy.ErrZkVerifyFail, "verify")
}
return nil
}
......@@ -5,14 +5,11 @@
package executor
import (
"encoding/hex"
"encoding/json"
"strconv"
"github.com/33cn/chain33/common/address"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark/frontend"
"github.com/pkg/errors"
)
......@@ -50,32 +47,28 @@ func spendVerify(db dbm.KV, exec, symbol string, treeRootHash, nulliferHash, aut
}
func (a *action) withdrawVerify(exec, symbol string, proof *mixTy.ZkProofInfo) (string, uint64, error) {
var input mixTy.WithdrawPublicInput
data, err := hex.DecodeString(proof.PublicInput)
if err != nil {
return "", 0, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
err = json.Unmarshal(data, &input)
if err != nil {
return "", 0, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput)
}
val, err := strconv.ParseUint(input.Amount, 10, 64)
func (a *action) withdrawVerify(exec, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.WithdrawCircuit, error) {
var input mixTy.WithdrawCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return "", 0, errors.Wrapf(err, "parseUint=%s", input.Amount)
return nil, errors.Wrapf(err, "setCircuitPubInput")
}
err = spendVerify(a.db, exec, symbol, input.TreeRootHash, input.NullifierHash, input.AuthorizeSpendHash)
treeRootHash := frontend.FromInterface(frontend.GetAssignedValue(input.TreeRootHash))
nullifierHash := frontend.FromInterface(frontend.GetAssignedValue(input.NullifierHash))
authSpendHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeSpendHash))
err = spendVerify(a.db, exec, symbol, treeRootHash.String(), nullifierHash.String(), authSpendHash.String())
if err != nil {
return "", 0, err
return nil, err
}
err = zkProofVerify(a.db, proof, mixTy.VerifyType_WITHDRAW)
if err != nil {
return "", 0, err
return nil, err
}
return input.NullifierHash, val, nil
return &input, nil
}
......@@ -90,12 +83,14 @@ func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, er
var nulliferSet []string
var sumValue uint64
for _, k := range withdraw.Proofs {
nulfier, v, err := a.withdrawVerify(exec, symbol, k)
input, err := a.withdrawVerify(exec, symbol, k)
if err != nil {
return nil, err
}
sumValue += v
nulliferSet = append(nulliferSet, nulfier)
v := frontend.FromInterface(frontend.GetAssignedValue(input.Amount))
sumValue += v.Uint64()
nullHash := frontend.FromInterface(frontend.GetAssignedValue(input.NullifierHash))
nulliferSet = append(nulliferSet, nullHash.String())
}
if sumValue != withdraw.Amount {
......
......@@ -18,11 +18,8 @@ package zksnark
import (
"encoding/json"
"github.com/consensys/gnark/backend"
groth16_bn256 "github.com/consensys/gnark/backend/bn256/groth16"
"github.com/consensys/gnark/encoding/gob"
"github.com/consensys/gurvy"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend/groth16"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
......@@ -44,42 +41,78 @@ func deserializeInput(input string) (map[string]interface{}, error) {
}
func Verify(verifyKeyStr, proofStr, pubInputStr string) (bool, error) {
curveID := gurvy.BN256
output, err := mixTy.GetByteBuff(verifyKeyStr)
vkBuf, err := mixTy.GetByteBuff(verifyKeyStr)
if err != nil {
return false, errors.Wrapf(err, "zkVerify.GetByteBuff")
return false, errors.Wrapf(err, "zkVerify.vk.GetByteBuff")
}
var vk groth16_bn256.VerifyingKey
if err := gob.Deserialize(output, &vk, curveID); err != nil {
return false, errors.Wrapf(err, "zkVerify.Deserize.VK=%s", verifyKeyStr[:10])
vk := groth16.NewVerifyingKey(ecc.BN254)
if _, err := vk.ReadFrom(vkBuf); err != nil {
return false, errors.Wrapf(err, "zkVerify.read.vk=%s", verifyKeyStr[:10])
}
// parse input file
assigns, err := deserializeInput(pubInputStr)
// load proof
proofBuf, err := mixTy.GetByteBuff(proofStr)
if err != nil {
return false, err
return false, errors.Wrapf(err, "zkVerify.get.proof")
}
r1csInput := backend.NewAssignment()
for k, v := range assigns {
r1csInput.Assign(backend.Public, k, v)
proof := groth16.NewProof(ecc.BN254)
if _, err = proof.ReadFrom(proofBuf); err != nil {
return false, errors.Wrapf(err, "zkVerify.read.proof=%s", proofStr[:10])
}
// load proof
output, err = mixTy.GetByteBuff(proofStr)
// decode pub input hex string
pubBuf, err := mixTy.GetByteBuff(pubInputStr)
if err != nil {
return false, errors.Wrapf(err, "zkVerify.proof")
}
var proof groth16_bn256.Proof
if err := gob.Deserialize(output, &proof, curveID); err != nil {
return false, errors.Wrapf(err, "zkVerify.deserial.proof=%s", proofStr[:10])
return false, errors.Wrapf(err, "zkVerify.pub.GetByteBuff")
}
// verify proof
//start := time.Now()
result, err := groth16_bn256.Verify(&proof, &vk, r1csInput)
err = groth16.ReadAndVerify(proof, vk, pubBuf)
if err != nil {
return false, errors.Wrapf(err, "zkVerify.verify")
}
return result, nil
return true, nil
}
//
//func Verify(verifyKeyStr, proofStr, pubInputStr string) (bool, error) {
// curveID := gurvy.BN256
//
// output, err := mixTy.GetByteBuff(verifyKeyStr)
// if err != nil {
// return false, errors.Wrapf(err, "zkVerify.GetByteBuff")
// }
// var vk groth16_bn256.VerifyingKey
// if err := gob.Deserialize(output, &vk, curveID); err != nil {
// return false, errors.Wrapf(err, "zkVerify.Deserize.VK=%s", verifyKeyStr[:10])
// }
//
// // parse input file
// assigns, err := deserializeInput(pubInputStr)
// if err != nil {
// return false, err
// }
// r1csInput := backend.NewAssignment()
// for k, v := range assigns {
// r1csInput.Assign(backend.Public, k, v)
// }
//
// // load proof
// output, err = mixTy.GetByteBuff(proofStr)
// if err != nil {
// return false, errors.Wrapf(err, "zkVerify.proof")
// }
// var proof groth16_bn256.Proof
// if err := gob.Deserialize(output, &proof, curveID); err != nil {
// return false, errors.Wrapf(err, "zkVerify.deserial.proof=%s", proofStr[:10])
// }
//
// // verify proof
// //start := time.Now()
// result, err := groth16_bn256.Verify(&proof, &vk, r1csInput)
// if err != nil {
// return false, errors.Wrapf(err, "zkVerify.verify")
// }
// return result, nil
//}
syntax = "proto3";
import "common.proto";
import "transaction.proto";
package types;
option go_package = "../types";
import "common.proto";
import "transaction.proto";
//区分不同的验证电路
enum VerifyType{
DEPOSIT = 0;
WITHDRAW = 1;
TRANSFERINPUT = 2;
TRANSFEROUTPUT = 3;
TRANSFERINPUT = 2;
TRANSFEROUTPUT = 3;
AUTHORIZE = 4;
}
message ZkVerifyKey {
VerifyType type = 1;
string value = 2;
string value = 2;
}
......@@ -30,15 +31,18 @@ message AuthKeys{
repeated string keys = 1;
}
message PaymentKey{
string addr = 1;
string receiverKey = 2;
string encryptKey = 3;
message NoteAccountKey{
//链上地址
string addr = 1;
//支票收款地址
string noteReceiveAddr = 2;
//note秘密信息接收key
string secretReceiveKey = 3;
}
message TokenTxFeeAddrReq{
string assetExec = 1;
string assetSymbol = 2;
string assetExec = 1;
string assetSymbol = 2;
}
enum MixConfigType{
......@@ -65,14 +69,14 @@ message MixConfigAction {
oneof value {
ZkVerifyKey verifyKey = 3;
string authKey = 4;
PaymentKey paymentKey = 5;
NoteAccountKey noteAccountKey = 5;
}
}
//DH one time pubkey with secret
message DHSecret{
string peerKey = 1;
string oneTimePubKey = 1;
string secret = 2;
}
......@@ -115,9 +119,9 @@ message MixWithdrawAction {
}
message MixAuthorizeAction {
string assetExec = 1;
string assetSymbol = 2;
ZkProofInfo proof = 3;
string assetExec = 1;
string assetSymbol = 2;
ZkProofInfo proofInfo = 3;
}
......@@ -135,44 +139,6 @@ message MixAction {
}
message DepositPublicInput {
string noteHash = 1;
string amount = 2;
}
message WithdrawPublicInput {
string treeRootHash = 1;
string nullifierHash = 2;
string authorizeSpendHash = 3;
string amount = 4;
}
message TransferInputPublicInput {
string treeRootHash = 1;
string shieldAmountX = 2;
string shieldAmountY = 3;
string authorizeSpendHash = 4;
string nullifierHash = 5;
}
message TransferOutputPublicInput {
string noteHash = 1;
string shieldAmountX = 2;
string shieldAmountY = 3;
}
message AuthorizePublicInput {
string treeRootHash = 1;
string authorizePubKey = 2;
string authorizeHash = 3;
string authorizeSpendHash = 4;
}
message VerifyProofInfo{
VerifyType ty = 1;
......@@ -384,17 +350,23 @@ message AuthTxReq{
message TransferInputTxReq{
string noteHashs = 1;
string zkPath = 2;
}
message TransferOutputTxReq{
DepositInfo deposit = 1;
string zkPath = 2;
}
message TransferTxReq{
TransferInputTxReq input = 1;
TransferOutputTxReq output = 2;
string zkPath = 3;
}
message CreateZkKeyFileReq{
int32 ty = 1;
string savePath = 2;
}
//加密了的input/output amount
......@@ -416,13 +388,13 @@ message ShieldAmountRst{
}
message CreateRawTxReq{
int32 actionTy = 1;
bytes data = 4;
string assetExec = 2;
string assetSymbol = 3;
string title = 6; //平行链名字
int32 privacy = 7; //1:打印隐私数据
int32 verify = 8; //0:链上验证,1:本地验证
int32 actionTy = 1;
bytes data = 4;
string assetExec = 2;
string assetSymbol = 3;
string title = 6; //平行链名字
string zkProof = 7; //输入证明内容,方便测试,空:读pk文件产生proof
bool verifyOnChain = 8; //true:链上验证,false:本地验证
}
......
......@@ -139,3 +139,12 @@ func (c *Jrpc) CreateRawTransaction(in *mixTy.CreateRawTxReq, result *interface{
*result = hex.EncodeToString(types.Encode(reply))
return err
}
func (c *Jrpc) CreateZkKeyFile(in *mixTy.CreateZkKeyFileReq, result *interface{}) error {
reply, err := c.cli.ExecWalletFunc(mixTy.MixX, "CreateZkKeyFile", in)
if err != nil {
return err
}
*result, err = types.PBToJSON(reply)
return err
}
package types
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/hash/mimc"
)
type AuthorizeCircuit struct {
TreeRootHash frontend.Variable `gnark:",public"`
AuthorizeHash frontend.Variable `gnark:",public"`
AuthorizeSpendHash frontend.Variable `gnark:",public"`
Amount frontend.Variable
ReceiverPubKey frontend.Variable
ReturnPubKey frontend.Variable
AuthorizePubKey frontend.Variable
AuthorizePriKey frontend.Variable
SpendFlag frontend.Variable
NoteRandom frontend.Variable
NoteHash frontend.Variable
//tree path info
Path0 frontend.Variable
Path1 frontend.Variable
Path2 frontend.Variable
Path3 frontend.Variable
Path4 frontend.Variable
Path5 frontend.Variable
Path6 frontend.Variable
Path7 frontend.Variable
Path8 frontend.Variable
Path9 frontend.Variable
Helper0 frontend.Variable
Helper1 frontend.Variable
Helper2 frontend.Variable
Helper3 frontend.Variable
Helper4 frontend.Variable
Helper5 frontend.Variable
Helper6 frontend.Variable
Helper7 frontend.Variable
Helper8 frontend.Variable
Helper9 frontend.Variable
Valid0 frontend.Variable
Valid1 frontend.Variable
Valid2 frontend.Variable
Valid3 frontend.Variable
Valid4 frontend.Variable
Valid5 frontend.Variable
Valid6 frontend.Variable
Valid7 frontend.Variable
Valid8 frontend.Variable
Valid9 frontend.Variable
}
// Define declares the circuit's constraints
func (circuit *AuthorizeCircuit) Define(curveID ecc.ID, cs *frontend.ConstraintSystem) error {
// hash function
h, _ := mimc.NewMiMC("seed", curveID, cs)
mimc := &h
mimc.Write(circuit.AuthorizePriKey)
cs.AssertIsEqual(circuit.AuthorizePubKey, mimc.Sum())
mimc.Reset()
mimc.Write(circuit.AuthorizePubKey, circuit.NoteRandom)
cs.AssertIsEqual(circuit.AuthorizeHash, mimc.Sum())
mimc.Reset()
cs.AssertIsBoolean(circuit.SpendFlag)
targetSpendKey := cs.Select(circuit.SpendFlag, circuit.ReceiverPubKey, circuit.ReturnPubKey)
mimc.Write(targetSpendKey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.AuthorizeSpendHash, mimc.Sum())
mimc.Reset()
mimc.Write(circuit.ReceiverPubKey, circuit.ReturnPubKey, circuit.AuthorizePubKey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.NoteHash, mimc.Sum())
var proofSet, helper, valid []frontend.Variable
proofSet = append(proofSet, circuit.NoteHash)
proofSet = append(proofSet, circuit.Path0)
proofSet = append(proofSet, circuit.Path1)
proofSet = append(proofSet, circuit.Path2)
proofSet = append(proofSet, circuit.Path3)
proofSet = append(proofSet, circuit.Path4)
proofSet = append(proofSet, circuit.Path5)
proofSet = append(proofSet, circuit.Path6)
proofSet = append(proofSet, circuit.Path7)
proofSet = append(proofSet, circuit.Path8)
proofSet = append(proofSet, circuit.Path9)
//helper[0],valid[0]占位, 方便接口只设置有效值
helper = append(helper, cs.Constant("1"))
helper = append(helper, circuit.Helper0)
helper = append(helper, circuit.Helper1)
helper = append(helper, circuit.Helper2)
helper = append(helper, circuit.Helper3)
helper = append(helper, circuit.Helper4)
helper = append(helper, circuit.Helper5)
helper = append(helper, circuit.Helper6)
helper = append(helper, circuit.Helper7)
helper = append(helper, circuit.Helper8)
helper = append(helper, circuit.Helper9)
valid = append(valid, cs.Constant("1"))
valid = append(valid, circuit.Valid0)
valid = append(valid, circuit.Valid1)
valid = append(valid, circuit.Valid2)
valid = append(valid, circuit.Valid3)
valid = append(valid, circuit.Valid4)
valid = append(valid, circuit.Valid5)
valid = append(valid, circuit.Valid6)
valid = append(valid, circuit.Valid7)
valid = append(valid, circuit.Valid8)
valid = append(valid, circuit.Valid9)
VerifyMerkleProof(cs, mimc, circuit.TreeRootHash, proofSet, helper, valid)
return nil
}
package types
import (
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
)
func TestAuthorize(t *testing.T) {
assert := groth16.NewAssert(t)
var authCircuit AuthorizeCircuit
// compiles our circuit into a R1CS
r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &authCircuit)
assert.NoError(err)
{
authCircuit.TreeRootHash.Assign("950328190378475063285997697131233976268556642407874368795731039491163033995")
authCircuit.AuthorizeHash.Assign("12118078255438699776281693699296572905522325280239057706039401491884511470990")
authCircuit.AuthorizeSpendHash.Assign("21866258877426223880121052705448065394371888667902748431050285218933372701264")
authCircuit.ReceiverPubKey.Assign("13496572805321444273664325641440458311310163934354047265362731297880627774936")
authCircuit.ReturnPubKey.Assign("10193030166569398670555398535278072963719579248877156082361830729347727033510")
authCircuit.AuthorizePubKey.Assign("2302306531516619173363925550130201424458047172090558749779153607734711372580")
authCircuit.AuthorizePriKey.Assign("17822967620457187568904804290291537271142779717280482398091401115827760898835")
authCircuit.NoteRandom.Assign("2824204835")
authCircuit.Amount.Assign("28242048")
authCircuit.SpendFlag.Assign("1")
authCircuit.NoteHash.Assign("11183619348394875496624033204802036013086293645689330234403504655205992608466")
authCircuit.Path0.Assign("19561523370160677851616596032513161448778901506614020103852017946679781620105")
authCircuit.Path1.Assign("13898857070666440684265042188056372750257678232709763835292910585848522658637")
authCircuit.Path2.Assign("15019169196974879571470243100379529757970866395477207575033769902587972032431")
authCircuit.Path3.Assign("0")
authCircuit.Path4.Assign("0")
authCircuit.Path5.Assign("0")
authCircuit.Path6.Assign("0")
authCircuit.Path7.Assign("0")
authCircuit.Path8.Assign("0")
authCircuit.Path9.Assign("0")
authCircuit.Helper0.Assign("1")
authCircuit.Helper1.Assign("1")
authCircuit.Helper2.Assign("1")
authCircuit.Helper3.Assign("0")
authCircuit.Helper4.Assign("0")
authCircuit.Helper5.Assign("0")
authCircuit.Helper6.Assign("0")
authCircuit.Helper7.Assign("0")
authCircuit.Helper8.Assign("0")
authCircuit.Helper9.Assign("0")
authCircuit.Valid0.Assign("1")
authCircuit.Valid1.Assign("1")
authCircuit.Valid2.Assign("1")
authCircuit.Valid3.Assign("0")
authCircuit.Valid4.Assign("0")
authCircuit.Valid5.Assign("0")
authCircuit.Valid6.Assign("0")
authCircuit.Valid7.Assign("0")
authCircuit.Valid8.Assign("0")
authCircuit.Valid9.Assign("0")
assert.ProverSucceeded(r1cs, &authCircuit)
}
}
package types
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/hash/mimc"
)
//spend commit hash the circuit implementing
type DepositCircuit struct {
NoteHash frontend.Variable `gnark:",public"`
Amount frontend.Variable `gnark:",public"`
ReceiverPubKey frontend.Variable
ReturnPubKey frontend.Variable
AuthorizePubKey frontend.Variable
NoteRandom frontend.Variable
}
func (circuit *DepositCircuit) Define(curveID ecc.ID, cs *frontend.ConstraintSystem) error {
// hash function
mimc, _ := mimc.NewMiMC("seed", curveID, cs)
mimc.Write(circuit.ReceiverPubKey, circuit.ReturnPubKey, circuit.AuthorizePubKey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.NoteHash, mimc.Sum())
return nil
}
package types
import (
"bytes"
"encoding/hex"
"fmt"
"github.com/consensys/gnark/backend/witness"
"github.com/stretchr/testify/assert"
"reflect"
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
)
//receiver prikey="10190477835300927557649934238820360529458681672073866116232821892325659279502"
//receiver pubkey="13496572805321444273664325641440458311310163934354047265362731297880627774936"
//return prikey="7969140283216448215269095418467361784159407896899334866715345504515077887397"
//return pubkey="10193030166569398670555398535278072963719579248877156082361830729347727033510"
//authorize prikey="17822967620457187568904804290291537271142779717280482398091401115827760898835"
//authorize pubkey="2302306531516619173363925550130201424458047172090558749779153607734711372580"
//spend prikey="10407830929890509544473717262275616077696950294748419792758056545898949331744"
//spend pubkey="3656010751855274388516368747583374746848682779395325737100877017850943546836"
func TestDeposit(t *testing.T) {
assert := groth16.NewAssert(t)
var depositCircuit DepositCircuit
// compiles our circuit into a R1CS
r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &depositCircuit)
assert.NoError(err)
{
//var witness Deposit
depositCircuit.NoteHash.Assign("11183619348394875496624033204802036013086293645689330234403504655205992608466")
depositCircuit.Amount.Assign(28242048)
depositCircuit.ReceiverPubKey.Assign("13496572805321444273664325641440458311310163934354047265362731297880627774936")
depositCircuit.ReturnPubKey.Assign("10193030166569398670555398535278072963719579248877156082361830729347727033510")
depositCircuit.AuthorizePubKey.Assign("2302306531516619173363925550130201424458047172090558749779153607734711372580")
depositCircuit.NoteRandom.Assign(2824204835)
assert.ProverSucceeded(r1cs, &depositCircuit)
}
var pubBuf bytes.Buffer
witness.WritePublicTo(&pubBuf, ecc.BN254, &depositCircuit)
//fmt.Println("buf",hex.EncodeToString(pubBuf.Bytes()))
pubStr := hex.EncodeToString(pubBuf.Bytes())
var buf bytes.Buffer
pk, vk, err := groth16.Setup(r1cs)
assert.Nil(err)
buf.Reset()
vk.WriteTo(&buf)
//fmt.Println("vk",hex.EncodeToString(buf.Bytes()))
vkStr := hex.EncodeToString(buf.Bytes())
proof, err := groth16.Prove(r1cs, pk, &depositCircuit)
assert.Nil(err)
buf.Reset()
proof.WriteTo(&buf)
//fmt.Println("proof",hex.EncodeToString(buf.Bytes()))
pfStr := hex.EncodeToString(buf.Bytes())
d, _ := hex.DecodeString(vkStr)
vkt := groth16.NewVerifyingKey(ecc.BN254)
buf.Reset()
buf.Write(d)
vkt.ReadFrom(&buf)
d, _ = hex.DecodeString(pfStr)
buf.Reset()
buf.Write(d)
prt := groth16.NewProof(ecc.BN254)
prt.ReadFrom(&buf)
d, _ = hex.DecodeString(pubStr)
buf.Reset()
buf.Write(d)
err = groth16.ReadAndVerify(prt, vkt, &buf)
assert.Nil(err)
}
func TestDepositSetVal(t *testing.T) {
pubInput := "0000000218b9b448bd793dab9075f70ce404a87497b3a2d0d0b5d177441d6cada1e9b2d20000000000000000000000000000000000000000000000000000000001aef080"
str, _ := hex.DecodeString(pubInput)
var buf bytes.Buffer
buf.Write(str)
var val Witness
n, err := val.LimitReadFrom(&buf)
assert.Nil(t, err)
fmt.Println("n=", n)
//val=make([]fr.Element,2)
//val[0].SetInterface(0x18b9b448bd793dab9075f70ce404a87497b3a2d0d0b5d177441d6cada1e9b2d2)
//val[0].set
//val[1].SetInterface(0x0000000000000000000000000000000000000000000000000000000001aef080)
fmt.Println("0=", val[0].String(), "1=", val[1].String())
var depositCircuit DepositCircuit
getVal(&depositCircuit, val)
fmt.Println("deposit", frontend.GetAssignedValue(depositCircuit.NoteHash))
fmt.Println("amount", frontend.GetAssignedValue(depositCircuit.Amount))
}
func getVal(input frontend.Circuit, w Witness) {
tValue := reflect.ValueOf(input)
if tValue.Kind() == reflect.Ptr {
tValue = tValue.Elem()
}
//reft := reflect.TypeOf(input)
fmt.Println("fields", tValue.NumField())
for i, v := range w {
field := tValue.Type().Field((i))
fmt.Println("i=", i, "name=", field.Name)
f := tValue.FieldByName(field.Name)
a := f.Addr().Interface().(*frontend.Variable)
//a:=tValue.Field(i).Interface().(frontend.Variable)
a.Assign(v.String())
}
}
......@@ -46,23 +46,18 @@ const (
//circuits default file name
const (
DepositCircuit = "circuit_deposit.r1cs"
DepositPk = "circuit_deposit.pk"
DepositVk = "circuit_deposit.vk"
DepositPk = "circuit_deposit.pk"
DepositVk = "circuit_deposit.vk"
WithdrawCircuit = "circuit_withdraw.r1cs"
WithdrawPk = "circuit_withdraw.pk"
WithdrawVk = "circuit_withdraw.vk"
WithdrawPk = "circuit_withdraw.pk"
WithdrawVk = "circuit_withdraw.vk"
AuthCircuit = "circuit_auth.r1cs"
AuthPk = "circuit_auth.pk"
AuthVk = "circuit_auth.vk"
AuthPk = "circuit_auth.pk"
AuthVk = "circuit_auth.vk"
TransInputCircuit = "circuit_transfer_input.r1cs"
TransInputPk = "circuit_transfer_input.pk"
TransInputVk = "circuit_transfer_input.vk"
TransInputPk = "circuit_transfer_input.pk"
TransInputVk = "circuit_transfer_input.vk"
TransOutputCircuit = "circuit_transfer_output.r1cs"
TransOutputPk = "circuit_transfer_output.pk"
TransOutputVk = "circuit_transfer_output.vk"
TransOutputPk = "circuit_transfer_output.pk"
TransOutputVk = "circuit_transfer_output.vk"
)
This source diff could not be displayed because it is too large. You can view the blob instead.
package types
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/hash/mimc"
)
type TransferInputCircuit struct {
TreeRootHash frontend.Variable `gnark:",public"`
AuthorizeSpendHash frontend.Variable `gnark:",public"`
NullifierHash frontend.Variable `gnark:",public"`
ShieldAmountX frontend.Variable `gnark:",public"`
ShieldAmountY frontend.Variable `gnark:",public"`
//secret
ReceiverPubKey frontend.Variable
ReturnPubKey frontend.Variable
AuthorizePubKey frontend.Variable
NoteRandom frontend.Variable
Amount frontend.Variable
AmountRandom frontend.Variable
SpendPriKey frontend.Variable
SpendFlag frontend.Variable
AuthorizeFlag frontend.Variable
NoteHash frontend.Variable
//tree path info
Path0 frontend.Variable
Path1 frontend.Variable
Path2 frontend.Variable
Path3 frontend.Variable
Path4 frontend.Variable
Path5 frontend.Variable
Path6 frontend.Variable
Path7 frontend.Variable
Path8 frontend.Variable
Path9 frontend.Variable
Helper0 frontend.Variable
Helper1 frontend.Variable
Helper2 frontend.Variable
Helper3 frontend.Variable
Helper4 frontend.Variable
Helper5 frontend.Variable
Helper6 frontend.Variable
Helper7 frontend.Variable
Helper8 frontend.Variable
Helper9 frontend.Variable
Valid0 frontend.Variable
Valid1 frontend.Variable
Valid2 frontend.Variable
Valid3 frontend.Variable
Valid4 frontend.Variable
Valid5 frontend.Variable
Valid6 frontend.Variable
Valid7 frontend.Variable
Valid8 frontend.Variable
Valid9 frontend.Variable
}
// Define declares the circuit's constraints
func (circuit *TransferInputCircuit) Define(curveID ecc.ID, cs *frontend.ConstraintSystem) error {
cs.AssertIsBoolean(circuit.SpendFlag)
cs.AssertIsBoolean(circuit.AuthorizeFlag)
// hash function
h, _ := mimc.NewMiMC("seed", curveID, cs)
mimc := &h
//verify spend private key
targetSpendKey := cs.Select(circuit.SpendFlag, circuit.ReceiverPubKey, circuit.ReturnPubKey)
mimc.Write(circuit.SpendPriKey)
cs.AssertIsEqual(targetSpendKey, mimc.Sum())
nullValue := cs.Constant(0)
mimc.Reset()
mimc.Write(targetSpendKey, circuit.Amount, circuit.NoteRandom)
calcAuthSpendHash := mimc.Sum()
targetAuthSpendHash := cs.Select(circuit.AuthorizeFlag, calcAuthSpendHash, nullValue)
cs.AssertIsEqual(circuit.AuthorizeSpendHash, targetAuthSpendHash)
mimc.Reset()
mimc.Write(circuit.NoteRandom)
cs.AssertIsEqual(circuit.NullifierHash, mimc.Sum())
//
calcReturnPubkey := cs.Select(circuit.AuthorizeFlag, circuit.ReturnPubKey, nullValue)
calcAuthPubkey := cs.Select(circuit.AuthorizeFlag, circuit.AuthorizePubKey, nullValue)
mimc.Reset()
mimc.Write(circuit.ReceiverPubKey, calcReturnPubkey, calcAuthPubkey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.NoteHash, mimc.Sum())
var proofSet, helper, valid []frontend.Variable
proofSet = append(proofSet, circuit.NoteHash)
proofSet = append(proofSet, circuit.Path0)
proofSet = append(proofSet, circuit.Path1)
proofSet = append(proofSet, circuit.Path2)
proofSet = append(proofSet, circuit.Path3)
proofSet = append(proofSet, circuit.Path4)
proofSet = append(proofSet, circuit.Path5)
proofSet = append(proofSet, circuit.Path6)
proofSet = append(proofSet, circuit.Path7)
proofSet = append(proofSet, circuit.Path8)
proofSet = append(proofSet, circuit.Path9)
//helper[0],valid[0]占位, 方便接口只设置有效值
helper = append(helper, cs.Constant("1"))
helper = append(helper, circuit.Helper0)
helper = append(helper, circuit.Helper1)
helper = append(helper, circuit.Helper2)
helper = append(helper, circuit.Helper3)
helper = append(helper, circuit.Helper4)
helper = append(helper, circuit.Helper5)
helper = append(helper, circuit.Helper6)
helper = append(helper, circuit.Helper7)
helper = append(helper, circuit.Helper8)
helper = append(helper, circuit.Helper9)
valid = append(valid, cs.Constant("1"))
valid = append(valid, circuit.Valid0)
valid = append(valid, circuit.Valid1)
valid = append(valid, circuit.Valid2)
valid = append(valid, circuit.Valid3)
valid = append(valid, circuit.Valid4)
valid = append(valid, circuit.Valid5)
valid = append(valid, circuit.Valid6)
valid = append(valid, circuit.Valid7)
valid = append(valid, circuit.Valid8)
valid = append(valid, circuit.Valid9)
CommitValueVerify(cs, circuit.Amount, circuit.AmountRandom, circuit.ShieldAmountX, circuit.ShieldAmountY)
VerifyMerkleProof(cs, mimc, circuit.TreeRootHash, proofSet, helper, valid)
return nil
}
package types
import (
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
)
func TestTransferInputAuth(t *testing.T) {
assert := groth16.NewAssert(t)
var inputCircuit TransferInputCircuit
// compiles our circuit into a R1CS
r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &inputCircuit)
assert.NoError(err)
{
inputCircuit.TreeRootHash.Assign("950328190378475063285997697131233976268556642407874368795731039491163033995")
inputCircuit.AuthorizeSpendHash.Assign("21866258877426223880121052705448065394371888667902748431050285218933372701264")
inputCircuit.NullifierHash.Assign("18261754976334473090934939020486888794395514077667802499672726421629833403191")
inputCircuit.ShieldAmountX.Assign("2999198834503527181782558341022909853195739283744640133924786234819945005771")
inputCircuit.ShieldAmountY.Assign("19443413539487113257436159186910517766382570615508121086985490610335878889881")
inputCircuit.ReceiverPubKey.Assign("13496572805321444273664325641440458311310163934354047265362731297880627774936")
inputCircuit.ReturnPubKey.Assign("10193030166569398670555398535278072963719579248877156082361830729347727033510")
inputCircuit.AuthorizePubKey.Assign("2302306531516619173363925550130201424458047172090558749779153607734711372580")
inputCircuit.NoteRandom.Assign("2824204835")
inputCircuit.Amount.Assign("28242048")
inputCircuit.AmountRandom.Assign("282420481")
inputCircuit.SpendPriKey.Assign("10190477835300927557649934238820360529458681672073866116232821892325659279502")
inputCircuit.SpendFlag.Assign("1")
inputCircuit.AuthorizeFlag.Assign("1")
inputCircuit.NoteHash.Assign("11183619348394875496624033204802036013086293645689330234403504655205992608466")
inputCircuit.Path0.Assign("19561523370160677851616596032513161448778901506614020103852017946679781620105")
inputCircuit.Path1.Assign("13898857070666440684265042188056372750257678232709763835292910585848522658637")
inputCircuit.Path2.Assign("15019169196974879571470243100379529757970866395477207575033769902587972032431")
inputCircuit.Path3.Assign("0")
inputCircuit.Path4.Assign("0")
inputCircuit.Path5.Assign("0")
inputCircuit.Path6.Assign("0")
inputCircuit.Path7.Assign("0")
inputCircuit.Path8.Assign("0")
inputCircuit.Path9.Assign("0")
inputCircuit.Helper0.Assign("1")
inputCircuit.Helper1.Assign("1")
inputCircuit.Helper2.Assign("1")
inputCircuit.Helper3.Assign("0")
inputCircuit.Helper4.Assign("0")
inputCircuit.Helper5.Assign("0")
inputCircuit.Helper6.Assign("0")
inputCircuit.Helper7.Assign("0")
inputCircuit.Helper8.Assign("0")
inputCircuit.Helper9.Assign("0")
inputCircuit.Valid0.Assign("1")
inputCircuit.Valid1.Assign("1")
inputCircuit.Valid2.Assign("1")
inputCircuit.Valid3.Assign("0")
inputCircuit.Valid4.Assign("0")
inputCircuit.Valid5.Assign("0")
inputCircuit.Valid6.Assign("0")
inputCircuit.Valid7.Assign("0")
inputCircuit.Valid8.Assign("0")
inputCircuit.Valid9.Assign("0")
assert.ProverSucceeded(r1cs, &inputCircuit)
}
}
//
//func TestTransferInputReturnKey(t *testing.T) {
//
// assert := groth16.NewAssert(t)
//
// r1cs := NewTransferInput()
// r1csBN256 := backend_bn256.Cast(r1cs)
// {
// good := backend.NewAssignment()
// good.Assign(backend.Public, "treeRootHash", "10531321614990797034921282585661869614556487056951485265320464926630499341310")
// good.Assign(backend.Public, "shieldAmountX", "14087975867275911077371231345227824611951436822132762463787130558957838320348")
// good.Assign(backend.Public, "shieldAmountY", "15113519960384204624879642069520481336224311978035289236693658603675385299879")
// good.Assign(backend.Public, "authorizeSpendHash", "6026163592877030954825395224309219861774131411806846860652261047183070579370")
// good.Assign(backend.Public, "nullifierHash", "6747518781649068310795677405858353007442326529625450860668944156162052335195")
//
// good.Assign(backend.Secret, "amount", "28242048")
// good.Assign(backend.Secret, "amountRandom", "35")
//
// good.Assign(backend.Secret, "receiverPubKey", "13735985067536865723202617343666111332145536963656464451727087263423649028705")
// good.Assign(backend.Secret, "returnPubKey", "16067249407809359746114321133992130903102335882983385972747813693681808870497")
// good.Assign(backend.Secret, "authorizePubKey", "13519883267141251871527102103999205179714486518503885909948192364772977661583")
//
// good.Assign(backend.Secret, "spendPriKey", "7969140283216448215269095418467361784159407896899334866715345504515077887397")
// //returnkey spend notehash
// good.Assign(backend.Secret, "spendFlag", "0")
//
// good.Assign(backend.Secret, "authorizeFlag", "1")
//
// good.Assign(backend.Secret, "noteRandom", "2824204835")
//
// good.Assign(backend.Secret, "noteHash", "16308793397024662832064523892418908145900866571524124093537199035808550255649")
//
// //nodehash="16308793397024662832064523892418908145900866571524124093537199035808550255649"
// good.Assign(backend.Secret, "path1", "19561523370160677851616596032513161448778901506614020103852017946679781620105")
// good.Assign(backend.Secret, "path2", "13898857070666440684265042188056372750257678232709763835292910585848522658637")
// good.Assign(backend.Secret, "path3", "15019169196974879571470243100379529757970866395477207575033769902587972032431")
// good.Assign(backend.Secret, "path4", "0")
// good.Assign(backend.Secret, "path5", "0")
// good.Assign(backend.Secret, "path6", "0")
// good.Assign(backend.Secret, "path7", "0")
// good.Assign(backend.Secret, "path8", "0")
// good.Assign(backend.Secret, "path9", "0")
//
// good.Assign(backend.Secret, "helper1", "1")
// good.Assign(backend.Secret, "helper2", "1")
// good.Assign(backend.Secret, "helper3", "1")
// good.Assign(backend.Secret, "helper4", "0")
// good.Assign(backend.Secret, "helper5", "0")
// good.Assign(backend.Secret, "helper6", "0")
// good.Assign(backend.Secret, "helper7", "0")
// good.Assign(backend.Secret, "helper8", "0")
// good.Assign(backend.Secret, "helper9", "0")
//
// good.Assign(backend.Secret, "valid1", "1")
// good.Assign(backend.Secret, "valid2", "1")
// good.Assign(backend.Secret, "valid3", "1")
// good.Assign(backend.Secret, "valid4", "0")
// good.Assign(backend.Secret, "valid5", "0")
// good.Assign(backend.Secret, "valid6", "0")
// good.Assign(backend.Secret, "valid7", "0")
// good.Assign(backend.Secret, "valid8", "0")
// good.Assign(backend.Secret, "valid9", "0")
//
// assert.Solved(&r1csBN256, good, nil)
// }
//
//}
//
//func TestTransferInputNoAuthorize(t *testing.T) {
//
// assert := groth16.NewAssert(t)
//
// r1cs := NewTransferInput()
// r1csBN256 := backend_bn256.Cast(r1cs)
// {
// good := backend.NewAssignment()
// good.Assign(backend.Public, "treeRootHash", "8924377726623516198388981994706612588174229761660626844219523809311621081152")
// good.Assign(backend.Public, "shieldAmountX", "20026900249169569699397829614948056401416692452575929785554743563301443795984")
// good.Assign(backend.Public, "shieldAmountY", "11443294504840468048882645872852838384649876010412151915870299030068051779303")
// good.Assign(backend.Public, "authorizeSpendHash", "0")
// good.Assign(backend.Public, "nullifierHash", "4493238794492517147695618716694376637191823831910850819304582851540887491471")
//
// good.Assign(backend.Secret, "amount", "500000000")
// good.Assign(backend.Secret, "amountRandom", "103649245823269378598256096359743803233")
//
// good.Assign(backend.Secret, "receiverPubKey", "7244551457692363731356498279463138379576484998878425864678733206990733443457")
// good.Assign(backend.Secret, "returnPubKey", "0")
// good.Assign(backend.Secret, "authorizePubKey", "0")
//
// good.Assign(backend.Secret, "spendPriKey", "19115616183616714814727844928908633989028519974595353009754871398745087846141")
// good.Assign(backend.Secret, "spendFlag", "1")
// //not need authorize
// good.Assign(backend.Secret, "authorizeFlag", "0")
//
// good.Assign(backend.Secret, "noteRandom", "16855817802811010832998322637530013398737002960466904173163094025121554818471")
//
// good.Assign(backend.Secret, "noteHash", "4757455985754753449547885621755931629265767091930770913671501411452663313694")
//
// good.Assign(backend.Secret, "path1", "21609869341494920403470153054548069228540665950349313465330160010270609674984")
// good.Assign(backend.Secret, "path2", "0")
// good.Assign(backend.Secret, "path3", "0")
// good.Assign(backend.Secret, "path4", "0")
// good.Assign(backend.Secret, "path5", "0")
// good.Assign(backend.Secret, "path6", "0")
// good.Assign(backend.Secret, "path7", "0")
// good.Assign(backend.Secret, "path8", "0")
// good.Assign(backend.Secret, "path9", "0")
//
// good.Assign(backend.Secret, "helper1", "0")
// good.Assign(backend.Secret, "helper2", "1")
// good.Assign(backend.Secret, "helper3", "1")
// good.Assign(backend.Secret, "helper4", "0")
// good.Assign(backend.Secret, "helper5", "0")
// good.Assign(backend.Secret, "helper6", "0")
// good.Assign(backend.Secret, "helper7", "0")
// good.Assign(backend.Secret, "helper8", "0")
// good.Assign(backend.Secret, "helper9", "0")
//
// good.Assign(backend.Secret, "valid1", "1")
// good.Assign(backend.Secret, "valid2", "0")
// good.Assign(backend.Secret, "valid3", "0")
// good.Assign(backend.Secret, "valid4", "0")
// good.Assign(backend.Secret, "valid5", "0")
// good.Assign(backend.Secret, "valid6", "0")
// good.Assign(backend.Secret, "valid7", "0")
// good.Assign(backend.Secret, "valid8", "0")
// good.Assign(backend.Secret, "valid9", "0")
//
// assert.Solved(&r1csBN256, good, nil)
// }
//
//}
package types
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/hash/mimc"
)
type TransferOutputCircuit struct {
//public
NoteHash frontend.Variable `gnark:",public"`
ShieldAmountX frontend.Variable `gnark:",public"`
ShieldAmountY frontend.Variable `gnark:",public"`
//secret
ReceiverPubKey frontend.Variable
ReturnPubKey frontend.Variable
AuthorizePubKey frontend.Variable
NoteRandom frontend.Variable
Amount frontend.Variable
AmountRandom frontend.Variable
}
// Define declares the circuit's constraints
func (circuit *TransferOutputCircuit) Define(curveID ecc.ID, cs *frontend.ConstraintSystem) error {
// hash function
h, _ := mimc.NewMiMC("seed", curveID, cs)
mimc := &h
mimc.Write(circuit.ReceiverPubKey, circuit.ReturnPubKey, circuit.AuthorizePubKey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.NoteHash, mimc.Sum())
CommitValueVerify(cs, circuit.Amount, circuit.AmountRandom, circuit.ShieldAmountX, circuit.ShieldAmountY)
return nil
}
package types
import (
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
)
func TestTransferOutput(t *testing.T) {
assert := groth16.NewAssert(t)
var outCircuit TransferOutputCircuit
// compiles our circuit into a R1CS
r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &outCircuit)
assert.NoError(err)
{
outCircuit.NoteHash.Assign("11183619348394875496624033204802036013086293645689330234403504655205992608466")
outCircuit.ShieldAmountX.Assign("2999198834503527181782558341022909853195739283744640133924786234819945005771")
outCircuit.ShieldAmountY.Assign("19443413539487113257436159186910517766382570615508121086985490610335878889881")
outCircuit.ReceiverPubKey.Assign("13496572805321444273664325641440458311310163934354047265362731297880627774936")
outCircuit.ReturnPubKey.Assign("10193030166569398670555398535278072963719579248877156082361830729347727033510")
outCircuit.AuthorizePubKey.Assign("2302306531516619173363925550130201424458047172090558749779153607734711372580")
outCircuit.NoteRandom.Assign("2824204835")
outCircuit.Amount.Assign("28242048")
outCircuit.AmountRandom.Assign("282420481")
assert.ProverSucceeded(r1cs, &outCircuit)
}
}
......@@ -5,19 +5,12 @@
package types
import (
"bytes"
"encoding/hex"
"encoding/json"
"reflect"
"github.com/pkg/errors"
log "github.com/33cn/chain33/common/log/log15"
coins "github.com/33cn/chain33/system/dapp/coins/types"
"github.com/33cn/chain33/types"
token "github.com/33cn/plugin/plugin/dapp/token/types"
"github.com/consensys/gurvy/bn256/fr"
"github.com/consensys/gurvy/bn256/twistededwards"
)
var (
......@@ -78,7 +71,7 @@ func (p *MixType) GetLogMap() map[int64]*types.LogInfo {
TyLogSubRoots: {Ty: reflect.TypeOf(ReceiptCommitSubRoots{}), Name: "LogSubRoots"},
TyLogArchiveRootLeaves: {Ty: reflect.TypeOf(ReceiptArchiveLeaves{}), Name: "LogArchiveRootLeaves"},
TyLogCommitTreeArchiveRoot: {Ty: reflect.TypeOf(ReceiptArchiveTreeRoot{}), Name: "LogCommitTreeArchiveRoot"},
TyLogMixConfigPaymentKey: {Ty: reflect.TypeOf(PaymentKey{}), Name: "LogConfigReceivingKey"},
TyLogMixConfigPaymentKey: {Ty: reflect.TypeOf(NoteAccountKey{}), Name: "LogConfigReceivingKey"},
TyLogNulliferSet: {Ty: reflect.TypeOf(ExistValue{}), Name: "LogNullifierSet"},
}
}
......@@ -99,126 +92,6 @@ func (p *MixType) GetPayload() types.Message {
return &MixAction{}
}
func DecodePubInput(ty VerifyType, input string) (interface{}, error) {
data, err := hex.DecodeString(input)
if err != nil {
return nil, errors.Wrapf(err, "decode string=%s", input)
}
switch ty {
case VerifyType_DEPOSIT:
var v DepositPublicInput
err = json.Unmarshal(data, &v)
if err != nil {
return nil, errors.Wrapf(err, "unmarshal string=%s", input)
}
return &v, nil
case VerifyType_WITHDRAW:
var v WithdrawPublicInput
err = json.Unmarshal(data, &v)
if err != nil {
return nil, errors.Wrapf(err, "unmarshal string=%s", input)
}
return &v, nil
case VerifyType_TRANSFERINPUT:
var v TransferInputPublicInput
err = json.Unmarshal(data, &v)
if err != nil {
return nil, errors.Wrapf(err, "unmarshal string=%s", input)
}
return &v, nil
case VerifyType_TRANSFEROUTPUT:
var v TransferOutputPublicInput
err = json.Unmarshal(data, &v)
if err != nil {
return nil, errors.Wrapf(err, "unmarshal string=%s", input)
}
return &v, nil
case VerifyType_AUTHORIZE:
var v AuthorizePublicInput
err = json.Unmarshal(data, &v)
if err != nil {
return nil, errors.Wrapf(err, "unmarshal string=%s", input)
}
return &v, nil
}
return nil, types.ErrInvalidParam
}
func MulCurvePointG(val interface{}) *twistededwards.Point {
v := fr.FromInterface(val)
var point twistededwards.Point
ed := twistededwards.GetEdwardsCurve()
point.ScalarMul(&ed.Base, *v.FromMont())
return &point
}
func MulCurvePointH(pointHX, pointHY, val string) *twistededwards.Point {
v := fr.FromInterface(val)
var pointV, pointH twistededwards.Point
pointH.X.SetString(pointHX)
pointH.Y.SetString(pointHY)
pointV.ScalarMul(&pointH, *v.FromMont())
return &pointV
}
func GetCurveSum(points ...*twistededwards.Point) *twistededwards.Point {
//Add之前需初始化pointSum,不能空值,不然会等于0
pointSum := twistededwards.NewPoint(points[0].X, points[0].Y)
for _, a := range points[1:] {
pointSum.Add(&pointSum, a)
}
return &pointSum
}
//A=B+C
func CheckSumEqual(points ...*twistededwards.Point) bool {
if len(points) < 2 {
return false
}
//Add之前需初始化pointSum,不能空值,不然会等于0
pointSum := twistededwards.NewPoint(points[1].X, points[1].Y)
for _, a := range points[2:] {
pointSum.Add(&pointSum, a)
}
if pointSum.X.Equal(&points[0].X) && pointSum.Y.Equal(&points[0].Y) {
return true
}
return false
}
func GetByteBuff(input string) (*bytes.Buffer, error) {
var buffInput bytes.Buffer
res, err := hex.DecodeString(input)
if err != nil {
return nil, errors.Wrapf(err, "getByteBuff to %s", input)
}
buffInput.Write(res)
return &buffInput, nil
}
func Str2Byte(v string) []byte {
var fr fr.Element
fr.SetString(v)
return fr.Bytes()
}
func Byte2Str(v []byte) string {
var f fr.Element
f.SetBytes(v)
return f.String()
}
func GetFrRandom() string {
var f fr.Element
return f.SetRandom().String()
}
func GetAssetExecSymbol(cfg *types.Chain33Config, execer, symbol string) (string, string) {
if symbol == "" {
return coins.CoinsX, cfg.GetCoinSymbol()
......
package types
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestMulCurvePointG(t *testing.T) {
p := MulCurvePointG(3300000)
assert.Equal(t, "16340309671848023141603674621476146712179749929747125480153351030768864391631", p.X.String())
assert.Equal(t, "7282133334630698770430559968655675427988723121976895210725923327624387185615", p.Y.String())
}
package types
import (
"bytes"
"encoding/binary"
"encoding/hex"
"github.com/consensys/gnark-crypto/ecc"
bn254 "github.com/consensys/gnark-crypto/ecc/bn254/twistededwards"
"github.com/consensys/gnark/frontend"
"github.com/pkg/errors"
"io"
"math/big"
"reflect"
"github.com/consensys/gnark/std/algebra/twistededwards"
"github.com/consensys/gnark/std/hash/mimc"
ecc_bn254 "github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/consensys/gnark-crypto/ecc/bn254/fr"
)
type Witness []fr.Element
func (witness *Witness) LimitReadFrom(r io.Reader) (int64, error) {
var buf [4]byte
if read, err := io.ReadFull(r, buf[:4]); err != nil {
return int64(read), err
}
sliceLen := binary.BigEndian.Uint32(buf[:4])
if len(*witness) != int(sliceLen) {
*witness = make([]fr.Element, sliceLen)
}
lr := io.LimitReader(r, int64(sliceLen*fr.Limbs*8))
dec := ecc_bn254.NewDecoder(lr)
for i := 0; i < int(sliceLen); i++ {
if err := dec.Decode(&(*witness)[i]); err != nil {
return dec.BytesRead() + 4, err
}
}
return dec.BytesRead() + 4, nil
}
func VerifyMerkleProof(cs *frontend.ConstraintSystem, mimc *mimc.MiMC, treeRootHash frontend.Variable, proofSet, helper, valid []frontend.Variable) {
sum := leafSum(mimc, proofSet[0])
for i := 1; i < len(proofSet); i++ {
cs.AssertIsBoolean(helper[i])
d1 := cs.Select(helper[i], sum, proofSet[i])
d2 := cs.Select(helper[i], proofSet[i], sum)
rst := nodeSum(mimc, d1, d2)
sum = cs.Select(valid[i], rst, sum)
}
// Compare our calculated Merkle root to the desired Merkle root.
cs.AssertIsEqual(sum, treeRootHash)
}
// nodeSum returns the hash created from data inserted to form a leaf.
// Without domain separation.
func nodeSum(mimc *mimc.MiMC, a, b frontend.Variable) frontend.Variable {
mimc.Reset()
mimc.Write(a, b)
return mimc.Sum()
}
// leafSum returns the hash created from data inserted to form a leaf.
// Without domain separation.
func leafSum(mimc *mimc.MiMC, data frontend.Variable) frontend.Variable {
mimc.Reset()
mimc.Write(data)
return mimc.Sum()
}
func CommitValueVerify(cs *frontend.ConstraintSystem, amount, amountRandom, shieldAmountX, shieldAmountY frontend.Variable) {
cs.AssertIsLessOrEqual(amount, 9000000000000000000)
curve, _ := twistededwards.NewEdCurve(ecc.BN254)
var pointAmount twistededwards.Point
pointAmount.ScalarMulFixedBase(cs, curve.BaseX, curve.BaseY, amount, curve)
var pointH bn254.PointAffine
pointH.X.SetString("9252662952969393856711468743327022054484546162727338092576697495684140272191")
pointH.Y.SetString("8220002160263982499510761441032261960817037857915665984040705585999508400744")
var pointRandom twistededwards.Point
pointRandom.ScalarMulFixedBase(cs, pointH.X, pointH.Y, amountRandom, curve)
var pointSum twistededwards.Point
pointSum.AddGeneric(cs, &pointAmount, &pointRandom, curve)
cs.AssertIsEqual(pointSum.X, shieldAmountX)
cs.AssertIsEqual(pointSum.Y, shieldAmountY)
}
func ConstructCircuitPubInput(pubInput string, circuit frontend.Circuit) error {
buf, err := GetByteBuff(pubInput)
if err != nil {
return errors.Wrapf(err, "decode string=%s", pubInput)
}
var witness Witness
_, err = witness.LimitReadFrom(buf)
if err != nil {
return errors.Wrapf(err, "LimitReadFrom pub input=%s", pubInput)
}
tValue := reflect.ValueOf(circuit)
if tValue.Kind() == reflect.Ptr {
tValue = tValue.Elem()
}
for i, v := range witness {
field := tValue.Type().Field(i)
tValue.FieldByName(field.Name).Addr().Interface().(*frontend.Variable).Assign(v.String())
}
return nil
}
func MulCurvePointG(val interface{}) *bn254.PointAffine {
var v fr.Element
v.SetInterface(val)
var scale big.Int
v.ToBigIntRegular(&scale)
var point bn254.PointAffine
ed := bn254.GetEdwardsCurve()
point.ScalarMul(&ed.Base, &scale)
return &point
}
func MulCurvePointH(pointHX, pointHY, val string) *bn254.PointAffine {
var v fr.Element
v.SetInterface(val)
var scale big.Int
v.ToBigIntRegular(&scale)
var pointV, pointH bn254.PointAffine
pointH.X.SetString(pointHX)
pointH.Y.SetString(pointHY)
pointV.ScalarMul(&pointH, &scale)
return &pointV
}
func GetCurveSum(points ...*bn254.PointAffine) *bn254.PointAffine {
//Add之前需初始化pointSum,不能空值,不然会等于0
pointSum := bn254.NewPointAffine(points[0].X, points[0].Y)
for _, a := range points[1:] {
pointSum.Add(&pointSum, a)
}
return &pointSum
}
//A=B+C
func CheckSumEqual(points ...*bn254.PointAffine) bool {
if len(points) < 2 {
return false
}
//Add之前需初始化pointSum,不能空值,不然会等于0
pointSum := bn254.NewPointAffine(points[1].X, points[1].Y)
for _, a := range points[2:] {
pointSum.Add(&pointSum, a)
}
if pointSum.X.Equal(&points[0].X) && pointSum.Y.Equal(&points[0].Y) {
return true
}
return false
}
func GetByteBuff(input string) (*bytes.Buffer, error) {
var buffInput bytes.Buffer
res, err := hex.DecodeString(input)
if err != nil {
return nil, errors.Wrapf(err, "getByteBuff to %s", input)
}
_, err = buffInput.Write(res)
if err != nil {
return nil, errors.Wrapf(err, "write buff %s", input)
}
return &buffInput, nil
}
func Str2Byte(v string) []byte {
var fr fr.Element
fr.SetString(v)
b := fr.Bytes()
return b[:]
}
func Byte2Str(v []byte) string {
var f fr.Element
f.SetBytes(v)
return f.String()
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment