Commit b9de3d60 authored by madengji's avatar madengji Committed by vipwzw

add mix coin contract

parent 7b04d42e
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
_ "github.com/33cn/plugin/plugin/dapp/issuance" //auto gen _ "github.com/33cn/plugin/plugin/dapp/issuance" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/js" //auto gen _ "github.com/33cn/plugin/plugin/dapp/js" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/lottery" //auto gen _ "github.com/33cn/plugin/plugin/dapp/lottery" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/mix" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/multisig" //auto gen _ "github.com/33cn/plugin/plugin/dapp/multisig" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/norm" //auto gen _ "github.com/33cn/plugin/plugin/dapp/norm" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/oracle" //auto gen _ "github.com/33cn/plugin/plugin/dapp/oracle" //auto gen
......
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 := NewAuth()
gob.Write("circuit_auth.r1cs", circuit, gurvy.BN256)
}
//spend commit hash the circuit implementing
/*
public:
treeRootHash
authorizePubKey
authorizeHash(=hash(authpubkey+noterandom))
authorizeSpendHash(=hash(spendpub+value+noterandom))
private:
spendAmount
spendPubKey
returnPubKey
authorizePubKey
authorizePriKey
spendFlag
noteRandom
path...
helper...
valid...
*/
func NewAuth() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
spendValue := circuit.SECRET_INPUT("spendAmount")
//spend pubkey
spendPubkey := circuit.SECRET_INPUT("spendPubKey")
returnPubkey := circuit.SECRET_INPUT("returnPubKey")
authPubkey := circuit.SECRET_INPUT("authorizePubKey")
authorizePrikey := circuit.SECRET_INPUT("authorizePriKey")
authPubHashInput := circuit.PUBLIC_INPUT("authorizePubKey")
// hash function
mimc, _ := mimc.NewMiMCGadget("seed", gurvy.BN256)
calcAuthPubHash := mimc.Hash(&circuit, authorizePrikey)
circuit.MUSTBE_EQ(authPubkey, calcAuthPubHash)
circuit.MUSTBE_EQ(authPubHashInput, mimc.Hash(&circuit, authPubkey))
//note hash random
noteRandom := circuit.SECRET_INPUT("noteRandom")
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, spendPubkey, returnPubkey)
calcAuthSpendHash := mimc.Hash(&circuit, targetPubHash, spendValue, noteRandom)
circuit.MUSTBE_EQ(authSpendHash, calcAuthSpendHash)
//通过merkle tree保证noteHash存在,即便return,auth都是null也是存在的,则可以不经过授权即可消费
//preImage=hash(spendPubkey, returnPubkey,AuthPubkey,spendValue,noteRandom)
noteHash := circuit.SECRET_INPUT("noteHash")
// specify note hash constraint
preImage := mimc.Hash(&circuit, spendPubkey, returnPubkey, authPubkey, spendValue, noteRandom)
circuit.MUSTBE_EQ(noteHash, mimc.Hash(&circuit, preImage))
merkelPathPart(&circuit, mimc, noteHash)
r1cs := circuit.ToR1CS()
return r1cs
}
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-1])
d1 := circuit.SELECT(helper[i-1], sum, proofSet[i])
d2 := circuit.SELECT(helper[i-1], 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
}
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:
nodeHash
amount
private:
spendPubkey
returnPubkey
authorizePubkey
noteRandom
*/
func NewDeposit() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
//公共输入以验证
spendValue := circuit.PUBLIC_INPUT("amount")
//spend pubkey
spendPubkey := circuit.SECRET_INPUT("spendPubkey")
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, mimc.Hash(&circuit, preImage))
r1cs := circuit.ToR1CS()
return r1cs
}
package main
import (
"strconv"
"github.com/consensys/gnark/encoding/gob"
"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 main() {
circuit := NewTransferInput()
gob.Write("circuit_transfer_input.r1cs", circuit, gurvy.BN256)
}
//spend commit hash the circuit implementing
/*
public:
treeRootHash
commitValueX
commitValueY
authorizeHash
nullifierHash
private:
spendAmount
spendRandom
spendPubKey
returnPubKey
authorizePubKey
spendPriKey
spendFlag
authorizeFlag
noteRandom
path...
helper...
valid...
*/
func NewTransferInput() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
spendValue := circuit.SECRET_INPUT("spendAmount")
//spend pubkey
spendPubkey := circuit.SECRET_INPUT("spendPubkey")
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("authorizeHash")
nullValue := circuit.ALLOCATE("null")
// specify auth hash constraint
calcAuthHash := mimc.Hash(&circuit, targetPubHash, spendValue, noteRandom)
targetAuthHash := circuit.SELECT(authFlag, calcAuthHash, nullValue)
circuit.MUSTBE_EQ(authHash, targetAuthHash)
//通过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, spendPubkey, calcReturnPubkey, calcAuthPubkey, spendValue, noteRandom)
circuit.MUSTBE_EQ(noteHash, mimc.Hash(&circuit, preImage))
commitValuePart(&circuit, spendValue)
merkelPathPart(&circuit, mimc, noteHash)
r1cs := circuit.ToR1CS()
return r1cs
}
func commitValuePart(circuit *frontend.CS, spendValue *frontend.Constraint) {
//cmt=transfer_value*G + random_value*H
cmtvalueX := circuit.PUBLIC_INPUT("commitValueX")
cmtvalueY := circuit.PUBLIC_INPUT("commitValueY")
// set curve parameters
edgadget, _ := twistededwards_gadget.NewEdCurveGadget(gurvy.BN256)
// set point G in the circuit
pointGSnark := twistededwards_gadget.NewPointGadget(circuit, nil, nil)
//scalar := circuit.ALLOCATE("-1")
circuit.MUSTBE_LESS_OR_EQ(spendValue, 10000000000, 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("spendRandom")
//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)
}
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)
//depth:10, path num need be 9
for i := 1; 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)
}
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 := NewTransferOutput()
gob.Write("circuit_transfer_output.r1cs", circuit, gurvy.BN256)
}
//spend commit hash the circuit implementing
/*
public:
commitValueX
commitValueY
nodeHash
private:
spendAmount
spendRandom
spendPubKey
returnPubKey
authorizePubKey
noteRandom
*/
func NewTransferOutput() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
spendValue := circuit.SECRET_INPUT("spendAmount")
//spend pubkey
spendPubkey := circuit.SECRET_INPUT("spendPubKey")
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.SECRET_INPUT("noteHash")
// specify note hash constraint
preImage := mimc.Hash(&circuit, spendPubkey, returnPubkey, authPubkey, spendValue, noteRandom)
circuit.MUSTBE_EQ(noteHash, mimc.Hash(&circuit, preImage))
commitValuePart(&circuit, spendValue)
r1cs := circuit.ToR1CS()
return r1cs
}
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 := NewWithdraw()
gob.Write("circuit_withdraw.r1cs", circuit, gurvy.BN256)
}
//withdraw commit hash the circuit implementing
/*
public:
treeRootHash
authorizeHash
nullifierHash
amount
private:
spendPubKey
returnPubKey
authorizePubKey
spendPriKey
spendFlag
authorizeFlag
noteRandom
path...
helper...
valid...
*/
func NewWithdraw() *frontend.R1CS {
// create root constraint system
circuit := frontend.New()
spendValue := circuit.PUBLIC_INPUT("amount")
//spend pubkey
spendPubkey := circuit.SECRET_INPUT("spendPubKey")
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("authorizeHash")
nullValue := circuit.ALLOCATE("null")
// specify auth hash constraint
calcAuthHash := mimc.Hash(&circuit, targetPubHash, spendValue, noteRandom)
targetAuthHash := circuit.SELECT(authFlag, calcAuthHash, nullValue)
circuit.MUSTBE_EQ(authHash, targetAuthHash)
//通过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, spendPubkey, calcReturnPubkey, calcAuthPubkey, spendValue, noteRandom)
circuit.MUSTBE_EQ(noteHash, mimc.Hash(&circuit, preImage))
merkelPathPart(&circuit, mimc, noteHash)
r1cs := circuit.ToR1CS()
return r1cs
}
/*
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")
_ = readCmd.MarkPersistentFlagRequired("type")
}
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 gob
import (
"bytes"
"encoding/gob"
"encoding/hex"
"errors"
"io"
"log"
"os"
)
var (
ErrInvalidCurve = errors.New("trying to deserialize an object serialized with another curve")
)
// Write serialize object into file
// uses gob + gzip
func Write(path string, from interface{}) error {
// create file
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
return Serialize(f, from)
}
// Read read and deserialize input into object
// provided interface must be a pointer
// uses gob + gzip
func Read(path string, into interface{}) error {
// open file
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
fileinfo, err := f.Stat()
if err != nil {
log.Fatal(err)
}
fileSize := fileinfo.Size()
buffer := make([]byte, fileSize)
_, err = f.Read(buffer)
if err != nil {
log.Fatal(err)
}
var buf bytes.Buffer
buf.Write(buffer)
return Deserialize(&buf, into)
}
func ReadBuf(str string, into interface{}) error {
strByts, err := hex.DecodeString(str)
if err != nil {
log.Fatal(err)
}
var buf bytes.Buffer
buf.Write(strByts)
return Deserialize(&buf, into)
}
// Serialize object from into f
// uses gob
func Serialize(f io.Writer, from interface{}) error {
// gzip writer
encoder := gob.NewEncoder(f)
// encode our object
if err := encoder.Encode(from); err != nil {
return err
}
return nil
}
// Deserialize f into object into
// uses gob + gzip
func Deserialize(f io.Reader, into interface{}) error {
// gzip reader
decoder := gob.NewDecoder(f)
if err := decoder.Decode(into); err != nil {
return err
}
return nil
}
public, treeRootHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
public, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
public, authorizeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
public, authorizeSpendHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
secret, spendAmount,28242048
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, authorizePriKey,19226210204356004706765360050059680583735587569269469539941275797408975356275
secret, spendFlag,0
secret, noteRandom,28242048
secret, path0,1e44c73ba7980b0450a8e997c9d9c78be5a9d7ceaf597df781469a1c9db4e4c9
secret, path1,191a80e377af9e0d04e1d75e8d702d4c2db21b952b9fff6bcca31f9e9fd5de00
secret, path2,220dc2041a8c81086a9bc8084e7f9ee0788ae2c8b7928e0b2e2672339b2933b3
secret, path3,295d631fcf0ed0d34742ac560fe7a0c0585225cff9194806d4d9d8e1f00e1747
secret, path4,215849ad7bd4344a807f4f0c9aefd2131572e3cb21a8b21aa96e8a11c4a214e5
secret, path5,0
secret, path6,0
secret, path7,0
secret, path8,0
secret, path9,0
secret, path10,0
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, helper10,1
secret, valid0,1
secret, valid1,1
secret, valid2,1
secret, valid3,1
secret, valid4,1
secret, valid5,0
secret, valid6,0
secret, valid7,0
secret, valid8,0
secret, valid9,0
secret, valid10,0
public, nodeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
public, amount,1000
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, noteRandom,28242048
public, treeRootHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
public, commitValueX,9940039130125917226477779823200431190767730273667531970219395440191717439673
public, commitValueY,9940039130125917226477779823200431190767730273667531970219395440191717439673
public, authorizeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
public, nullifierHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
secret, spendAmount,28242048
secret, spendRandom,1000
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, spendPriKey,19226210204356004706765360050059680583735587569269469539941275797408975356275
secret, spendFlag,0
secret, authorizeFlag,0
secret, noteRandom,28242048
secret, path0,1e44c73ba7980b0450a8e997c9d9c78be5a9d7ceaf597df781469a1c9db4e4c9
secret, path1,191a80e377af9e0d04e1d75e8d702d4c2db21b952b9fff6bcca31f9e9fd5de00
secret, path2,220dc2041a8c81086a9bc8084e7f9ee0788ae2c8b7928e0b2e2672339b2933b3
secret, path3,295d631fcf0ed0d34742ac560fe7a0c0585225cff9194806d4d9d8e1f00e1747
secret, path4,215849ad7bd4344a807f4f0c9aefd2131572e3cb21a8b21aa96e8a11c4a214e5
secret, path5,0
secret, path6,0
secret, path7,0
secret, path8,0
secret, path9,0
secret, path10,0
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, helper10,1
secret, valid0,1
secret, valid1,1
secret, valid2,1
secret, valid3,1
secret, valid4,1
secret, valid5,0
secret, valid6,0
secret, valid7,0
secret, valid8,0
secret, valid9,0
secret, valid10,0
public, commitValueX,9940039130125917226477779823200431190767730273667531970219395440191717439673
public, commitValueY,9940039130125917226477779823200431190767730273667531970219395440191717439673
public, nodeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
secret, spendAmount,28242048
secret, spendRandom,28242048
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, noteRandom,28242048
public, treeRootHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
public, authorizeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
public, nullifierHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4
public, amount,28242048
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673
secret, spendPriKey,19226210204356004706765360050059680583735587569269469539941275797408975356275
secret, spendFlag,0
secret, authorizeFlag,0
secret, noteRandom,28242048
secret, path0,1e44c73ba7980b0450a8e997c9d9c78be5a9d7ceaf597df781469a1c9db4e4c9
secret, path1,191a80e377af9e0d04e1d75e8d702d4c2db21b952b9fff6bcca31f9e9fd5de00
secret, path2,220dc2041a8c81086a9bc8084e7f9ee0788ae2c8b7928e0b2e2672339b2933b3
secret, path3,295d631fcf0ed0d34742ac560fe7a0c0585225cff9194806d4d9d8e1f00e1747
secret, path4,215849ad7bd4344a807f4f0c9aefd2131572e3cb21a8b21aa96e8a11c4a214e5
secret, path5,0
secret, path6,0
secret, path7,0
secret, path8,0
secret, path9,0
secret, path10,0
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, helper10,1
secret, valid0,1
secret, valid1,1
secret, valid2,1
secret, valid3,1
secret, valid4,1
secret, valid5,0
secret, valid6,0
secret, valid7,0
secret, valid8,0
secret, valid9,0
secret, valid10,0
/*
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()
}
// 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 commands
import (
"fmt"
"strings"
"github.com/33cn/chain33/rpc/jsonclient"
"github.com/33cn/chain33/types"
rpctypes "github.com/33cn/chain33/rpc/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/spf13/cobra"
)
//ParcCmd paracross cmd register
func ParcCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "mix",
Short: "Construct mix coin transactions",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
CreateDepositCmd(),
CreateTransferCmd(),
CreateWithdrawCmd(),
CreateConfigCmd(),
CreateAuthorizeCmd(),
)
return cmd
}
func getRealExecName(paraName string, name string) string {
if strings.HasPrefix(name, "user.p.") {
return name
}
return paraName + name
}
// CreateDepositCmd create raw asset transfer tx
func CreateDepositCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "deposit",
Short: "Create a asset deposit to mix coin contract",
Run: createDeposit,
}
addCreateDepositFlags(cmd)
return cmd
}
func addCreateDepositFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proofs", "p", "", "'proof-pubinput' pair, multi pairs allowed with ','")
cmd.MarkFlagRequired("proofs")
cmd.Flags().Uint64P("amount", "a", 0, "deposit amount")
cmd.MarkFlagRequired("amount")
}
func parseProofPara(input string) ([]*mixTy.ZkProofInfo, error) {
var proofInputs []*mixTy.ZkProofInfo
inputParas := strings.Split(input, ",")
for _, i := range inputParas {
inputs := strings.Split(i, "-")
if len(inputs) != 2 {
fmt.Println("proofs parameters not correct:", i)
return nil, types.ErrInvalidParam
}
var proofInfo mixTy.ZkProofInfo
proofInfo.Proof = inputs[0]
proofInfo.PublicInput = inputs[1]
proofInputs = append(proofInputs, &proofInfo)
}
return proofInputs, nil
}
func createDeposit(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
amount, _ := cmd.Flags().GetUint64("amount")
proofsPara, _ := cmd.Flags().GetString("proofs")
proofInputs, err := parseProofPara(proofsPara)
if err != nil {
return
}
payload := &mixTy.MixDepositAction{}
payload.Amount = amount
payload.NewCommits = append(payload.NewCommits, proofInputs...)
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, mixTy.MixX),
ActionName: "Deposit",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreateWithdrawCmd create raw asset transfer tx
func CreateWithdrawCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "withdraw",
Short: "Create a asset withdraw from mix coin contract",
Run: createWithdraw,
}
addCreateWithdrawFlags(cmd)
return cmd
}
func addCreateWithdrawFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proofs", "p", "", "spend 'proof-pubinput' pair, multi pairs allowed with ','")
cmd.MarkFlagRequired("proofs")
cmd.Flags().Uint64P("amount", "a", 0, "withdraw amount")
cmd.MarkFlagRequired("amount")
}
func createWithdraw(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
amount, _ := cmd.Flags().GetUint64("amount")
proofsPara, _ := cmd.Flags().GetString("proofs")
proofInputs, err := parseProofPara(proofsPara)
if err != nil {
return
}
payload := &mixTy.MixWithdrawAction{}
payload.Amount = amount
payload.SpendCommits = append(payload.SpendCommits, proofInputs...)
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, mixTy.MixX),
ActionName: "Withdraw",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreateTransferCmd create raw asset transfer tx
func CreateTransferCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "transfer",
Short: "Create a asset transfer in mix coin contract",
Run: createTransfer,
}
addCreateTransferFlags(cmd)
return cmd
}
func addCreateTransferFlags(cmd *cobra.Command) {
cmd.Flags().StringP("input", "i", "", "input 'proof-pubinput' pair, multi pairs allowed with ','")
cmd.MarkFlagRequired("input")
cmd.Flags().StringP("output", "o", "", "output 'proof-pubinput' pair, multi pairs allowed with ','")
cmd.MarkFlagRequired("output")
}
func createTransfer(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
proofsInput, _ := cmd.Flags().GetString("input")
proofsOutput, _ := cmd.Flags().GetString("output")
proofInputs, err := parseProofPara(proofsInput)
if err != nil {
fmt.Println("proofsInput error")
return
}
proofOutputs, err := parseProofPara(proofsOutput)
if err != nil {
fmt.Println("proofsOutput error")
return
}
payload := &mixTy.MixTransferAction{}
payload.Input = append(payload.Input, proofInputs...)
payload.Output = append(payload.Output, proofOutputs...)
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, mixTy.MixX),
ActionName: "Transfer",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreateAuthorizeCmd create raw asset transfer tx
func CreateAuthorizeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "authorize",
Short: "Create a asset authorize in mix coin contract",
Run: createAuthorize,
}
addCreateAuthorizeFlags(cmd)
return cmd
}
func addCreateAuthorizeFlags(cmd *cobra.Command) {
cmd.Flags().StringP("proofs", "p", "", "authorize 'proof-pubinput' pair, multi pairs allowed with ','")
cmd.MarkFlagRequired("proofs")
}
func createAuthorize(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
proofsPara, _ := cmd.Flags().GetString("proofs")
proofInputs, err := parseProofPara(proofsPara)
if err != nil {
return
}
payload := &mixTy.MixAuthorizeAction{}
payload.AuthCommits = append(payload.AuthCommits, proofInputs...)
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, mixTy.MixX),
ActionName: "Authorize",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreateDepositCmd create raw asset transfer tx
func CreateConfigCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "config",
Short: "Proof parameters config to mix coin contract",
}
cmd.AddCommand(mixConfigVerifyKeyParaCmd())
cmd.AddCommand(mixConfigAuthPubKeyParaCmd())
return cmd
}
func mixConfigVerifyKeyParaCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "verify",
Short: "zk proof verify key config cmd",
Run: createConfigVerify,
}
addVkConfigFlags(cmd)
return cmd
}
func addVkConfigFlags(cmd *cobra.Command) {
cmd.Flags().Uint32P("action", "a", 0, "0:add,1:delete")
cmd.Flags().Uint32P("curveid", "i", 0, "zk curve id,1:bls377,2:bls381,3:bn256")
cmd.MarkFlagRequired("curveid")
cmd.Flags().Uint32P("circuit", "c", 0, "mix circuit type,0:deposit,1:withdraw,2:spendinput,3:spendout,4:authorize")
cmd.MarkFlagRequired("circuit")
cmd.Flags().StringP("key", "k", "", "zk proof verify key")
cmd.MarkFlagRequired("key")
}
func createConfigVerify(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
action, _ := cmd.Flags().GetUint32("action")
curveid, _ := cmd.Flags().GetUint32("curveid")
circuit, _ := cmd.Flags().GetUint32("circuit")
key, _ := cmd.Flags().GetString("key")
var zkVk mixTy.ZkVerifyKey
zkVk.Value = key
zkVk.Type = mixTy.VerifyType(circuit)
zkVk.CurveId = mixTy.ZkCurveId(curveid)
payload := &mixTy.MixConfigAction{}
payload.Ty = mixTy.MixConfigType_VerifyKey
payload.Action = mixTy.MixConfigAct(action)
payload.Value = &mixTy.MixConfigAction_VerifyKey{VerifyKey: &zkVk}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, mixTy.MixX),
ActionName: "Config",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
func mixConfigAuthPubKeyParaCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "pubkey",
Short: "mix authorize pub key config cmd",
Run: createConfigPubKey,
}
addPubKeyConfigFlags(cmd)
return cmd
}
func addPubKeyConfigFlags(cmd *cobra.Command) {
cmd.Flags().Uint32P("action", "a", 0, "0:add,1:delete")
cmd.Flags().StringP("key", "k", "", "zk proof verify key")
cmd.MarkFlagRequired("key")
}
func createConfigPubKey(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
action, _ := cmd.Flags().GetUint32("action")
key, _ := cmd.Flags().GetString("key")
var pubkey mixTy.AuthorizePubKey
pubkey.Value = key
payload := &mixTy.MixConfigAction{}
payload.Ty = mixTy.MixConfigType_AuthPubKey
payload.Action = mixTy.MixConfigAct(action)
payload.Value = &mixTy.MixConfigAction_AuthKey{AuthKey: &pubkey}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, mixTy.MixX),
ActionName: "Config",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// 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 (
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/client"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
"github.com/golang/protobuf/proto"
token "github.com/33cn/plugin/plugin/dapp/token/types"
)
type action struct {
coinsAccount *account.DB
db dbm.KV
localdb dbm.KVDB
txhash []byte
fromaddr string
blocktime int64
height int64
execaddr string
api client.QueueProtocolAPI
tx *types.Transaction
exec *Mix
}
func newAction(t *Mix, tx *types.Transaction) *action {
hash := tx.Hash()
fromaddr := tx.From()
return &action{t.GetCoinsAccount(), t.GetStateDB(), t.GetLocalDB(), hash, fromaddr,
t.GetBlockTime(), t.GetHeight(), dapp.ExecAddress(string(tx.Execer)), t.GetAPI(), tx, t}
}
func createAccount(cfg *types.Chain33Config, execer, symbol string, db dbm.KV) (*account.DB, error) {
var accDB *account.DB
if symbol == "" {
accDB = account.NewCoinsAccount(cfg)
accDB.SetDB(db)
return accDB, nil
}
if execer == "" {
execer = token.TokenX
}
return account.NewAccountDB(cfg, execer, symbol, db)
}
func isNotFound(err error) bool {
if err != nil && (err == dbm.ErrNotFoundInDb || err == types.ErrNotFound) {
return true
}
return false
}
func mergeReceipt(receipt1, receipt2 *types.Receipt) *types.Receipt {
if receipt2 != nil {
receipt1.KV = append(receipt1.KV, receipt2.KV...)
receipt1.Logs = append(receipt1.Logs, receipt2.Logs...)
}
return receipt1
}
func makeReceipt(key []byte, logTy int32, data proto.Message) *types.Receipt {
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
{Key: key, Value: types.Encode(data)},
},
Logs: []*types.ReceiptLog{
{Ty: logTy, Log: types.Encode(data)},
},
}
}
// 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 (
"encoding/hex"
"encoding/json"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
func (a *action) authParamCheck(input *mixTy.AuthorizePublicInput) error {
//check tree rootHash exist
if !checkTreeRootHashExist(a.db, input.TreeRootHash) {
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", common.ToHex(input.TreeRootHash))
}
//authorize key should not exist
authKey := calcAuthorizeHashKey(common.ToHex(input.AuthorizeHash))
_, err := a.db.Get(authKey)
if err == nil {
return errors.Wrapf(mixTy.ErrAuthorizeHashExist, "auth=%s", common.ToHex(input.AuthorizeHash))
}
if !isNotFound(err) {
return errors.Wrapf(err, "auth=%s", common.ToHex(input.AuthorizeHash))
}
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.Data {
if input.AuthorizePubKey == k {
found = true
break
}
}
if !found {
return errors.Wrapf(types.ErrNotFound, "authPubkey=%s", input.AuthorizePubKey)
}
return nil
}
func (a *action) authorizeVerify(proof *mixTy.ZkProofInfo) (*mixTy.AuthorizePublicInput, error) {
var input mixTy.AuthorizePublicInput
data, err := hex.DecodeString(proof.PublicInput)
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)
}
err = a.authParamCheck(&input)
if err != nil {
return nil, err
}
//zk-proof校验
err = a.zkProofVerify(proof, mixTy.VerifyType_AUTHORIZE)
if err != nil {
return nil, err
}
return &input, nil
}
/*
1. verify(zk-proof)
2, check tree root hash exist
3, check authorize pubkey hash in config or not
4. check authorize hash if exist in authorize pool
5. set authorize hash and authorize_spend hash
*/
func (a *action) Authorize(authorize *mixTy.MixAuthorizeAction) (*types.Receipt, error) {
var inputs []*mixTy.AuthorizePublicInput
for _, proof := range authorize.AuthCommits {
in, err := a.authorizeVerify(proof)
if err != nil {
return nil, err
}
inputs = append(inputs, in)
}
receipt := &types.Receipt{Ty: types.ExecOk}
for _, in := range inputs {
r := makeReceipt(calcAuthorizeHashKey(common.ToHex(in.AuthorizeHash)), mixTy.TyLogAuthorizeSet, &mixTy.ExistValue{Data: true})
mergeReceipt(receipt, r)
r = makeReceipt(calcAuthorizeSpendHashKey(common.ToHex(in.AuthorizeSpendHash)), mixTy.TyLogAuthorizeSpendSet, &mixTy.ExistValue{Data: true})
mergeReceipt(receipt, r)
}
return receipt, nil
}
// 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 (
"bytes"
"github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/NebulousLabs/merkletree"
"github.com/consensys/gnark/crypto/hash/mimc/bn256"
"github.com/pkg/errors"
)
//func makeTreeReceipt(key []byte, logTy int32, data proto.Message) *types.Receipt {
// return &types.Receipt{
// Ty: types.ExecOk,
// KV: []*types.KeyValue{
// {Key: key, Value: types.Encode(data)},
// },
// Logs: []*types.ReceiptLog{
// {Ty: logTy, Log: types.Encode(data)},
// },
// }
//}
func makeTreeLeavesReceipt(data *mixTy.CommitTreeLeaves) *types.Receipt {
return makeReceipt(calcCurrentCommitLeavesKey(), mixTy.TyLogCurrentCommitTreeLeaves, data)
}
func makeTreeRootsReceipt(data *mixTy.CommitTreeRoots) *types.Receipt {
return makeReceipt(calcCurrentCommitRootsKey(), mixTy.TyLogCurrentCommitTreeRoots, data)
}
func makeCurrentTreeReceipt(leaves *mixTy.CommitTreeLeaves, roots *mixTy.CommitTreeRoots) *types.Receipt {
r1 := makeTreeLeavesReceipt(leaves)
r2 := makeTreeRootsReceipt(roots)
return mergeReceipt(r1, r2)
}
func makeTreeRootLeavesReceipt(root []byte, data *mixTy.CommitTreeLeaves) *types.Receipt {
return makeReceipt(calcCommitTreeRootLeaves(common.ToHex(root)), mixTy.TyLogCommitTreeRootLeaves, data)
}
func makeTreeArchiveRootsReceipt(data *mixTy.CommitTreeRoots) *types.Receipt {
return makeReceipt(calcCommitTreeArchiveRootsKey(), mixTy.TyLogCommitTreeArchiveRoots, data)
}
func getCommitLeaves(db dbm.KV, key []byte) (*mixTy.CommitTreeLeaves, error) {
v, err := db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db")
}
var leaves mixTy.CommitTreeLeaves
err = types.Decode(v, &leaves)
if err != nil {
return nil, errors.Wrapf(err, "decode db verify key")
}
return &leaves, nil
}
func getCurrentCommitTreeLeaves(db dbm.KV) (*mixTy.CommitTreeLeaves, error) {
return getCommitLeaves(db, calcCurrentCommitLeavesKey())
}
func getCommitRootLeaves(db dbm.KV, rootHash []byte) (*mixTy.CommitTreeLeaves, error) {
return getCommitLeaves(db, calcCommitTreeRootLeaves(common.ToHex(rootHash)))
}
func getCommitTreeRoots(db dbm.KV, key []byte) (*mixTy.CommitTreeRoots, error) {
v, err := db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db")
}
var roots mixTy.CommitTreeRoots
err = types.Decode(v, &roots)
if err != nil {
return nil, errors.Wrapf(err, "decode db verify key")
}
return &roots, nil
}
func getCurrentCommitTreeRoots(db dbm.KV) (*mixTy.CommitTreeRoots, error) {
return getCommitTreeRoots(db, calcCurrentCommitRootsKey())
}
func getArchiveCommitRoots(db dbm.KV) (*mixTy.CommitTreeRoots, error) {
return getCommitTreeRoots(db, calcCommitTreeArchiveRootsKey())
}
func getNewTree() *merkletree.Tree {
return merkletree.New(bn256.NewMiMC("seed"))
}
func calcTreeRoot(leaves *mixTy.CommitTreeLeaves) []byte {
tree := getNewTree()
for _, leaf := range leaves.Data {
tree.Push(leaf)
}
return tree.Root()
}
func getNewCommitLeaves() (*mixTy.CommitTreeLeaves, *mixTy.CommitTreeRoots) {
leaves := &mixTy.CommitTreeLeaves{}
roots := &mixTy.CommitTreeRoots{}
//第一个叶子节点都是固定的"00"字节
leaf := []byte("00")
leaves.Data = append(leaves.Data, leaf)
roots.Data = append(roots.Data, calcTreeRoot(leaves))
return leaves, roots
}
func initNewLeaves(leaf []byte) *types.Receipt {
leaves, roots := getNewCommitLeaves()
if len(leaf) > 0 {
leaves.Data = append(leaves.Data, leaf)
roots.Data = append(roots.Data, calcTreeRoot(leaves))
}
return makeCurrentTreeReceipt(leaves, roots)
}
func archiveRoots(db dbm.KV, root []byte, leaves *mixTy.CommitTreeLeaves) (*types.Receipt, error) {
receiptRootLeaves := makeTreeRootLeavesReceipt(root, leaves)
archiveRoots, err := getArchiveCommitRoots(db)
if isNotFound(errors.Cause(err)) {
archiveRoots = &mixTy.CommitTreeRoots{}
err = nil
}
if err != nil {
return nil, err
}
archiveRoots.Data = append(archiveRoots.Data, root)
receiptArch := makeTreeArchiveRootsReceipt(archiveRoots)
return mergeReceipt(receiptRootLeaves, receiptArch), nil
}
/*
1. 增加到当前leaves 和roots
2. 如果leaves 达到最大比如1024,则按root归档leaves,并归档相应root
3. 归档同时初始化新的current leaves 和roots
*/
func pushTree(db dbm.KV, leaf []byte) (*types.Receipt, error) {
leaves, err := getCurrentCommitTreeLeaves(db)
if isNotFound(errors.Cause(err)) {
//系统初始状态
return initNewLeaves(leaf), nil
}
if err != nil {
return nil, err
}
//Roots应该和Leaves保持一致,如果err 是不应该的。
roots, err := getCurrentCommitTreeRoots(db)
if isNotFound(errors.Cause(err)) {
roots = &mixTy.CommitTreeRoots{}
err = nil
}
if err != nil {
return nil, err
}
leaves.Data = append(leaves.Data, leaf)
currentRoot := calcTreeRoot(leaves)
roots.Data = append(roots.Data, currentRoot)
r := makeCurrentTreeReceipt(leaves, roots)
//归档
if len(leaves.Data) >= mixTy.MaxTreeLeaves {
receiptArch, err := archiveRoots(db, currentRoot, leaves)
if err != nil {
return nil, err
}
mergeReceipt(r, receiptArch)
//创建新的leaves
receiptNew := initNewLeaves(nil)
mergeReceipt(r, receiptNew)
}
return r, nil
}
func checkTreeRootHashExist(db dbm.KV, hash []byte) bool {
var roots [][]byte
currentRoots, err := getCurrentCommitTreeRoots(db)
if err == nil {
roots = append(roots, currentRoots.Data...)
}
archiveRoots, err := getArchiveCommitRoots(db)
if err == nil {
roots = append(roots, archiveRoots.Data...)
}
for _, k := range roots {
if bytes.Equal(k, hash) {
return true
}
}
return false
}
func getProveData(targetLeaf []byte, leaves [][]byte) (*mixTy.CommitTreeProve, error) {
index := 0
for i, key := range leaves {
if bytes.Equal(key, targetLeaf) {
index = i
break
}
}
//index=0的leaf是占位"00",不会和leaf相等
if index == 0 {
return nil, mixTy.ErrLeafNotFound
}
tree := getNewTree()
tree.SetIndex(uint64(index))
for _, key := range leaves {
tree.Push(key)
}
root, set, proofIndex, num := tree.Prove()
var prove mixTy.CommitTreeProve
prove.RootHash = common.ToHex(root)
prove.ProofIndex = uint32(proofIndex)
prove.NumLeaves = uint32(num)
for _, s := range set {
prove.ProofSet = append(prove.ProofSet, common.ToHex(s))
}
return &prove, nil
}
func CalcTreeProve(db dbm.KV, rootHash, leaf []byte) (*mixTy.CommitTreeProve, error) {
leaves, err := getCurrentCommitTreeLeaves(db)
if err == nil {
p, err := getProveData(leaf, leaves.Data)
if err == nil {
return p, nil
}
}
if len(rootHash) > 0 {
leaves, err := getCommitRootLeaves(db, rootHash)
if err != nil {
return nil, err
}
p, err := getProveData(leaf, leaves.Data)
if err != nil {
return nil, errors.Wrapf(err, "hash=%s,leaf=%s", common.ToHex(rootHash), common.ToHex(leaf))
}
return p, nil
}
roots, err := getArchiveCommitRoots(db)
if err == nil {
for _, root := range roots.Data {
leaves, err := getCommitRootLeaves(db, root)
if err == nil {
p, err := getProveData(leaf, leaves.Data)
if err == nil {
return p, nil
}
}
}
}
return nil, errors.Wrapf(err, "hash=%s,leaf=%s", common.ToHex(rootHash), common.ToHex(leaf))
}
// 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 (
manager "github.com/33cn/chain33/system/dapp/manage/types"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
// IsSuperManager is supper manager or not
func isSuperManager(cfg *types.Chain33Config, addr string) bool {
confManager := types.ConfSub(cfg, manager.ManageX)
for _, m := range confManager.GStrList("superManager") {
if addr == m {
return true
}
}
return false
}
// need super manager
func (a *action) Config(config *mixTy.MixConfigAction) (*types.Receipt, error) {
cfg := a.api.GetConfig()
if !isSuperManager(cfg, a.fromaddr) {
return nil, types.ErrNotAllow
}
switch config.Ty {
case mixTy.MixConfigType_VerifyKey:
if config.Action == mixTy.MixConfigAct_Add {
return a.ConfigAddVerifyKey(config.GetVerifyKey())
} else {
return a.ConfigDeleteVerifyKey(config.GetVerifyKey())
}
case mixTy.MixConfigType_AuthPubKey:
if config.Action == mixTy.MixConfigAct_Add {
return a.ConfigAddAuthPubKey(config.GetAuthKey())
} else {
return a.ConfigDeleteAuthPubKey(config.GetAuthKey())
}
}
return nil, types.ErrNotFound
}
func makeConfigVerifyKeyReceipt(data *mixTy.ZkVerifyKeys) *types.Receipt {
key := getVerifyKeysKey()
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
{Key: key, Value: types.Encode(data)},
},
Logs: []*types.ReceiptLog{
{Ty: mixTy.TyLogMixConfigVk, Log: types.Encode(data)},
},
}
}
func (a *action) getVerifyKeys() (*mixTy.ZkVerifyKeys, error) {
key := getVerifyKeysKey()
v, err := a.db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db verify key")
}
var keys mixTy.ZkVerifyKeys
err = types.Decode(v, &keys)
if err != nil {
return nil, errors.Wrapf(err, "decode db verify key")
}
return &keys, nil
}
func (a *action) ConfigAddVerifyKey(newKey *mixTy.ZkVerifyKey) (*types.Receipt, error) {
keys, err := a.getVerifyKeys()
if isNotFound(errors.Cause(err)) {
keys := &mixTy.ZkVerifyKeys{}
keys.Data = append(keys.Data, newKey)
return makeConfigVerifyKeyReceipt(keys), nil
}
if err != nil {
return nil, err
}
keys.Data = append(keys.Data, newKey)
return makeConfigVerifyKeyReceipt(keys), nil
}
func (a *action) ConfigDeleteVerifyKey(config *mixTy.ZkVerifyKey) (*types.Receipt, error) {
keys, err := a.getVerifyKeys()
if err != nil {
return nil, err
}
var newKeys mixTy.ZkVerifyKeys
for _, v := range keys.Data {
//不同类型的vk 肯定不同,
if v.CurveId == config.CurveId && v.Value == config.Value {
continue
}
newKeys.Data = append(newKeys.Data, v)
}
return makeConfigVerifyKeyReceipt(&newKeys), nil
}
func makeConfigAuthKeyReceipt(data *mixTy.AuthPubKeys) *types.Receipt {
key := getAuthPubKeysKey()
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
{Key: key, Value: types.Encode(data)},
},
Logs: []*types.ReceiptLog{
{Ty: mixTy.TyLogMixConfigAuth, Log: types.Encode(data)},
},
}
}
func (a *action) getAuthKeys() (*mixTy.AuthPubKeys, error) {
key := getAuthPubKeysKey()
v, err := a.db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db")
}
var keys mixTy.AuthPubKeys
err = types.Decode(v, &keys)
if err != nil {
return nil, errors.Wrapf(err, "decode db key")
}
return &keys, nil
}
func (a *action) ConfigAddAuthPubKey(config *mixTy.AuthorizePubKey) (*types.Receipt, error) {
keys, err := a.getAuthKeys()
if isNotFound(errors.Cause(err)) {
keys := &mixTy.AuthPubKeys{}
keys.Data = append(keys.Data, config.Value)
return makeConfigAuthKeyReceipt(keys), nil
}
if err != nil {
return nil, err
}
keys.Data = append(keys.Data, config.Value)
return makeConfigAuthKeyReceipt(keys), nil
}
func (a *action) ConfigDeleteAuthPubKey(config *mixTy.AuthorizePubKey) (*types.Receipt, error) {
keys, err := a.getAuthKeys()
if err != nil {
return nil, err
}
var newKeys mixTy.AuthPubKeys
for _, v := range keys.Data {
if config.Value == v {
continue
}
newKeys.Data = append(newKeys.Data, v)
}
return makeConfigAuthKeyReceipt(&newKeys), nil
}
// 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 (
"encoding/hex"
"encoding/json"
"strconv"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"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/golang/protobuf/proto"
"github.com/pkg/errors"
)
func makeNullifierSetReceipt(hash []byte, data proto.Message) *types.Receipt {
return makeReceipt(calcNullifierHashKey(common.ToHex(hash)), mixTy.TyLogNulliferSet, data)
}
func (a *action) zkProofVerify(proof *mixTy.ZkProofInfo, verifyTy mixTy.VerifyType) error {
keys, err := a.getVerifyKeys()
if err != nil {
return err
}
var pass bool
for _, verifyKey := range keys.Data {
if verifyKey.Type == verifyTy {
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) ([]byte, uint64, error) {
var input mixTy.DepositPublicInput
data, err := hex.DecodeString(proof.PublicInput)
if err != nil {
return nil, 0, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
err = json.Unmarshal(data, &input)
if err != nil {
return nil, 0, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput)
}
val, err := strconv.ParseUint(input.Amount, 10, 64)
if err != nil {
return nil, 0, errors.Wrapf(err, "parseUint=%s", input.Amount)
}
err = a.zkProofVerify(proof, mixTy.VerifyType_DEPOSIT)
if err != nil {
return nil, 0, err
}
return input.NodeHash, val, nil
}
/*
1. verify zk-proof
2. verify commit value vs value
3. deposit to mix contract
4. add new commits to merkle tree
*/
func (a *action) Deposit(deposit *mixTy.MixDepositAction) (*types.Receipt, error) {
//1. zk-proof校验
var sum uint64
var commitHashs [][]byte
for _, v := range deposit.NewCommits {
hash, val, err := a.depositVerify(v)
if err != nil {
return nil, err
}
sum += val
commitHashs = append(commitHashs, hash)
}
//校验总存款额
if sum != deposit.Amount {
return nil, mixTy.ErrInputParaNotMatch
}
//存款
cfg := a.api.GetConfig()
accoutDb, err := createAccount(cfg, "", "", a.db)
if err != nil {
return nil, errors.Wrapf(err, "createAccount")
}
//主链上存入toAddr为mix 执行器地址,平行链上为user.p.{}.mix执行器地址,execAddr和toAddr一致
execAddr := address.ExecAddress(string(a.tx.Execer))
receipt, err := accoutDb.ExecTransfer(a.fromaddr, execAddr, execAddr, int64(deposit.Amount))
if err != nil {
return nil, errors.Wrapf(err, "ExecTransfer")
}
//push new commit to merkle tree
for _, h := range commitHashs {
rpt, err := pushTree(a.db, h)
if err != nil {
return nil, err
}
mergeReceipt(receipt, rpt)
}
return receipt, nil
}
// 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 (
"encoding/hex"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
//Exec_Commit consensus commit tx exec process
func (m *Mix) Exec_Config(payload *mixTy.MixConfigAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Config(payload)
if err != nil {
mlog.Error("mix config failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
//Exec_Deposit ...
func (m *Mix) Exec_Deposit(payload *mixTy.MixDepositAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Deposit(payload)
if err != nil {
mlog.Error("mix deposit failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
//Exec_Withdraw ...
func (m *Mix) Exec_Withdraw(payload *mixTy.MixWithdrawAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Withdraw(payload)
if err != nil {
mlog.Error("mix withdraw failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
func (m *Mix) Exec_Transfer(payload *mixTy.MixTransferAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Transfer(payload)
if err != nil {
mlog.Error("mix config failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
func (m *Mix) Exec_Authorize(payload *mixTy.MixAuthorizeAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Authorize(payload)
if err != nil {
mlog.Error("mix config failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
// 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 (
"github.com/33cn/chain33/types"
)
//ExecLocal_Config asset withdraw local db process
func (m *Mix) ExecDelLocal_Config(payload *types.AssetsWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
//ExecLocal_Deposit asset withdraw local db process
func (m *Mix) ExecDelLocal_Deposit(payload *types.AssetsWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
//ExecLocal_Withdraw asset withdraw local db process
func (m *Mix) ExecDelLocal_Withdraw(payload *types.AssetsWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
// ExecLocal_Transfer asset transfer local db process
func (m *Mix) ExecDelLocal_Transfer(payload *types.AssetsTransfer, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
//ExecLocal_Authorize asset withdraw local db process
func (m *Mix) ExecDelLocal_Authorize(payload *types.AssetsWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
// 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 (
"github.com/33cn/chain33/types"
)
//ExecLocal_Config asset withdraw local db process
func (m *Mix) ExecLocal_Config(payload *types.AssetsWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
//ExecLocal_Deposit asset withdraw local db process
func (m *Mix) ExecLocal_Deposit(payload *types.AssetsWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
//ExecLocal_Withdraw asset withdraw local db process
func (m *Mix) ExecLocal_Withdraw(payload *types.AssetsWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
// ExecLocal_Transfer asset transfer local db process
func (m *Mix) ExecLocal_Transfer(payload *types.AssetsTransfer, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
//ExecLocal_Authorize asset withdraw local db process
func (m *Mix) ExecLocal_Authorize(payload *types.AssetsWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
// 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 (
"fmt"
)
var (
verifyKeys string
authPubKeys string
commitTreeArchiveRoots string
commitTreeCurrentRoots string
commitTreeCurrentLeaves string
commitTreeRootLeaves string
authorizeHash string
authorizeSpendHash string
nullifierHash string
localTx string
localTitle string
)
func setPrefix() {
verifyKeys = "mavl-mixcoin-verify-keys-"
authPubKeys = "mavl-mixcoin-auth-pubkeys-"
commitTreeArchiveRoots = "mavl-mixcoin-commitTree-roots-archive-"
commitTreeCurrentRoots = "mavl-mixcoin-commitTree-current-roots"
commitTreeCurrentLeaves = "mavl-mixcoin-commitTree-current-leaves-"
commitTreeRootLeaves = "mavl-mixcoin-commitTree-rootLeaves-"
authorizeHash = "mavl-mixcoin-authorizeHash"
authorizeSpendHash = "mavl-mixcoin-authorizeHash-spend-"
nullifierHash = "mavl-mixcoin-nullifierHash"
}
//support multi version verify parameter setting
func getVerifyKeysKey() []byte {
return []byte(fmt.Sprintf(verifyKeys))
}
func getAuthPubKeysKey() []byte {
return []byte(fmt.Sprintf(authPubKeys))
}
func calcCommitTreeArchiveRootsKey() []byte {
return []byte(fmt.Sprintf(commitTreeArchiveRoots))
}
func calcCurrentCommitRootsKey() []byte {
return []byte(fmt.Sprintf(commitTreeCurrentRoots))
}
func calcCurrentCommitLeavesKey() []byte {
return []byte(fmt.Sprintf(commitTreeCurrentLeaves))
}
func calcCommitTreeRootLeaves(rootHash string) []byte {
return []byte(fmt.Sprintf(commitTreeRootLeaves+"s", rootHash))
}
func calcAuthorizeHashKey(hash string) []byte {
return []byte(fmt.Sprintf(authorizeHash+"%s", hash))
}
func calcAuthorizeSpendHashKey(hash string) []byte {
return []byte(fmt.Sprintf(authorizeSpendHash+"%s", hash))
}
func calcNullifierHashKey(hash string) []byte {
return []byte(fmt.Sprintf(nullifierHash+"%s", hash))
}
// 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 (
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
log "github.com/33cn/chain33/common/log/log15"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
var (
mlog = log.New("module", "execs.mix")
driverName = mixTy.MixX
)
// Mix exec
type Mix struct {
drivers.DriverBase
}
//Init paracross exec register
func Init(name string, cfg *types.Chain33Config, sub []byte) {
drivers.Register(cfg, GetName(), newMix, cfg.GetDappFork(driverName, "Enable"))
InitExecType()
setPrefix()
}
//InitExecType ...
func InitExecType() {
ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&Mix{}))
}
//GetName return paracross name
func GetName() string {
return newMix().GetName()
}
func newMix() drivers.Driver {
c := &Mix{}
c.SetChild(c)
c.SetExecutorType(types.LoadExecutorType(driverName))
return c
}
// GetDriverName return paracross driver name
func (c *Mix) GetDriverName() string {
return pt.ParaX
}
// 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 (
"encoding/hex"
"encoding/json"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gurvy/bn256/twistededwards"
"github.com/pkg/errors"
)
/*
1. verify(zk-proof)
2. check if exist in authorize pool and nullifier pool
*/
func (a *action) transferInputVerify(proof *mixTy.ZkProofInfo) (*mixTy.TransferInputPublicInput, error) {
var input mixTy.TransferInputPublicInput
data, err := hex.DecodeString(proof.PublicInput)
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)
}
err = a.spendVerify(input.TreeRootHash, input.NullifierHash, input.AuthorizeHash)
if err != nil {
return nil, err
}
err = a.zkProofVerify(proof, mixTy.VerifyType_TRANSFERINPUT)
if err != nil {
return nil, err
}
return &input, nil
}
/*
1. verify(zk-proof)
2. check if exist in authorize pool and nullifier pool
*/
func (a *action) transferOutputVerify(proof *mixTy.ZkProofInfo) (*mixTy.TransferOutputPublicInput, error) {
var input mixTy.TransferOutputPublicInput
data, err := hex.DecodeString(proof.PublicInput)
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)
}
err = a.zkProofVerify(proof, mixTy.VerifyType_TRANSFEROUTPUT)
if err != nil {
return nil, err
}
return &input, nil
}
func verifyCommitValues(inputs []*mixTy.TransferInputPublicInput, outputs []*mixTy.TransferOutputPublicInput) bool {
var inputPoints, outputPoints []*twistededwards.Point
for _, in := range inputs {
var p twistededwards.Point
p.X.SetString(in.CommitValueX)
p.Y.SetString(in.CommitValueY)
inputPoints = append(inputPoints, &p)
}
for _, out := range outputs {
var p twistededwards.Point
p.X.SetString(out.CommitValueX)
p.Y.SetString(out.CommitValueY)
outputPoints = append(outputPoints, &p)
}
var sumInput, sumOutput twistededwards.Point
for _, p := range inputPoints {
sumInput.Add(&sumInput, p)
}
for _, p := range outputPoints {
sumOutput.Add(&sumOutput, p)
}
if sumInput.X.Equal(&sumOutput.X) && sumInput.Y.Equal(&sumOutput.Y) {
return true
}
return false
}
/*
1. verify(zk-proof, sum value of spend and new commits)
2. check if exist in authorize pool and nullifier pool
3. add nullifier to pool
*/
func (a *action) Transfer(transfer *mixTy.MixTransferAction) (*types.Receipt, error) {
var inputs []*mixTy.TransferInputPublicInput
var outputs []*mixTy.TransferOutputPublicInput
for _, k := range transfer.Input {
in, err := a.transferInputVerify(k)
if err != nil {
return nil, err
}
inputs = append(inputs, in)
}
for _, k := range transfer.Output {
out, err := a.transferOutputVerify(k)
if err != nil {
return nil, err
}
outputs = append(outputs, out)
}
if !verifyCommitValues(inputs, outputs) {
return nil, errors.Wrap(mixTy.ErrSpendInOutValueNotMatch, "verifyValue")
}
receipt := &types.Receipt{Ty: types.ExecOk}
//set nullifier
for _, k := range inputs {
r := makeNullifierSetReceipt(k.NullifierHash, &mixTy.ExistValue{Data: true})
mergeReceipt(receipt, r)
}
//push new commit to merkle tree
for _, h := range outputs {
rpt, err := pushTree(a.db, h.NodeHash)
if err != nil {
return nil, err
}
mergeReceipt(receipt, rpt)
}
return receipt, nil
}
// 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 (
"testing"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/stretchr/testify/assert"
)
func TestVerifyCommitValues(t *testing.T) {
input1 := &mixTy.TransferInputPublicInput{
CommitValueX: "8728367628344135467582547753719073727968275979035063555332785894244029982715",
CommitValueY: "8834462946188529904793384347374734779374831553974460136522409595751449858199",
}
input2 := &mixTy.TransferInputPublicInput{
CommitValueX: "9560056125663567360314373555170485462871740364163814576088225107862234393497",
CommitValueY: "13024071698463677601393829581435828705327146000694268918451707151508990195684",
}
var inputs []*mixTy.TransferInputPublicInput
inputs = append(inputs, input1)
inputs = append(inputs, input2)
output1 := &mixTy.TransferOutputPublicInput{
CommitValueX: "8728367628344135467582547753719073727968275979035063555332785894244029982715",
CommitValueY: "8834462946188529904793384347374734779374831553974460136522409595751449858199",
}
var outputs []*mixTy.TransferOutputPublicInput
outputs = append(outputs, output1)
ret := verifyCommitValues(inputs, outputs)
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 (
"encoding/hex"
"encoding/json"
"strconv"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
func (a *action) spendVerify(treeRootHash, nulliferHash, authorizeHash []byte) error {
//zk-proof校验
//check tree rootHash exist
if !checkTreeRootHashExist(a.db, treeRootHash) {
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", common.ToHex(treeRootHash))
}
//nullifier should not exist
nullifierKey := calcNullifierHashKey(common.ToHex(nulliferHash))
_, err := a.db.Get(nullifierKey)
if err == nil {
return errors.Wrapf(mixTy.ErrNulliferHashExist, "nullifier=%s", common.ToHex(nulliferHash))
}
if !isNotFound(err) {
return errors.Wrapf(err, "nullifier=%s", common.ToHex(nulliferHash))
}
// authorize should exist if needed
if len(authorizeHash) > 0 {
authKey := calcAuthorizeHashKey(common.ToHex(authorizeHash))
_, err = a.db.Get(authKey)
if err != nil {
return errors.Wrapf(err, "authorize=%s", common.ToHex(authorizeHash))
}
}
return nil
}
func (a *action) withdrawVerify(proof *mixTy.ZkProofInfo) ([]byte, uint64, error) {
var input mixTy.WithdrawPublicInput
data, err := hex.DecodeString(proof.PublicInput)
if err != nil {
return nil, 0, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
err = json.Unmarshal(data, &input)
if err != nil {
return nil, 0, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput)
}
val, err := strconv.ParseUint(input.Amount, 10, 64)
if err != nil {
return nil, 0, errors.Wrapf(err, "parseUint=%s", input.Amount)
}
err = a.spendVerify(input.TreeRootHash, input.NullifierHash, input.AuthorizeHash)
if err != nil {
return nil, 0, err
}
err = a.zkProofVerify(proof, mixTy.VerifyType_WITHDRAW)
if err != nil {
return nil, 0, err
}
return input.NullifierHash, val, nil
}
/*
1. verify(zk-proof, sum commit value)
2. withdraw from mix contract
3. set nullifier exist
*/
func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, error) {
var nulliferSet [][]byte
var sumValue uint64
for _, k := range withdraw.SpendCommits {
nulfier, v, err := a.withdrawVerify(k)
if err != nil {
return nil, err
}
sumValue += v
nulliferSet = append(nulliferSet, nulfier)
}
if sumValue != withdraw.Amount {
return nil, mixTy.ErrInputParaNotMatch
}
//withdraw value
cfg := a.api.GetConfig()
accoutDb, err := createAccount(cfg, "", "", a.db)
if err != nil {
return nil, err
}
//主链上存入toAddr为mix 执行器地址,平行链上为user.p.{}.mix执行器地址,execAddr和toAddr一致
execAddr := address.ExecAddress(string(a.tx.Execer))
receipt, err := accoutDb.ExecTransfer(execAddr, a.fromaddr, execAddr, int64(withdraw.Amount))
if err != nil {
return nil, err
}
//set nullifier
for _, k := range nulliferSet {
r := makeNullifierSetReceipt(k, &mixTy.ExistValue{Data: true})
mergeReceipt(receipt, r)
}
return receipt, 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 zksnark
import (
"bytes"
"encoding/hex"
"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/pkg/errors"
)
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 deserializeInput(input string) (map[string]interface{}, error) {
buff, err := getByteBuff(input)
if err != nil {
return nil, err
}
decoder := json.NewDecoder(buff)
toRead := make(map[string]interface{})
if err := decoder.Decode(&toRead); err != nil {
return nil, errors.Wrapf(err, "deserializeInput %s", input)
}
return toRead, nil
}
func Verify(verifyKeyStr, proofStr, pubInputStr string) (bool, error) {
curveID := gurvy.BN256
output, err := getByteBuff(verifyKeyStr)
if err != nil {
return false, errors.Wrapf(err, "zk.verify")
}
var vk groth16_bn256.VerifyingKey
if err := gob.Deserialize(output, &vk, curveID); err != nil {
return false, errors.Wrapf(err, "zk.verify.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 = getByteBuff(proofStr)
if err != nil {
return false, errors.Wrapf(err, "proof")
}
var proof groth16_bn256.Proof
if err := gob.Deserialize(output, &proof, curveID); err != nil {
return false, errors.Wrapf(err, "zk.verify.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, "zk.Verify")
}
return result, nil
}
// 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 zksnark
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestVerify(t *testing.T) {
verifyKey := "1f8b08000000000000ff6c517b4c937714fdddf6536116149022a8a3bc9c1544a84a1086c8a3b85a278ac1c7b0bc6ba90386b41511910928e5fdb43a3543610c5164109c5a37314689c4218e1158650a5b47c4884e05991714bea51fe292657f9dfc7ef7dc7bceb9973d93b003e8436c00ce5669b27c57aa3c512696a6029d49800210029d4d80b54e00748101dd812e21c0d9a48a8e97c7881293544a05d01a42881d9dc506604bdd05531dc00a7003fa08015680bb010959421f6603b0a41ecc371b58fe6e40ab09b0fcdddfa1c08084f0e81c862898fa06969f1bd07904587eee0624c48ace058059c27869823451c9d466821121523a9f0de0ad5026ab6294bc34debaa88484a88d52192f3a51b0cac3759dc06fd72e79a2d49b17288d57fe4f81973e95128ca63b812e2260344d37bc0871a40bd90046d34d0c8505b09d710b3ba63208e86236c0a2f756c4bc30c93b31f77fc54a08008018e80a42882d5dce0298fb5f9ea108749941b794d17dff5f36ad9b37a56b580d973eca02300a932894c9f24499e136c0216492dd4a671ab4286c53bcacf11bbf7402b5c8b1bf38b157895983a14badf436e9c8d56dc9dfe3dad50814a6d7465af46d1d6b46fd8f631e51dd8a6eb475a914b4da44f4e0acc7cd8e23034b55c4308d2babfdeb79a64316aa3afbefa83fffec28b6b9253b4ddcb694e3f23f4bbe7f312af1040a858bf5837e5b9e05a1282d29b377c53e37bcdddfbda2ddab2d16cd35f10feecf7bb29999569bab1f14cb1a8250f1ddf15e9de3ad37b87afdd5868ad50331b85055de2adb861140a1f596a37d73bcc79d715fc3b5039dbf695c50af9eedefebba488d0b9d87d7ea0fdeb22184c99a127c5912ee59c147a37dc4f711e78c1faa95675b3571bbbdd0aee297932e21c72e00858f46474da21b440118776a81e92585731c66151c08af3a625f8f1f5856342a0e167833ee62ed33124b7d9bae628d71dcf84513761e0ee51e5e3522d18ee1525d7fd34a21270b282c7ec9bd32af3af62966fadc0968896d7f831da27a0f9c61721a3979e79dd76ed85dcb4c8b793b5278236d38199f8d17a55766478e608ac7b9a61b55430a9cbb725b7647df09c31d2e3717efecfd4317832b1af4c1d5b2949ff1a979a5981f91148a663ec3f9658157761026ac617b7dfc21e31f469e63ca3703ed3983ca5ff1edf916cfbfcd343bd03498fbed3dd18510a0f06e58754fd7ecb4e5c8ad5bbfeac927ea022c4f900f08db8aacd179a2382092bb7f82f1b75db24cad0d71f0c20f87261cc336a51aa36bf3ab84cc25cd34f2e77c35daf8f6740350d885d228301eeec19b35053e2b2d861ad1f361e30bfe0d311f4dc7b5f7be36b33ff4ee167517ebfcc54109f7b163f9c2f98bae0b63519dbdc6f59497d923345fd3e1131aedd70214d2faf0979ffaabcab0c3a92ff4ead90336585d3e1974f96cc831b4a56d23afb53d2c63dcd5db25f10ba1528fbd5d15ca8e415e2796f0ac449a1289095a65e8acf78449cf0185339b1c6c3c4c1d6c5113d9fe65a05a721c4fd66ff5dfe9fdc065cce3f8e6ebc67539ccf2584061a9aea78aeff97b2796b6cdcfe8945adc43575fdd82bb65af65386372e7fec843a79d80c2d541813f6d0a1bbf8939cbae770657a92cf1c45e4e8b57ef17f968fdf1f90bb1c9dc3b04288cef1739693ff2a731f3f5e35ccbf4c200bcbbf95542c46bef545cbc41606773b3520b1456172936a64cca2dd06e8e437dcb68773876d5f4cfc88834f34273f119b714edc33442806514bc5118b14d14228454f24f000000ffffd7ca51e5ae050000"
pubInput := "7b2279223a223335227d0a"
proof := "1f8b08000000000000ff62666360d6f9dfc8ccc8c81a50949f9fc6f8bf8981919991c9b188f17f0b0323b377513198c1e454ccf8bf83818141e57f3333232387bba1635a5a665e2a4492913182f17f1b0323632488626010ffdfcac8c8c8ee9a939a9b9a5702966263e400696e076b368269ee8069ee8268ee62606050f8dfc9ccc8c8946a04166562647234009bc0e4680831fd1fa3edff264646961ff2dac6726f5e0770fdd87d50ae413cc4a0fe87884ade7de7bfdd0b7eb0cdb27dd07755c99691e5879fb6c43f4b39a7a93fda32c5ae1c3d3cf5d28f79f35d4d3e955999fee099f6694e45d40e65069069468dd1b6cb04f3847ffc4ff8e2753ff3a2e48f77f24b59ff96d69df921b371399fffd5f5bf19597e249ebdf6e77fd444f71f079466ad774ef3abfe71a07bdd077ed695e13fe46ebe9e6ba4bb51888111645cd4abcfee7d2a26277fdc0a3d533b695a8bcc0faffdbcb71c4d3fb8fd50ac280dd7b253bbc2c8f26375a28ed446a98fb77f1cf8735e594cfbefff1feebdbbd25317759ef9211221d33433eb7c33d87147ef898b06a44ebffaa3227cdd5fddedaf56ff5860397f86c0559f673f647be744dc5fa6f49891e5475335e7a317d32df87e1c2f3f7352ef5339cb8f2dd11ffeff09ebbcf7437ff6e6873f8fa96c64606000040000ffff023acbaff4010000"
rst, err := Verify(verifyKey, proof, pubInput)
assert.Nil(t, err)
assert.Equal(t, true, rst)
}
//
//func TestDeserializeWitness(t *testing.T) {
// //str := "7b0a202020202259223a202230783233222c0a202020202278223a202230783033220a7d0a"
// str := "7b22636d7468617368223a2230393265613834303464323431303566326263616638616132656365633239626230303039353965376137313433393539663465623638373232656531653765222c22636d7476616c756578223a2231663235383330333630353866613432376338346364663264303361666234363233623361376566313365366637653465656239663762316335666563326463222c22636d7476616c756579223a2232313639663266626634623839653431343631643734326430373036663362313137643761613531376663313164333261336563313765666664346638336137222c22636f6d6d69745f72616e646f6d223a226138353566323233222c2268656c70657231223a223031222c2268656c70657232223a223031222c2268656c70657233223a223031222c2268656c70657234223a223031222c2268656c70657235223a223031222c227061746830223a2231653434633733626137393830623034353061386539393763396439633738626535613964376365616635393764663738313436396131633964623465346339222c227061746831223a2231393161383065333737616639653064303465316437356538643730326434633264623231623935326239666666366263636133316639653966643564653030222c227061746832223a2232323064633230343161386338313038366139626338303834653766396565303738386165326338623739323865306232653236373233333962323933336233222c227061746833223a2232393564363331666366306564306433343734326163353630666537613063303538353232356366663931393438303664346439643865316630306531373437222c227061746834223a2232313538343961643762643433343461383037663466306339616566643231333135373265336362323161386232316161393665386131316334613231346535222c227061746835223a22222c227072696b6579223a2232613831613633623731616534383132343836396661316537363664643637633164336236383431653561646132643362623831326661303432363730313733222c227075626b6579223a2231356639646364656362396432623963323635643936376534623135363532636564393862663530303566646236623562333030626630376335303666386239222c22726f6f7468617368223a2232616665613563323866373631663432663335636361343731313730636130373263626534623639623662313863346133623435363337653937343738336334222c227472616e736665725f72616e646f6d223a223233222c227472616e736665725f76616c7565223a223031616566303830222c2276616c696430223a223031222c2276616c696431223a223031222c2276616c696432223a223031222c2276616c696433223a223031222c2276616c696434223a223031222c2276616c696435223a22222c2276616c7565223a2233306537227d0a"
// res, _ := hex.DecodeString(str)
// var buf bytes.Buffer
// buf.Write(res)
// decoder := json.NewDecoder(&buf)
//
// var ss mixTy.TestMsg2
//
// if err := decoder.Decode(&ss); err != nil {
// panic(err)
// }
// val, _ := hex.DecodeString(ss.Cmthash)
// var a big.Int
// a.SetBytes(val)
// fmt.Println("cmthash=", ss.Cmthash, "val=", a.String(), "v=", a)
// fmt.Println("cmtvaluex=", ss.Cmtvaluex)
// fmt.Println("y=", ss.Cmtvaluey)
// fmt.Println("roothash", ss.Roothash)
// //v,err := strconv.ParseInt(ss.Value,16,0)
// b, err := new(big.Int).SetString(ss.Value, 16)
// fmt.Println("erri", err)
// fmt.Println("value", ss.Value, "atoi", b)
//
//}
//
//func TestDeserial(t *testing.T) {
// val := make(map[string]interface{})
// val["cmthash"] = "1"
// hash := "0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4"
// hashb, _ := hex.DecodeString(hash[2:])
// val["value"] = hashb
//
// res, err := json.Marshal(val)
// assert.Nil(t, err)
// str := hex.EncodeToString(res)
// fmt.Println("res", string(res), "str", str)
//
// str2, _ := hex.DecodeString(str)
// var msg mixTy.TestMsg3
// json.Unmarshal(str2, &msg)
// fmt.Println("msg", msg.Cmthash, "val", hex.EncodeToString(msg.Value))
//
// val2 := make(map[string]interface{})
// var buff2 bytes.Buffer
// buff2.Write(str2)
// decode := json.NewDecoder(&buff2)
// err = decode.Decode(&val2)
// assert.Nil(t, err)
// for k, v := range val2 {
// fmt.Println("k=", k, "v=", v)
// }
//
//}
func TestDeserial(t *testing.T) {
val := make(map[string]interface{})
val["cmthash"] = "1"
hash := "0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4"
hashb, _ := hex.DecodeString(hash[2:])
val["value"] = hashb
var buf bytes.Buffer
encode := json.NewEncoder(&buf)
err := encode.Encode(val)
assert.Nil(t, err)
enstr := hex.EncodeToString(buf.Bytes())
fmt.Println("encode", enstr)
enbuff, _ := hex.DecodeString(enstr)
var buff2 bytes.Buffer
buff2.Write(enbuff)
decode := json.NewDecoder(&buff2)
val2 := make(map[string]interface{})
err = decode.Decode(&val2)
assert.Nil(t, err)
for k, v := range val2 {
fmt.Println("k=", k, "v=", v)
}
}
// 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 paracross
import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/mix/commands"
"github.com/33cn/plugin/plugin/dapp/mix/executor"
"github.com/33cn/plugin/plugin/dapp/mix/types"
_ "github.com/33cn/plugin/plugin/dapp/paracross/wallet" // register wallet package
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: types.MixX,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.ParcCmd,
})
}
all:
sh ./create_protobuf.sh
#!/bin/sh
chain33_path=$(go list -f '{{.Dir}}' "github.com/33cn/chain33")
protoc --go_out=plugins=grpc:../types ./*.proto --proto_path=. --proto_path="${chain33_path}/types/proto/"
syntax = "proto3";
package types;
//区分不同的验证电路
enum VerifyType{
DEPOSIT = 0;
WITHDRAW = 1;
TRANSFERINPUT = 2;
TRANSFEROUTPUT = 3;
AUTHORIZE = 4;
}
//区分zk 所选取的曲线,需要和gnark保持一致
enum ZkCurveId{
UNKNOWN = 0;
BLS377 = 1;
BLS381 = 2;
BN256 = 3;
}
message ZkVerifyKey {
ZkCurveId curveId = 1;
VerifyType type = 2;
string value = 3;
}
message ZkVerifyKeys{
repeated ZkVerifyKey data = 1;
}
message AuthPubKeys{
repeated string data = 1;
}
enum MixConfigType{
VerifyKey = 0;
AuthPubKey = 1;
}
enum MixConfigAct{
Add = 0;
Delete = 1;
}
message AuthorizePubKey {
string value = 3;
}
//config verify parameter for proof
message MixConfigAction {
MixConfigType Ty = 1;
MixConfigAct Action = 2;
oneof value {
ZkVerifyKey verifyKey = 3;
AuthorizePubKey authKey = 4;
}
}
message ZkProofInfo {
string proof = 1;
string publicInput = 2;
}
message MixDepositAction {
uint64 amount = 1;
repeated ZkProofInfo newCommits = 2;
}
message MixTransferAction {
repeated ZkProofInfo input = 1;
repeated ZkProofInfo output = 2;
}
message MixWithdrawAction {
uint64 amount = 1;
repeated ZkProofInfo spendCommits = 2;
}
message MixAuthorizeAction {
repeated ZkProofInfo authCommits = 1;
}
message MixAction {
int32 ty = 1;
oneof value {
MixConfigAction config = 2;
MixDepositAction deposit = 3;
MixWithdrawAction withdraw = 4;
MixTransferAction transfer = 5;
MixAuthorizeAction authorize = 6;
}
}
message DepositPublicInput {
bytes nodeHash = 1;
string amount = 2;
}
message WithdrawPublicInput {
bytes treeRootHash = 1;
bytes nullifierHash = 2;
bytes authorizeHash = 3;
string amount = 4;
}
message TransferInputPublicInput {
bytes treeRootHash = 1;
string commitValueX = 2;
string commitValueY = 3;
bytes authorizeHash = 4;
bytes nullifierHash = 5;
}
message TransferOutputPublicInput {
bytes nodeHash = 1;
string commitValueX = 2;
string commitValueY = 3;
}
message AuthorizePublicInput {
bytes treeRootHash = 1;
string authorizePubKey = 2;
bytes authorizeHash = 3;
bytes authorizeSpendHash = 4;
}
message ExistValue {
bool data = 1;
}
message CommitTreeLeaves {
repeated bytes data = 1;
}
message CommitTreeRoots {
repeated bytes data = 1;
}
message CommitTreeProve {
string rootHash = 1;
repeated string proofSet = 2;
uint32 proofIndex = 3;
uint32 numLeaves = 4;
}
// 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 types
import "errors"
var (
// ErrZkVerifyFail zk verify fail
ErrZkVerifyFail = errors.New("ErrZkVerifyFail")
//ErrInputParaNotMatch input paras not match
ErrInputParaNotMatch = errors.New("ErrInputParaNotMatch")
//ErrLeafNotFound not found leaf
ErrLeafNotFound = errors.New("ErrLeafNotFound")
//ErrTreeRootHashNotFound not found leaf
ErrTreeRootHashNotFound = errors.New("ErrTreeRootHashNotFound")
//ErrNulliferHashExist exist
ErrNulliferHashExist = errors.New("ErrNulliferHashExist")
//ErrAuthorizeHashExist exist
ErrAuthorizeHashExist = errors.New("ErrAuthorizeHashExist")
//ErrSpendInOutValueNotMatch spend input and output value not match
ErrSpendInOutValueNotMatch = errors.New("ErrSpendInOutValueNotMatch")
)
// 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 types
import "github.com/33cn/chain33/common/log/log15"
var tlog = log15.New("module", MixX)
const (
MaxTreeLeaves = 1024
)
// 执行器的日志类型
const (
// TyLogParacrossCommit commit log key
TyLogMixDeposit = 750
TyLogMixWithdraw = 751
TyLogMixTransfer = 752
TyLogMixAuth = 753
TyLogMixConfigVk = 754
TyLogMixConfigAuth = 755
TyLogCurrentCommitTreeLeaves = 756
TyLogCurrentCommitTreeRoots = 756
TyLogCommitTreeRootLeaves = 757
TyLogCommitTreeArchiveRoots = 758
TyLogNulliferSet = 759
TyLogAuthorizeSet = 760
TyLogAuthorizeSpendSet = 761
)
//action type
const (
MixActionConfig = iota
MixActionDeposit
MixActionWithdraw
MixActionTransfer
MixActionAuth
)
This diff is collapsed.
// 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 types
import (
"reflect"
log "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
var (
// ParaX paracross exec name
MixX = "mix"
glog = log.New("module", MixX)
)
func init() {
// init executor type
types.AllowUserExec = append(types.AllowUserExec, []byte(MixX))
types.RegFork(MixX, InitFork)
types.RegExec(MixX, InitExecutor)
}
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(MixX, "Enable", 0)
}
//InitExecutor ...
func InitExecutor(cfg *types.Chain33Config) {
types.RegistorExecutor(MixX, NewType(cfg))
}
// GetExecName get para exec name
func GetExecName(cfg *types.Chain33Config) string {
return cfg.ExecName(MixX)
}
// ParacrossType base paracross type
type MixType struct {
types.ExecTypeBase
}
// NewType get paracross type
func NewType(cfg *types.Chain33Config) *MixType {
c := &MixType{}
c.SetChild(c)
c.SetConfig(cfg)
return c
}
// GetName 获取执行器名称
func (p *MixType) GetName() string {
return MixX
}
// GetLogMap get receipt log map
func (p *MixType) GetLogMap() map[int64]*types.LogInfo {
return map[int64]*types.LogInfo{
TyLogMixConfigVk: {Ty: reflect.TypeOf(ZkVerifyKeys{}), Name: "LogMixConfigVk"},
TyLogMixConfigAuth: {Ty: reflect.TypeOf(AuthPubKeys{}), Name: "LogMixConfigAuthPubKey"},
}
}
// GetTypeMap get action type
func (p *MixType) GetTypeMap() map[string]int32 {
return map[string]int32{
"Config": MixActionConfig,
"Deposit": MixActionDeposit,
"Withdraw": MixActionWithdraw,
"Transfer": MixActionTransfer,
"Authorize": MixActionAuth,
}
}
// GetPayload mix get action payload
func (p *MixType) GetPayload() types.Message {
return &MixAction{}
}
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