Commit 9ff24cd5 authored by madengji's avatar madengji Committed by vipwzw

add merkle tree

parent 0baa7ba6
...@@ -45,8 +45,6 @@ func TestTransferOutput(t *testing.T) { ...@@ -45,8 +45,6 @@ func TestTransferOutput(t *testing.T) {
good.Assign(backend.Secret, "noteRandom", "2824204835") good.Assign(backend.Secret, "noteRandom", "2824204835")
good.Assign(backend.Secret, "noteHash", "16308793397024662832064523892418908145900866571524124093537199035808550255649")
assert.Solved(&r1csBN256, good, nil) assert.Solved(&r1csBN256, good, nil)
} }
......
public, treeRootHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4 public, treeRootHash,10531321614990797034921282585661869614556487056951485265320464926630499341310
public, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 public, authorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
public, authorizeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4 public, authorizeHash,1267825436937766239630340333349685320927256968591056373125946583184548355070
public, authorizeSpendHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4 public, authorizeSpendHash,14468512365438613046028281588661351435476168610934165547900473609197783547663
secret, spendAmount,28242048 secret, spendAmount,28242048
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, spendPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, returnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, authorizePriKey,17822967620457187568904804290291537271142779717280482398091401115827760898835
secret, authorizePriKey,19226210204356004706765360050059680583735587569269469539941275797408975356275 secret, spendFlag,1
secret, spendFlag,0 secret, noteRandom,2824204835
secret, noteRandom,28242048
secret, path1,19561523370160677851616596032513161448778901506614020103852017946679781620105
secret, path0,1e44c73ba7980b0450a8e997c9d9c78be5a9d7ceaf597df781469a1c9db4e4c9 secret, path2,13898857070666440684265042188056372750257678232709763835292910585848522658637
secret, path1,191a80e377af9e0d04e1d75e8d702d4c2db21b952b9fff6bcca31f9e9fd5de00 secret, path3,15019169196974879571470243100379529757970866395477207575033769902587972032431
secret, path2,220dc2041a8c81086a9bc8084e7f9ee0788ae2c8b7928e0b2e2672339b2933b3 secret, path4,0
secret, path3,295d631fcf0ed0d34742ac560fe7a0c0585225cff9194806d4d9d8e1f00e1747
secret, path4,215849ad7bd4344a807f4f0c9aefd2131572e3cb21a8b21aa96e8a11c4a214e5
secret, path5,0 secret, path5,0
secret, path6,0 secret, path6,0
secret, path7,0 secret, path7,0
...@@ -36,11 +34,10 @@ secret, helper9,1 ...@@ -36,11 +34,10 @@ secret, helper9,1
secret, helper10,1 secret, helper10,1
secret, valid0,1
secret, valid1,1 secret, valid1,1
secret, valid2,1 secret, valid2,1
secret, valid3,1 secret, valid3,1
secret, valid4,1 secret, valid4,0
secret, valid5,0 secret, valid5,0
secret, valid6,0 secret, valid6,0
secret, valid7,0 secret, valid7,0
......
public, nodeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4 public, nodeHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
public, amount,1000 public, amount,28242048
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, spendPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, returnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, authorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
secret, noteRandom,28242048 secret, noteRandom,2824204835
......
...@@ -14,8 +14,8 @@ secret, spendPriKey,101904778353009275576499342388203605294586816720738661162328 ...@@ -14,8 +14,8 @@ secret, spendPriKey,101904778353009275576499342388203605294586816720738661162328
secret, spendFlag,1 secret, spendFlag,1
secret, authorizeFlag,1 secret, authorizeFlag,1
secret, noteRandom,2824204835 secret, noteRandom,2824204835
secret, noteHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
secret, noteHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
secret, path1,19561523370160677851616596032513161448778901506614020103852017946679781620105 secret, path1,19561523370160677851616596032513161448778901506614020103852017946679781620105
secret, path2,13898857070666440684265042188056372750257678232709763835292910585848522658637 secret, path2,13898857070666440684265042188056372750257678232709763835292910585848522658637
secret, path3,15019169196974879571470243100379529757970866395477207575033769902587972032431 secret, path3,15019169196974879571470243100379529757970866395477207575033769902587972032431
......
public, commitValueX,9940039130125917226477779823200431190767730273667531970219395440191717439673 public, commitValueX,14087975867275911077371231345227824611951436822132762463787130558957838320348
public, commitValueY,9940039130125917226477779823200431190767730273667531970219395440191717439673 public, commitValueY,15113519960384204624879642069520481336224311978035289236693658603675385299879
public, nodeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4 public, nodeHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
secret, spendAmount,28242048 secret, spendAmount,28242048
secret, spendRandom,28242048 secret, spendRandom,35
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, spendPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, returnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, authorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
secret, noteRandom,28242048 secret, noteRandom,2824204835
public, treeRootHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4 public, treeRootHash,10531321614990797034921282585661869614556487056951485265320464926630499341310
public, authorizeHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4 public, authorizeSpendHash,14468512365438613046028281588661351435476168610934165547900473609197783547663
public, nullifierHash,0x2afea5c28f761f42f35cca471170ca072cbe4b69b6b18c4a3b45637e974783c4 public, nullifierHash,6747518781649068310795677405858353007442326529625450860668944156162052335195
public, amount,28242048 public, amount,28242048
secret, spendPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, spendPubKey,13735985067536865723202617343666111332145536963656464451727087263423649028705
secret, returnPubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, returnPubKey,16067249407809359746114321133992130903102335882983385972747813693681808870497
secret, authorizePubKey,9940039130125917226477779823200431190767730273667531970219395440191717439673 secret, authorizePubKey,13519883267141251871527102103999205179714486518503885909948192364772977661583
secret, spendPriKey,19226210204356004706765360050059680583735587569269469539941275797408975356275 secret, spendPriKey,10190477835300927557649934238820360529458681672073866116232821892325659279502
secret, spendFlag,0 secret, spendFlag,1
secret, authorizeFlag,0 secret, authorizeFlag,1
secret, noteRandom,28242048 secret, noteRandom,2824204835
secret, path0,1e44c73ba7980b0450a8e997c9d9c78be5a9d7ceaf597df781469a1c9db4e4c9 secret, noteHash,16308793397024662832064523892418908145900866571524124093537199035808550255649
secret, path1,191a80e377af9e0d04e1d75e8d702d4c2db21b952b9fff6bcca31f9e9fd5de00 secret, path1,19561523370160677851616596032513161448778901506614020103852017946679781620105
secret, path2,220dc2041a8c81086a9bc8084e7f9ee0788ae2c8b7928e0b2e2672339b2933b3 secret, path2,13898857070666440684265042188056372750257678232709763835292910585848522658637
secret, path3,295d631fcf0ed0d34742ac560fe7a0c0585225cff9194806d4d9d8e1f00e1747 secret, path3,15019169196974879571470243100379529757970866395477207575033769902587972032431
secret, path4,215849ad7bd4344a807f4f0c9aefd2131572e3cb21a8b21aa96e8a11c4a214e5 secret, path4,0
secret, path5,0 secret, path5,0
secret, path6,0 secret, path6,0
secret, path7,0 secret, path7,0
...@@ -33,19 +33,17 @@ secret, helper6,1 ...@@ -33,19 +33,17 @@ secret, helper6,1
secret, helper7,1 secret, helper7,1
secret, helper8,1 secret, helper8,1
secret, helper9,1 secret, helper9,1
secret, helper10,1
secret, valid0,1
secret, valid1,1 secret, valid1,1
secret, valid2,1 secret, valid2,1
secret, valid3,1 secret, valid3,1
secret, valid4,1 secret, valid4,0
secret, valid5,0 secret, valid5,0
secret, valid6,0 secret, valid6,0
secret, valid7,0 secret, valid7,0
secret, valid8,0 secret, valid8,0
secret, valid9,0 secret, valid9,0
secret, valid10,0
...@@ -7,6 +7,7 @@ package executor ...@@ -7,6 +7,7 @@ package executor
import ( import (
"github.com/33cn/chain33/account" "github.com/33cn/chain33/account"
"github.com/33cn/chain33/client" "github.com/33cn/chain33/client"
"github.com/consensys/gurvy/bn256/fr"
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/system/dapp" "github.com/33cn/chain33/system/dapp"
...@@ -79,3 +80,15 @@ func makeReceipt(key []byte, logTy int32, data proto.Message) *types.Receipt { ...@@ -79,3 +80,15 @@ func makeReceipt(key []byte, logTy int32, data proto.Message) *types.Receipt {
}, },
} }
} }
func transferFr2Bytes(v string) []byte {
var leaf fr.Element
leaf.SetString(v)
return leaf.Bytes()
}
func transferFr2String(val []byte) string {
var leaf fr.Element
leaf.SetBytes(val)
return leaf.String()
}
...@@ -8,8 +8,6 @@ import ( ...@@ -8,8 +8,6 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types" mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
...@@ -19,18 +17,18 @@ import ( ...@@ -19,18 +17,18 @@ import (
func (a *action) authParamCheck(input *mixTy.AuthorizePublicInput) error { func (a *action) authParamCheck(input *mixTy.AuthorizePublicInput) error {
//check tree rootHash exist //check tree rootHash exist
if !checkTreeRootHashExist(a.db, input.TreeRootHash) { if !checkTreeRootHashExist(a.db, transferFr2Bytes(input.TreeRootHash)) {
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", common.ToHex(input.TreeRootHash)) return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", input.TreeRootHash)
} }
//authorize key should not exist //authorize key should not exist
authKey := calcAuthorizeHashKey(common.ToHex(input.AuthorizeHash)) authKey := calcAuthorizeHashKey(input.AuthorizeHash)
_, err := a.db.Get(authKey) _, err := a.db.Get(authKey)
if err == nil { if err == nil {
return errors.Wrapf(mixTy.ErrAuthorizeHashExist, "auth=%s", common.ToHex(input.AuthorizeHash)) return errors.Wrapf(mixTy.ErrAuthorizeHashExist, "auth=%s", input.AuthorizeHash)
} }
if !isNotFound(err) { if !isNotFound(err) {
return errors.Wrapf(err, "auth=%s", common.ToHex(input.AuthorizeHash)) return errors.Wrapf(err, "auth=%s", input.AuthorizeHash)
} }
authPubKeys, err := a.getAuthKeys() authPubKeys, err := a.getAuthKeys()
...@@ -97,9 +95,9 @@ func (a *action) Authorize(authorize *mixTy.MixAuthorizeAction) (*types.Receipt, ...@@ -97,9 +95,9 @@ func (a *action) Authorize(authorize *mixTy.MixAuthorizeAction) (*types.Receipt,
receipt := &types.Receipt{Ty: types.ExecOk} receipt := &types.Receipt{Ty: types.ExecOk}
for _, in := range inputs { for _, in := range inputs {
r := makeReceipt(calcAuthorizeHashKey(common.ToHex(in.AuthorizeHash)), mixTy.TyLogAuthorizeSet, &mixTy.ExistValue{Data: true}) r := makeReceipt(calcAuthorizeHashKey(in.AuthorizeHash), mixTy.TyLogAuthorizeSet, &mixTy.ExistValue{Data: true})
mergeReceipt(receipt, r) mergeReceipt(receipt, r)
r = makeReceipt(calcAuthorizeSpendHashKey(common.ToHex(in.AuthorizeSpendHash)), mixTy.TyLogAuthorizeSpendSet, &mixTy.ExistValue{Data: true}) r = makeReceipt(calcAuthorizeSpendHashKey(in.AuthorizeSpendHash), mixTy.TyLogAuthorizeSpendSet, &mixTy.ExistValue{Data: true})
mergeReceipt(receipt, r) mergeReceipt(receipt, r)
} }
......
...@@ -6,28 +6,17 @@ package executor ...@@ -6,28 +6,17 @@ package executor
import ( import (
"bytes" "bytes"
"strconv"
"strings"
"github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/mix/executor/merkletree"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types" mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/NebulousLabs/merkletree"
"github.com/consensys/gnark/crypto/hash/mimc/bn256" "github.com/consensys/gnark/crypto/hash/mimc/bn256"
"github.com/pkg/errors" "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 { func makeTreeLeavesReceipt(data *mixTy.CommitTreeLeaves) *types.Receipt {
return makeReceipt(calcCurrentCommitLeavesKey(), mixTy.TyLogCurrentCommitTreeLeaves, data) return makeReceipt(calcCurrentCommitLeavesKey(), mixTy.TyLogCurrentCommitTreeLeaves, data)
} }
...@@ -42,8 +31,8 @@ func makeCurrentTreeReceipt(leaves *mixTy.CommitTreeLeaves, roots *mixTy.CommitT ...@@ -42,8 +31,8 @@ func makeCurrentTreeReceipt(leaves *mixTy.CommitTreeLeaves, roots *mixTy.CommitT
return mergeReceipt(r1, r2) return mergeReceipt(r1, r2)
} }
func makeTreeRootLeavesReceipt(root []byte, data *mixTy.CommitTreeLeaves) *types.Receipt { func makeTreeRootLeavesReceipt(root string, data *mixTy.CommitTreeLeaves) *types.Receipt {
return makeReceipt(calcCommitTreeRootLeaves(common.ToHex(root)), mixTy.TyLogCommitTreeRootLeaves, data) return makeReceipt(calcCommitTreeRootLeaves(root), mixTy.TyLogCommitTreeRootLeaves, data)
} }
func makeTreeArchiveRootsReceipt(data *mixTy.CommitTreeRoots) *types.Receipt { func makeTreeArchiveRootsReceipt(data *mixTy.CommitTreeRoots) *types.Receipt {
...@@ -68,8 +57,8 @@ func getCurrentCommitTreeLeaves(db dbm.KV) (*mixTy.CommitTreeLeaves, error) { ...@@ -68,8 +57,8 @@ func getCurrentCommitTreeLeaves(db dbm.KV) (*mixTy.CommitTreeLeaves, error) {
return getCommitLeaves(db, calcCurrentCommitLeavesKey()) return getCommitLeaves(db, calcCurrentCommitLeavesKey())
} }
func getCommitRootLeaves(db dbm.KV, rootHash []byte) (*mixTy.CommitTreeLeaves, error) { func getCommitRootLeaves(db dbm.KV, rootHash string) (*mixTy.CommitTreeLeaves, error) {
return getCommitLeaves(db, calcCommitTreeRootLeaves(common.ToHex(rootHash))) return getCommitLeaves(db, calcCommitTreeRootLeaves(rootHash))
} }
func getCommitTreeRoots(db dbm.KV, key []byte) (*mixTy.CommitTreeRoots, error) { func getCommitTreeRoots(db dbm.KV, key []byte) (*mixTy.CommitTreeRoots, error) {
...@@ -130,7 +119,7 @@ func initNewLeaves(leaf []byte) *types.Receipt { ...@@ -130,7 +119,7 @@ func initNewLeaves(leaf []byte) *types.Receipt {
} }
func archiveRoots(db dbm.KV, root []byte, leaves *mixTy.CommitTreeLeaves) (*types.Receipt, error) { func archiveRoots(db dbm.KV, root []byte, leaves *mixTy.CommitTreeLeaves) (*types.Receipt, error) {
receiptRootLeaves := makeTreeRootLeavesReceipt(root, leaves) receiptRootLeaves := makeTreeRootLeavesReceipt(transferFr2String(root), leaves)
archiveRoots, err := getArchiveCommitRoots(db) archiveRoots, err := getArchiveCommitRoots(db)
if isNotFound(errors.Cause(err)) { if isNotFound(errors.Cause(err)) {
...@@ -216,14 +205,16 @@ func checkTreeRootHashExist(db dbm.KV, hash []byte) bool { ...@@ -216,14 +205,16 @@ func checkTreeRootHashExist(db dbm.KV, hash []byte) bool {
func getProveData(targetLeaf []byte, leaves [][]byte) (*mixTy.CommitTreeProve, error) { func getProveData(targetLeaf []byte, leaves [][]byte) (*mixTy.CommitTreeProve, error) {
index := 0 index := 0
found := false
for i, key := range leaves { for i, key := range leaves {
if bytes.Equal(key, targetLeaf) { if bytes.Equal(key, targetLeaf) {
index = i index = i
found = true
break break
} }
} }
//index=0的leaf是占位"00",不会和leaf相等 //index=0的leaf是占位"00",不会和leaf相等
if index == 0 { if !found {
return nil, mixTy.ErrLeafNotFound return nil, mixTy.ErrLeafNotFound
} }
...@@ -232,22 +223,35 @@ func getProveData(targetLeaf []byte, leaves [][]byte) (*mixTy.CommitTreeProve, e ...@@ -232,22 +223,35 @@ func getProveData(targetLeaf []byte, leaves [][]byte) (*mixTy.CommitTreeProve, e
for _, key := range leaves { for _, key := range leaves {
tree.Push(key) tree.Push(key)
} }
root, set, proofIndex, num := tree.Prove() root, proofSet, proofIndex, num := tree.Prove()
var prove mixTy.CommitTreeProve var prove mixTy.CommitTreeProve
prove.RootHash = common.ToHex(root)
prove.RootHash = transferFr2String(root)
prove.ProofIndex = uint32(proofIndex) prove.ProofIndex = uint32(proofIndex)
prove.NumLeaves = uint32(num) prove.NumLeaves = uint32(num)
for _, s := range set { //set[0] 是targetLeaf
prove.ProofSet = append(prove.ProofSet, common.ToHex(s)) for _, s := range proofSet {
prove.ProofSet = append(prove.ProofSet, transferFr2String(s))
}
helpers := merkletree.GenerateProofHelper(proofSet, proofIndex, num)
var helpStr []string
for _, i := range helpers {
helpStr = append(helpStr, strconv.Itoa(i))
} }
prove.Helpers = strings.Join(helpStr, ",")
return &prove, nil return &prove, nil
} }
func CalcTreeProve(db dbm.KV, rootHash, leaf []byte) (*mixTy.CommitTreeProve, error) { func CalcTreeProve(db dbm.KV, rootHash, leaf string) (*mixTy.CommitTreeProve, error) {
if len(leaf) <= 0 {
return nil, errors.Wrap(types.ErrInvalidParam, "leaf is null")
}
leaves, err := getCurrentCommitTreeLeaves(db) leaves, err := getCurrentCommitTreeLeaves(db)
if err == nil { if err == nil {
p, err := getProveData(leaf, leaves.Data) p, err := getProveData(transferFr2Bytes(leaf), leaves.Data)
if err == nil { if err == nil {
return p, nil return p, nil
} }
...@@ -258,9 +262,9 @@ func CalcTreeProve(db dbm.KV, rootHash, leaf []byte) (*mixTy.CommitTreeProve, er ...@@ -258,9 +262,9 @@ func CalcTreeProve(db dbm.KV, rootHash, leaf []byte) (*mixTy.CommitTreeProve, er
if err != nil { if err != nil {
return nil, err return nil, err
} }
p, err := getProveData(leaf, leaves.Data) p, err := getProveData(transferFr2Bytes(leaf), leaves.Data)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "hash=%s,leaf=%s", common.ToHex(rootHash), common.ToHex(leaf)) return nil, errors.Wrapf(err, "hash=%s,leaf=%s", rootHash, leaf)
} }
return p, nil return p, nil
} }
...@@ -268,9 +272,9 @@ func CalcTreeProve(db dbm.KV, rootHash, leaf []byte) (*mixTy.CommitTreeProve, er ...@@ -268,9 +272,9 @@ func CalcTreeProve(db dbm.KV, rootHash, leaf []byte) (*mixTy.CommitTreeProve, er
roots, err := getArchiveCommitRoots(db) roots, err := getArchiveCommitRoots(db)
if err == nil { if err == nil {
for _, root := range roots.Data { for _, root := range roots.Data {
leaves, err := getCommitRootLeaves(db, root) leaves, err := getCommitRootLeaves(db, transferFr2String(root))
if err == nil { if err == nil {
p, err := getProveData(leaf, leaves.Data) p, err := getProveData(transferFr2Bytes(leaf), leaves.Data)
if err == nil { if err == nil {
return p, nil return p, nil
} }
...@@ -279,6 +283,6 @@ func CalcTreeProve(db dbm.KV, rootHash, leaf []byte) (*mixTy.CommitTreeProve, er ...@@ -279,6 +283,6 @@ func CalcTreeProve(db dbm.KV, rootHash, leaf []byte) (*mixTy.CommitTreeProve, er
} }
} }
return nil, errors.Wrapf(err, "hash=%s,leaf=%s", common.ToHex(rootHash), common.ToHex(leaf)) return nil, errors.Wrapf(err, "hash=%s,leaf=%s", rootHash, 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 (
"testing"
"github.com/stretchr/testify/assert"
)
/*
leaf0 = "16308793397024662832064523892418908145900866571524124093537199035808550255649"
hexstr 240e732fc90c3a88a11f3f60bbbe412f6b4b56d007cf34fdb2500195071c7c21
leaf1 = 21467822781369104390668289189963532506973289112396605437823854946060028754354
leaf hash 17799daf83d82530d70343bc44578bdabafcb134332d4949883695a1ec9d1ba9
leaf2= 4178471437305290899835614805415999986197321812505352791035422725360758750328
leaf hash 29ded1ba9ed45d829f458ce511e013a8d11058db9d6f03fea14267082087b151
leaf3= 10407830929890509544473717262275616077696950294748419792758056545898949331744
leaf hash 1b757026b07fd17150c5d23081bddd52e77dc26b0c7c46b4e0150ca7ccfed35a
leaf4= 11032604436245646157001636966356016502073301224837385665550497706958264582086
leaf hash 24a8d61af8e16abaf9ccb1051c882799121c6ece1094655b5b93f837aead2f30
merkleroot= 6988991286454436061784929049510388415076132311642532433013500389938249229356
0 proof str= 21467822781369104390668289189963532506973289112396605437823854946060028754354
1 proof str= 12096317366724227951683802305909172775715878134489527031786909074403605889217
2 proof str= 14541527209424185878803689752018034974129079647509824805270353433359922459228
3 proof str= 16581570556767364549626991605903512613557832602774591000372759906303762837296
*/
func TestGetProveData(t *testing.T) {
leaves := []string{
"16308793397024662832064523892418908145900866571524124093537199035808550255649",
"21467822781369104390668289189963532506973289112396605437823854946060028754354",
"4178471437305290899835614805415999986197321812505352791035422725360758750328",
"10407830929890509544473717262275616077696950294748419792758056545898949331744",
"11032604436245646157001636966356016502073301224837385665550497706958264582086",
}
proves := []string{
"21467822781369104390668289189963532506973289112396605437823854946060028754354",
"12096317366724227951683802305909172775715878134489527031786909074403605889217",
"14541527209424185878803689752018034974129079647509824805270353433359922459228",
"16581570556767364549626991605903512613557832602774591000372759906303762837296",
}
var leave [][]byte
for _, l := range leaves {
leave = append(leave, transferFr2Bytes(l))
}
ret, err := getProveData(leave[1], leave)
assert.Nil(t, err)
assert.Equal(t, uint32(5), ret.NumLeaves)
assert.Equal(t, uint32(1), ret.ProofIndex)
assert.Equal(t, "6988991286454436061784929049510388415076132311642532433013500389938249229356", ret.RootHash)
assert.Equal(t, len(proves), len(ret.ProofSet))
for i, k := range proves {
assert.Equal(t, k, ret.ProofSet[i])
}
assert.Equal(t, "0,1,1", ret.Helpers)
}
...@@ -26,7 +26,7 @@ func isSuperManager(cfg *types.Chain33Config, addr string) bool { ...@@ -26,7 +26,7 @@ func isSuperManager(cfg *types.Chain33Config, addr string) bool {
func (a *action) Config(config *mixTy.MixConfigAction) (*types.Receipt, error) { func (a *action) Config(config *mixTy.MixConfigAction) (*types.Receipt, error) {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
if !isSuperManager(cfg, a.fromaddr) { if !isSuperManager(cfg, a.fromaddr) {
return nil, types.ErrNotAllow return nil, errors.Wrapf(types.ErrNotAllow, "not super manager,%s", a.fromaddr)
} }
switch config.Ty { switch config.Ty {
case mixTy.MixConfigType_VerifyKey: case mixTy.MixConfigType_VerifyKey:
......
...@@ -9,8 +9,6 @@ import ( ...@@ -9,8 +9,6 @@ import (
"encoding/json" "encoding/json"
"strconv" "strconv"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/mix/executor/zksnark" "github.com/33cn/plugin/plugin/dapp/mix/executor/zksnark"
...@@ -20,8 +18,8 @@ import ( ...@@ -20,8 +18,8 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func makeNullifierSetReceipt(hash []byte, data proto.Message) *types.Receipt { func makeNullifierSetReceipt(hash string, data proto.Message) *types.Receipt {
return makeReceipt(calcNullifierHashKey(common.ToHex(hash)), mixTy.TyLogNulliferSet, data) return makeReceipt(calcNullifierHashKey(hash), mixTy.TyLogNulliferSet, data)
} }
...@@ -72,7 +70,7 @@ func (a *action) depositVerify(proof *mixTy.ZkProofInfo) ([]byte, uint64, error) ...@@ -72,7 +70,7 @@ func (a *action) depositVerify(proof *mixTy.ZkProofInfo) ([]byte, uint64, error)
return nil, 0, err return nil, 0, err
} }
return input.NodeHash, val, nil return transferFr2Bytes(input.NodeHash), val, nil
} }
......
// from https://gitlab.com/NebulousLabs/merkletree
package merkletree
import (
"errors"
"hash"
"io"
)
// ReadAll will read segments of size 'segmentSize' and push them into the tree
// until EOF is reached. Success will return 'err == nil', not 'err == EOF'. No
// padding is added to the data, so the last element may be smaller than
// 'segmentSize'.
func (t *Tree) ReadAll(r io.Reader, segmentSize int) error {
for {
segment := make([]byte, segmentSize)
n, readErr := io.ReadFull(r, segment)
if readErr == io.EOF {
// All data has been read.
break
} else if readErr == io.ErrUnexpectedEOF {
// This is the last segment, and there aren't enough bytes to fill
// the entire segment. Note that the next call will return io.EOF.
segment = segment[:n]
} else if readErr != nil {
return readErr
}
t.Push(segment)
}
return nil
}
// ReaderRoot returns the Merkle root of the data read from the reader, where
// each leaf is 'segmentSize' long and 'h' is used as the hashing function. All
// leaves will be 'segmentSize' bytes except the last leaf, which will not be
// padded out if there are not enough bytes remaining in the reader.
func ReaderRoot(r io.Reader, h hash.Hash, segmentSize int) (root []byte, err error) {
tree := New(h)
err = tree.ReadAll(r, segmentSize)
if err != nil {
return
}
root = tree.Root()
return
}
// BuildReaderProof returns a proof that certain data is in the merkle tree
// created by the data in the reader. The merkle root, set of proofs, and the
// number of leaves in the Merkle tree are all returned. All leaves will we
// 'segmentSize' bytes except the last leaf, which will not be padded out if
// there are not enough bytes remaining in the reader.
func BuildReaderProof(r io.Reader, h hash.Hash, segmentSize int, index uint64) (root []byte, proofSet [][]byte, numLeaves uint64, err error) {
tree := New(h)
err = tree.SetIndex(index)
if err != nil {
// This code should be unreachable - SetIndex will only return an error
// if the tree is not empty, and yet the tree should be empty at this
// point.
panic(err)
}
err = tree.ReadAll(r, segmentSize)
if err != nil {
return
}
root, proofSet, _, numLeaves = tree.Prove()
if len(proofSet) == 0 {
err = errors.New("index was not reached while creating proof")
return
}
return
}
// from https://gitlab.com/NebulousLabs/merkletree
package merkletree
import (
"encoding/hex"
"errors"
"fmt"
"hash"
)
// A Tree takes data as leaves and returns the Merkle root. Each call to 'Push'
// adds one leaf to the Merkle tree. Calling 'Root' returns the Merkle root.
// The Tree also constructs proof that a single leaf is a part of the tree. The
// leaf can be chosen with 'SetIndex'. The memory footprint of Tree grows in
// O(log(n)) in the number of leaves.
type Tree struct {
// The Tree is stored as a stack of subtrees. Each subtree has a height,
// and is the Merkle root of 2^height leaves. A Tree with 11 nodes is
// represented as a subtree of height 3 (8 nodes), a subtree of height 1 (2
// nodes), and a subtree of height 0 (1 node). Head points to the smallest
// tree. When a new leaf is inserted, it is inserted as a subtree of height
// 0. If there is another subtree of the same height, both can be removed,
// combined, and then inserted as a subtree of height n + 1.
head *subTree
hash hash.Hash
// Helper variables used to construct proofs that the data at 'proofIndex'
// is in the Merkle tree. The proofSet is constructed as elements are being
// added to the tree. The first element of the proof set is the original
// data used to create the leaf at index 'proofIndex'. proofTree indicates
// if the tree will be used to create a merkle proof.
currentIndex uint64
proofIndex uint64
proofSet [][]byte
proofTree bool
// The cachedTree flag indicates that the tree is cached, meaning that
// different code is used in 'Push' for creating a new head subtree. Adding
// this flag is somewhat gross, but eliminates needing to duplicate the
// entire 'Push' function when writing the cached tree.
cachedTree bool
}
// A subTree contains the Merkle root of a complete (2^height leaves) subTree
// of the Tree. 'sum' is the Merkle root of the subTree. If 'next' is not nil,
// it will be a tree with a higher height.
type subTree struct {
next *subTree
height int // Int is okay because a height over 300 is physically unachievable.
sum []byte
}
// sum returns the hash of the input data using the specified algorithm.
func sum(h hash.Hash, data ...[]byte) []byte {
h.Reset()
for _, d := range data {
// the Hash interface specifies that Write never returns an error
_, _ = h.Write(d)
}
return h.Sum(nil)
}
// leafSum returns the hash created from data inserted to form a leaf. Leaf
// sums are calculated using:
// Hash(0x00 || data)
func leafSum(h hash.Hash, data []byte) []byte {
//return sum(h, leafHashPrefix, data)
return sum(h, data)
}
// nodeSum returns the hash created from two sibling nodes being combined into
// a parent node. Node sums are calculated using:
// Hash(0x01 || left sibling sum || right sibling sum)
func nodeSum(h hash.Hash, a, b []byte) []byte {
//return sum(h, nodeHashPrefix, a, b)
return sum(h, a, b)
}
// joinSubTrees combines two equal sized subTrees into a larger subTree.
func joinSubTrees(h hash.Hash, a, b *subTree) *subTree {
// if DEBUG {
// if b.next != a {
// panic("invalid subtree join - 'a' is not paired with 'b'")
// }
// if a.height < b.height {
// panic("invalid subtree presented - height mismatch")
// }
// }
return &subTree{
next: a.next,
height: a.height + 1,
sum: nodeSum(h, a.sum, b.sum),
}
}
// New creates a new Tree. The provided hash will be used for all hashing
// operations within the Tree.
func New(h hash.Hash) *Tree {
return &Tree{
hash: h,
}
}
// Prove creates a proof that the leaf at the established index (established by
// SetIndex) is an element of the Merkle tree. Prove will return a nil proof
// set if used incorrectly. Prove does not modify the Tree. Prove can only be
// called if SetIndex has been called previously.
func (t *Tree) Prove() (merkleRoot []byte, proofSet [][]byte, proofIndex uint64, numLeaves uint64) {
if !t.proofTree {
panic("wrong usage: can't call prove on a tree if SetIndex wasn't called")
}
// Return nil if the Tree is empty, or if the proofIndex hasn't yet been
// reached.
if t.head == nil || len(t.proofSet) == 0 {
return t.Root(), nil, t.proofIndex, t.currentIndex
}
proofSet = t.proofSet
// The set of subtrees must now be collapsed into a single root. The proof
// set already contains all of the elements that are members of a complete
// subtree. Of what remains, there will be at most 1 element provided from
// a sibling on the right, and all of the other proofs will be provided
// from a sibling on the left. This results from the way orphans are
// treated. All subtrees smaller than the subtree containing the proofIndex
// will be combined into a single subtree that gets combined with the
// proofIndex subtree as a single right sibling. All subtrees larger than
// the subtree containing the proofIndex will be combined with the subtree
// containing the proof index as left siblings.
// Start at the smallest subtree and combine it with larger subtrees until
// it would be combining with the subtree that contains the proof index. We
// can recognize the subtree containing the proof index because the height
// of that subtree will be one less than the current length of the proof
// set.
current := t.head
for current.next != nil && current.next.height < len(proofSet)-1 {
current = joinSubTrees(t.hash, current.next, current)
}
// Sanity check - check that either 'current' or 'current.next' is the
// subtree containing the proof index.
// if DEBUG {
// if current.height != len(t.proofSet)-1 && (current.next != nil && current.next.height != len(t.proofSet)-1) {
// panic("could not find the subtree containing the proof index")
// }
// }
// If the current subtree is not the subtree containing the proof index,
// then it must be an aggregate subtree that is to the right of the subtree
// containing the proof index, and the next subtree is the subtree
// containing the proof index.
if current.next != nil && current.next.height == len(proofSet)-1 {
proofSet = append(proofSet, current.sum)
current = current.next
}
// The current subtree must be the subtree containing the proof index. This
// subtree does not need an entry, as the entry was created during the
// construction of the Tree. Instead, skip to the next subtree.
current = current.next
// All remaining subtrees will be added to the proof set as a left sibling,
// completing the proof set.
for current != nil {
proofSet = append(proofSet, current.sum)
current = current.next
}
return t.Root(), proofSet, t.proofIndex, t.currentIndex
}
// Push will add data to the set, building out the Merkle tree and Root. The
// tree does not remember all elements that are added, instead only keeping the
// log(n) elements that are necessary to build the Merkle root and keeping the
// log(n) elements necessary to build a proof that a piece of data is in the
// Merkle tree.
func (t *Tree) Push(data []byte) {
// The first element of a proof is the data at the proof index. If this
// data is being inserted at the proof index, it is added to the proof set.
if t.currentIndex == t.proofIndex {
t.proofSet = append(t.proofSet, data)
}
// Hash the data to create a subtree of height 0. The sum of the new node
// is going to be the data for cached trees, and is going to be the result
// of calling leafSum() on the data for standard trees. Doing a check here
// prevents needing to duplicate the entire 'Push' function for the trees.
t.head = &subTree{
next: t.head,
height: 0,
}
if t.cachedTree {
t.head.sum = data
} else {
t.head.sum = leafSum(t.hash, data)
fmt.Println("leaf hash", hex.EncodeToString(t.head.sum))
}
// Join subTrees if possible.
t.joinAllSubTrees()
// Update the index.
t.currentIndex++
// Sanity check - From head to tail of the stack, the height should be
// strictly increasing.
// if DEBUG {
// current := t.head
// height := current.height
// for current.next != nil {
// current = current.next
// if current.height <= height {
// panic("subtrees are out of order")
// }
// height = current.height
// }
// }
}
// PushSubTree pushes a cached subtree into the merkle tree. The subtree has to
// be smaller than the smallest subtree in the merkle tree, it has to be
// balanced and it can't contain the element that needs to be proven. Since we
// can't tell if a subTree is balanced, we can't sanity check for unbalanced
// trees. Therefore an unbalanced tree will cause silent errors, pain and
// misery for the person who wants to debug the resulting error.
func (t *Tree) PushSubTree(height int, sum []byte) error {
// Check if the cached tree that is pushed contains the element at
// proofIndex. This is not allowed.
newIndex := t.currentIndex + 1<<uint64(height)
if t.proofTree && (t.currentIndex == t.proofIndex ||
(t.currentIndex < t.proofIndex && t.proofIndex < newIndex)) {
return errors.New("the cached tree shouldn't contain the element to prove")
}
// We can only add the cached tree if its depth is <= the depth of the
// current subtree.
if t.head != nil && height > t.head.height {
return fmt.Errorf("can't add a subtree that is larger than the smallest subtree %v > %v", height, t.head.height)
}
// Insert the cached tree as the new head.
t.head = &subTree{
height: height,
next: t.head,
sum: sum,
}
// Join subTrees if possible.
t.joinAllSubTrees()
// Update the index.
t.currentIndex = newIndex
// Sanity check - From head to tail of the stack, the height should be
// strictly increasing.
// if DEBUG {
// current := t.head
// height := current.height
// for current.next != nil {
// current = current.next
// if current.height <= height {
// panic("subtrees are out of order")
// }
// height = current.height
// }
// }
return nil
}
// Root returns the Merkle root of the data that has been pushed.
func (t *Tree) Root() []byte {
// If the Tree is empty, return nil.
if t.head == nil {
return nil
}
// The root is formed by hashing together subTrees in order from least in
// height to greatest in height. The taller subtree is the first subtree in
// the join.
current := t.head
for current.next != nil {
current = joinSubTrees(t.hash, current.next, current)
}
// Return a copy to prevent leaking a pointer to internal data.
return append(current.sum[:0:0], current.sum...)
}
// SetIndex will tell the Tree to create a storage proof for the leaf at the
// input index. SetIndex must be called on an empty tree.
func (t *Tree) SetIndex(i uint64) error {
if t.head != nil {
return errors.New("cannot call SetIndex on Tree if Tree has not been reset")
}
t.proofTree = true
t.proofIndex = i
return nil
}
// joinAllSubTrees inserts the subTree at t.head into the Tree. As long as the
// height of the next subTree is the same as the height of the current subTree,
// the two will be combined into a single subTree of height n+1.
func (t *Tree) joinAllSubTrees() {
for t.head.next != nil && t.head.height == t.head.next.height {
// Before combining subtrees, check whether one of the subtree hashes
// needs to be added to the proof set. This is going to be true IFF the
// subtrees being combined are one height higher than the previous
// subtree added to the proof set. The height of the previous subtree
// added to the proof set is equal to len(t.proofSet) - 1.
if t.head.height == len(t.proofSet)-1 {
// One of the subtrees needs to be added to the proof set. The
// subtree that needs to be added is the subtree that does not
// contain the proofIndex. Because the subtrees being compared are
// the smallest and rightmost trees in the Tree, this can be
// determined by rounding the currentIndex down to the number of
// nodes in the subtree and comparing that index to the proofIndex.
leaves := uint64(1 << uint(t.head.height))
mid := (t.currentIndex / leaves) * leaves
if t.proofIndex < mid {
t.proofSet = append(t.proofSet, t.head.sum)
} else {
t.proofSet = append(t.proofSet, t.head.next.sum)
}
// Sanity check - the proofIndex should never be less than the
// midpoint minus the number of leaves in each subtree.
// if DEBUG {
// if t.proofIndex < mid-leaves {
// panic("proof being added with weird values")
// }
// }
}
// Join the two subTrees into one subTree with a greater height. Then
// compare the new subTree to the next subTree.
t.head = joinSubTrees(t.hash, t.head.next, t.head)
}
}
// from https://gitlab.com/NebulousLabs/merkletree
package merkletree
import (
"bytes"
"hash"
)
// VerifyProof takes a Merkle root, a proofSet, and a proofIndex and returns
// true if the first element of the proof set is a leaf of data in the Merkle
// root. False is returned if the proof set or Merkle root is nil, and if
// 'numLeaves' equals 0.
func VerifyProof(h hash.Hash, merkleRoot []byte, proofSet [][]byte, proofIndex uint64, numLeaves uint64) bool {
// Return false for nonsense input. A switch statement is used so that the
// cover tool will reveal if a case is not covered by the test suite. This
// would not be possible using a single if statement due to the limitations
// of the cover tool.
if merkleRoot == nil {
return false
}
if proofIndex >= numLeaves {
return false
}
// In a Merkle tree, every node except the root node has a sibling.
// Combining the two siblings in the correct order will create the parent
// node. Each of the remaining hashes in the proof set is a sibling to a
// node that can be built from all of the previous elements of the proof
// set. The next node is built by taking:
//
// H(0x01 || sibling A || sibling B)
//
// The difficulty of the algorithm lies in determining whether the supplied
// hash is sibling A or sibling B. This information can be determined by
// using the proof index and the total number of leaves in the tree.
//
// A pair of two siblings forms a subtree. The subtree is complete if it
// has 1 << height total leaves. When the subtree is complete, the position
// of the proof index within the subtree can be determined by looking at
// the bounds of the subtree and determining if the proof index is in the
// first or second half of the subtree.
//
// When the subtree is not complete, either 1 or 0 of the remaining hashes
// will be sibling B. All remaining hashes after that will be sibling A.
// This is true because of the way that orphans are merged into the Merkle
// tree - an orphan at height n is elevated to height n + 1, and only
// hashed when it is no longer an orphan. Each subtree will therefore merge
// with at most 1 orphan to the right before becoming an orphan itself.
// Orphan nodes are always merged with larger subtrees to the left.
//
// One vulnerability with the proof verification is that the proofSet may
// not be long enough. Before looking at an element of proofSet, a check
// needs to be made that the element exists.
// The first element of the set is the original data. A sibling at height 1
// is created by getting the leafSum of the original data.
height := 0
if len(proofSet) <= height {
return false
}
sum := leafSum(h, proofSet[height])
height++
// While the current subtree (of height 'height') is complete, determine
// the position of the next sibling using the complete subtree algorithm.
// 'stableEnd' tells us the ending index of the last full subtree. It gets
// initialized to 'proofIndex' because the first full subtree was the
// subtree of height 1, created above (and had an ending index of
// 'proofIndex').
stableEnd := proofIndex
for {
// Determine if the subtree is complete. This is accomplished by
// rounding down the proofIndex to the nearest 1 << 'height', adding 1
// << 'height', and comparing the result to the number of leaves in the
// Merkle tree.
subTreeStartIndex := (proofIndex / (1 << uint(height))) * (1 << uint(height)) // round down to the nearest 1 << height
subTreeEndIndex := subTreeStartIndex + (1 << (uint(height))) - 1 // subtract 1 because the start index is inclusive
if subTreeEndIndex >= numLeaves {
// If the Merkle tree does not have a leaf at index
// 'subTreeEndIndex', then the subtree of the current height is not
// a complete subtree.
break
}
stableEnd = subTreeEndIndex
// Determine if the proofIndex is in the first or the second half of
// the subtree.
if len(proofSet) <= height {
return false
}
if proofIndex-subTreeStartIndex < 1<<uint(height-1) {
sum = nodeSum(h, sum, proofSet[height])
} else {
sum = nodeSum(h, proofSet[height], sum)
}
height++
}
// Determine if the next hash belongs to an orphan that was elevated. This
// is the case IFF 'stableEnd' (the last index of the largest full subtree)
// is equal to the number of leaves in the Merkle tree.
if stableEnd != numLeaves-1 {
if len(proofSet) <= height {
return false
}
sum = nodeSum(h, sum, proofSet[height])
height++
}
// All remaining elements in the proof set will belong to a left sibling.
for height < len(proofSet) {
sum = nodeSum(h, proofSet[height], sum)
height++
}
// Compare our calculated Merkle root to the desired Merkle root.
if bytes.Equal(sum, merkleRoot) {
return true
}
return false
}
// GenerateProofHelper generates an array of 1 or 0 telling if during the proof verification
// the hash to compute is h(sum, proof[i]) or h(proof[i], sum). The size of the resulting slice is
// len(proofSet)-1.
// cf gitlab.com/NebulousLabs/merkletree for the algorithm
func GenerateProofHelper(proofSet [][]byte, proofIndex, numLeaves uint64) []int {
res := make([]int, len(proofSet)-1)
height := 1
// While the current subtree (of height 'height') is complete, determine
// the position of the next sibling using the complete subtree algorithm.
// 'stableEnd' tells us the ending index of the last full subtree. It gets
// initialized to 'proofIndex' because the first full subtree was the
// subtree of height 1, created above (and had an ending index of
// 'proofIndex').
stableEnd := proofIndex
for {
// Determine if the subtree is complete. This is accomplished by
// rounding down the proofIndex to the nearest 1 << 'height', adding 1
// << 'height', and comparing the result to the number of leaves in the
// Merkle tree.
subTreeStartIndex := (proofIndex / (1 << uint(height))) * (1 << uint(height)) // round down to the nearest 1 << height
subTreeEndIndex := subTreeStartIndex + (1 << (uint(height))) - 1 // subtract 1 because the start index is inclusive
if subTreeEndIndex >= numLeaves {
// If the Merkle tree does not have a leaf at index
// 'subTreeEndIndex', then the subtree of the current height is not
// a complete subtree.
break
}
stableEnd = subTreeEndIndex
if proofIndex-subTreeStartIndex < 1<<uint(height-1) {
res[height-1] = 1
} else {
res[height-1] = 0
}
height++
}
// Determine if the next hash belongs to an orphan that was elevated. This
// is the case IFF 'stableEnd' (the last index of the largest full subtree)
// is equal to the number of leaves in the Merkle tree.
if stableEnd != numLeaves-1 {
res[height-1] = 1
height++
}
// All remaining elements in the proof set will belong to a left sibling.
for height < len(proofSet) {
res[height-1] = 0
height++
}
return res
}
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
package executor package executor
import ( import (
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
log "github.com/33cn/chain33/common/log/log15" log "github.com/33cn/chain33/common/log/log15"
drivers "github.com/33cn/chain33/system/dapp" drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -49,6 +47,6 @@ func newMix() drivers.Driver { ...@@ -49,6 +47,6 @@ func newMix() drivers.Driver {
} }
// GetDriverName return paracross driver name // GetDriverName return paracross driver name
func (c *Mix) GetDriverName() string { func (m *Mix) GetDriverName() string {
return pt.ParaX return mixTy.MixX
} }
// 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"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
// Query_GetTitle query paracross title
func (m *Mix) Query_GetTreePath(in *mixTy.TreePathReq) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
return CalcTreeProve(m.GetStateDB(), in.RootHash, in.LeafHash)
}
...@@ -31,7 +31,7 @@ func (a *action) transferInputVerify(proof *mixTy.ZkProofInfo) (*mixTy.TransferI ...@@ -31,7 +31,7 @@ func (a *action) transferInputVerify(proof *mixTy.ZkProofInfo) (*mixTy.TransferI
return nil, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput) return nil, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput)
} }
err = a.spendVerify(input.TreeRootHash, input.NullifierHash, input.AuthorizeHash) err = a.spendVerify(input.TreeRootHash, input.NullifierHash, input.AuthorizeSpendHash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -138,7 +138,7 @@ func (a *action) Transfer(transfer *mixTy.MixTransferAction) (*types.Receipt, er ...@@ -138,7 +138,7 @@ func (a *action) Transfer(transfer *mixTy.MixTransferAction) (*types.Receipt, er
//push new commit to merkle tree //push new commit to merkle tree
for _, h := range outputs { for _, h := range outputs {
rpt, err := pushTree(a.db, h.NodeHash) rpt, err := pushTree(a.db, transferFr2Bytes(h.NodeHash))
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -9,37 +9,35 @@ import ( ...@@ -9,37 +9,35 @@ import (
"encoding/json" "encoding/json"
"strconv" "strconv"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types" mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func (a *action) spendVerify(treeRootHash, nulliferHash, authorizeHash []byte) error { func (a *action) spendVerify(treeRootHash, nulliferHash, authorizeSpendHash string) error {
//zk-proof校验 //zk-proof校验
//check tree rootHash exist //check tree rootHash exist
if !checkTreeRootHashExist(a.db, treeRootHash) { if !checkTreeRootHashExist(a.db, transferFr2Bytes(treeRootHash)) {
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", common.ToHex(treeRootHash)) return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", treeRootHash)
} }
//nullifier should not exist //nullifier should not exist
nullifierKey := calcNullifierHashKey(common.ToHex(nulliferHash)) nullifierKey := calcNullifierHashKey(nulliferHash)
_, err := a.db.Get(nullifierKey) _, err := a.db.Get(nullifierKey)
if err == nil { if err == nil {
return errors.Wrapf(mixTy.ErrNulliferHashExist, "nullifier=%s", common.ToHex(nulliferHash)) return errors.Wrapf(mixTy.ErrNulliferHashExist, "nullifier=%s", nulliferHash)
} }
if !isNotFound(err) { if !isNotFound(err) {
return errors.Wrapf(err, "nullifier=%s", common.ToHex(nulliferHash)) return errors.Wrapf(err, "nullifier=%s", nulliferHash)
} }
// authorize should exist if needed // authorize should exist if needed
if len(authorizeHash) > 0 { if len(authorizeSpendHash) > 0 {
authKey := calcAuthorizeHashKey(common.ToHex(authorizeHash)) authKey := calcAuthorizeHashKey(authorizeSpendHash)
_, err = a.db.Get(authKey) _, err = a.db.Get(authKey)
if err != nil { if err != nil {
return errors.Wrapf(err, "authorize=%s", common.ToHex(authorizeHash)) return errors.Wrapf(err, "authorize=%s", authorizeSpendHash)
} }
} }
...@@ -47,29 +45,29 @@ func (a *action) spendVerify(treeRootHash, nulliferHash, authorizeHash []byte) e ...@@ -47,29 +45,29 @@ func (a *action) spendVerify(treeRootHash, nulliferHash, authorizeHash []byte) e
} }
func (a *action) withdrawVerify(proof *mixTy.ZkProofInfo) ([]byte, uint64, error) { func (a *action) withdrawVerify(proof *mixTy.ZkProofInfo) (string, uint64, error) {
var input mixTy.WithdrawPublicInput var input mixTy.WithdrawPublicInput
data, err := hex.DecodeString(proof.PublicInput) data, err := hex.DecodeString(proof.PublicInput)
if err != nil { if err != nil {
return nil, 0, errors.Wrapf(err, "decode string=%s", proof.PublicInput) return "", 0, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
} }
err = json.Unmarshal(data, &input) err = json.Unmarshal(data, &input)
if err != nil { if err != nil {
return nil, 0, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput) return "", 0, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput)
} }
val, err := strconv.ParseUint(input.Amount, 10, 64) val, err := strconv.ParseUint(input.Amount, 10, 64)
if err != nil { if err != nil {
return nil, 0, errors.Wrapf(err, "parseUint=%s", input.Amount) return "", 0, errors.Wrapf(err, "parseUint=%s", input.Amount)
} }
err = a.spendVerify(input.TreeRootHash, input.NullifierHash, input.AuthorizeHash) err = a.spendVerify(input.TreeRootHash, input.NullifierHash, input.AuthorizeSpendHash)
if err != nil { if err != nil {
return nil, 0, err return "", 0, err
} }
err = a.zkProofVerify(proof, mixTy.VerifyType_WITHDRAW) err = a.zkProofVerify(proof, mixTy.VerifyType_WITHDRAW)
if err != nil { if err != nil {
return nil, 0, err return "", 0, err
} }
return input.NullifierHash, val, nil return input.NullifierHash, val, nil
...@@ -82,7 +80,7 @@ func (a *action) withdrawVerify(proof *mixTy.ZkProofInfo) ([]byte, uint64, error ...@@ -82,7 +80,7 @@ func (a *action) withdrawVerify(proof *mixTy.ZkProofInfo) ([]byte, uint64, error
3. set nullifier exist 3. set nullifier exist
*/ */
func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, error) { func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, error) {
var nulliferSet [][]byte var nulliferSet []string
var sumValue uint64 var sumValue uint64
for _, k := range withdraw.SpendCommits { for _, k := range withdraw.SpendCommits {
nulfier, v, err := a.withdrawVerify(k) nulfier, v, err := a.withdrawVerify(k)
......
...@@ -102,39 +102,39 @@ message MixAction { ...@@ -102,39 +102,39 @@ message MixAction {
message DepositPublicInput { message DepositPublicInput {
bytes nodeHash = 1; string nodeHash = 1;
string amount = 2; string amount = 2;
} }
message WithdrawPublicInput { message WithdrawPublicInput {
bytes treeRootHash = 1; string treeRootHash = 1;
bytes nullifierHash = 2; string nullifierHash = 2;
bytes authorizeHash = 3; string authorizeSpendHash = 3;
string amount = 4; string amount = 4;
} }
message TransferInputPublicInput { message TransferInputPublicInput {
bytes treeRootHash = 1; string treeRootHash = 1;
string commitValueX = 2; string commitValueX = 2;
string commitValueY = 3; string commitValueY = 3;
bytes authorizeHash = 4; string authorizeSpendHash = 4;
bytes nullifierHash = 5; string nullifierHash = 5;
} }
message TransferOutputPublicInput { message TransferOutputPublicInput {
bytes nodeHash = 1; string nodeHash = 1;
string commitValueX = 2; string commitValueX = 2;
string commitValueY = 3; string commitValueY = 3;
} }
message AuthorizePublicInput { message AuthorizePublicInput {
bytes treeRootHash = 1; string treeRootHash = 1;
string authorizePubKey = 2; string authorizePubKey = 2;
bytes authorizeHash = 3; string authorizeHash = 3;
bytes authorizeSpendHash = 4; string authorizeSpendHash = 4;
} }
...@@ -156,9 +156,13 @@ message CommitTreeProve { ...@@ -156,9 +156,13 @@ message CommitTreeProve {
repeated string proofSet = 2; repeated string proofSet = 2;
uint32 proofIndex = 3; uint32 proofIndex = 3;
uint32 numLeaves = 4; uint32 numLeaves = 4;
string helpers = 5;
} }
message TreePathReq{
string rootHash = 1;
string leafHash = 2;
}
......
...@@ -5,9 +5,8 @@ package types ...@@ -5,9 +5,8 @@ package types
import ( import (
fmt "fmt" fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
math "math"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
...@@ -768,7 +767,7 @@ func (*MixAction) XXX_OneofWrappers() []interface{} { ...@@ -768,7 +767,7 @@ func (*MixAction) XXX_OneofWrappers() []interface{} {
} }
type DepositPublicInput struct { type DepositPublicInput struct {
NodeHash []byte `protobuf:"bytes,1,opt,name=nodeHash,proto3" json:"nodeHash,omitempty"` NodeHash string `protobuf:"bytes,1,opt,name=nodeHash,proto3" json:"nodeHash,omitempty"`
Amount string `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount,omitempty"` Amount string `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
...@@ -800,11 +799,11 @@ func (m *DepositPublicInput) XXX_DiscardUnknown() { ...@@ -800,11 +799,11 @@ func (m *DepositPublicInput) XXX_DiscardUnknown() {
var xxx_messageInfo_DepositPublicInput proto.InternalMessageInfo var xxx_messageInfo_DepositPublicInput proto.InternalMessageInfo
func (m *DepositPublicInput) GetNodeHash() []byte { func (m *DepositPublicInput) GetNodeHash() string {
if m != nil { if m != nil {
return m.NodeHash return m.NodeHash
} }
return nil return ""
} }
func (m *DepositPublicInput) GetAmount() string { func (m *DepositPublicInput) GetAmount() string {
...@@ -815,9 +814,9 @@ func (m *DepositPublicInput) GetAmount() string { ...@@ -815,9 +814,9 @@ func (m *DepositPublicInput) GetAmount() string {
} }
type WithdrawPublicInput struct { type WithdrawPublicInput struct {
TreeRootHash []byte `protobuf:"bytes,1,opt,name=treeRootHash,proto3" json:"treeRootHash,omitempty"` TreeRootHash string `protobuf:"bytes,1,opt,name=treeRootHash,proto3" json:"treeRootHash,omitempty"`
NullifierHash []byte `protobuf:"bytes,2,opt,name=nullifierHash,proto3" json:"nullifierHash,omitempty"` NullifierHash string `protobuf:"bytes,2,opt,name=nullifierHash,proto3" json:"nullifierHash,omitempty"`
AuthorizeHash []byte `protobuf:"bytes,3,opt,name=authorizeHash,proto3" json:"authorizeHash,omitempty"` AuthorizeSpendHash string `protobuf:"bytes,3,opt,name=authorizeSpendHash,proto3" json:"authorizeSpendHash,omitempty"`
Amount string `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` Amount string `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
...@@ -849,25 +848,25 @@ func (m *WithdrawPublicInput) XXX_DiscardUnknown() { ...@@ -849,25 +848,25 @@ func (m *WithdrawPublicInput) XXX_DiscardUnknown() {
var xxx_messageInfo_WithdrawPublicInput proto.InternalMessageInfo var xxx_messageInfo_WithdrawPublicInput proto.InternalMessageInfo
func (m *WithdrawPublicInput) GetTreeRootHash() []byte { func (m *WithdrawPublicInput) GetTreeRootHash() string {
if m != nil { if m != nil {
return m.TreeRootHash return m.TreeRootHash
} }
return nil return ""
} }
func (m *WithdrawPublicInput) GetNullifierHash() []byte { func (m *WithdrawPublicInput) GetNullifierHash() string {
if m != nil { if m != nil {
return m.NullifierHash return m.NullifierHash
} }
return nil return ""
} }
func (m *WithdrawPublicInput) GetAuthorizeHash() []byte { func (m *WithdrawPublicInput) GetAuthorizeSpendHash() string {
if m != nil { if m != nil {
return m.AuthorizeHash return m.AuthorizeSpendHash
} }
return nil return ""
} }
func (m *WithdrawPublicInput) GetAmount() string { func (m *WithdrawPublicInput) GetAmount() string {
...@@ -878,11 +877,11 @@ func (m *WithdrawPublicInput) GetAmount() string { ...@@ -878,11 +877,11 @@ func (m *WithdrawPublicInput) GetAmount() string {
} }
type TransferInputPublicInput struct { type TransferInputPublicInput struct {
TreeRootHash []byte `protobuf:"bytes,1,opt,name=treeRootHash,proto3" json:"treeRootHash,omitempty"` TreeRootHash string `protobuf:"bytes,1,opt,name=treeRootHash,proto3" json:"treeRootHash,omitempty"`
CommitValueX string `protobuf:"bytes,2,opt,name=commitValueX,proto3" json:"commitValueX,omitempty"` CommitValueX string `protobuf:"bytes,2,opt,name=commitValueX,proto3" json:"commitValueX,omitempty"`
CommitValueY string `protobuf:"bytes,3,opt,name=commitValueY,proto3" json:"commitValueY,omitempty"` CommitValueY string `protobuf:"bytes,3,opt,name=commitValueY,proto3" json:"commitValueY,omitempty"`
AuthorizeHash []byte `protobuf:"bytes,4,opt,name=authorizeHash,proto3" json:"authorizeHash,omitempty"` AuthorizeSpendHash string `protobuf:"bytes,4,opt,name=authorizeSpendHash,proto3" json:"authorizeSpendHash,omitempty"`
NullifierHash []byte `protobuf:"bytes,5,opt,name=nullifierHash,proto3" json:"nullifierHash,omitempty"` NullifierHash string `protobuf:"bytes,5,opt,name=nullifierHash,proto3" json:"nullifierHash,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -913,11 +912,11 @@ func (m *TransferInputPublicInput) XXX_DiscardUnknown() { ...@@ -913,11 +912,11 @@ func (m *TransferInputPublicInput) XXX_DiscardUnknown() {
var xxx_messageInfo_TransferInputPublicInput proto.InternalMessageInfo var xxx_messageInfo_TransferInputPublicInput proto.InternalMessageInfo
func (m *TransferInputPublicInput) GetTreeRootHash() []byte { func (m *TransferInputPublicInput) GetTreeRootHash() string {
if m != nil { if m != nil {
return m.TreeRootHash return m.TreeRootHash
} }
return nil return ""
} }
func (m *TransferInputPublicInput) GetCommitValueX() string { func (m *TransferInputPublicInput) GetCommitValueX() string {
...@@ -934,22 +933,22 @@ func (m *TransferInputPublicInput) GetCommitValueY() string { ...@@ -934,22 +933,22 @@ func (m *TransferInputPublicInput) GetCommitValueY() string {
return "" return ""
} }
func (m *TransferInputPublicInput) GetAuthorizeHash() []byte { func (m *TransferInputPublicInput) GetAuthorizeSpendHash() string {
if m != nil { if m != nil {
return m.AuthorizeHash return m.AuthorizeSpendHash
} }
return nil return ""
} }
func (m *TransferInputPublicInput) GetNullifierHash() []byte { func (m *TransferInputPublicInput) GetNullifierHash() string {
if m != nil { if m != nil {
return m.NullifierHash return m.NullifierHash
} }
return nil return ""
} }
type TransferOutputPublicInput struct { type TransferOutputPublicInput struct {
NodeHash []byte `protobuf:"bytes,1,opt,name=nodeHash,proto3" json:"nodeHash,omitempty"` NodeHash string `protobuf:"bytes,1,opt,name=nodeHash,proto3" json:"nodeHash,omitempty"`
CommitValueX string `protobuf:"bytes,2,opt,name=commitValueX,proto3" json:"commitValueX,omitempty"` CommitValueX string `protobuf:"bytes,2,opt,name=commitValueX,proto3" json:"commitValueX,omitempty"`
CommitValueY string `protobuf:"bytes,3,opt,name=commitValueY,proto3" json:"commitValueY,omitempty"` CommitValueY string `protobuf:"bytes,3,opt,name=commitValueY,proto3" json:"commitValueY,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
...@@ -982,11 +981,11 @@ func (m *TransferOutputPublicInput) XXX_DiscardUnknown() { ...@@ -982,11 +981,11 @@ func (m *TransferOutputPublicInput) XXX_DiscardUnknown() {
var xxx_messageInfo_TransferOutputPublicInput proto.InternalMessageInfo var xxx_messageInfo_TransferOutputPublicInput proto.InternalMessageInfo
func (m *TransferOutputPublicInput) GetNodeHash() []byte { func (m *TransferOutputPublicInput) GetNodeHash() string {
if m != nil { if m != nil {
return m.NodeHash return m.NodeHash
} }
return nil return ""
} }
func (m *TransferOutputPublicInput) GetCommitValueX() string { func (m *TransferOutputPublicInput) GetCommitValueX() string {
...@@ -1004,10 +1003,10 @@ func (m *TransferOutputPublicInput) GetCommitValueY() string { ...@@ -1004,10 +1003,10 @@ func (m *TransferOutputPublicInput) GetCommitValueY() string {
} }
type AuthorizePublicInput struct { type AuthorizePublicInput struct {
TreeRootHash []byte `protobuf:"bytes,1,opt,name=treeRootHash,proto3" json:"treeRootHash,omitempty"` TreeRootHash string `protobuf:"bytes,1,opt,name=treeRootHash,proto3" json:"treeRootHash,omitempty"`
AuthorizePubKey string `protobuf:"bytes,2,opt,name=authorizePubKey,proto3" json:"authorizePubKey,omitempty"` AuthorizePubKey string `protobuf:"bytes,2,opt,name=authorizePubKey,proto3" json:"authorizePubKey,omitempty"`
AuthorizeHash []byte `protobuf:"bytes,3,opt,name=authorizeHash,proto3" json:"authorizeHash,omitempty"` AuthorizeHash string `protobuf:"bytes,3,opt,name=authorizeHash,proto3" json:"authorizeHash,omitempty"`
AuthorizeSpendHash []byte `protobuf:"bytes,4,opt,name=authorizeSpendHash,proto3" json:"authorizeSpendHash,omitempty"` AuthorizeSpendHash string `protobuf:"bytes,4,opt,name=authorizeSpendHash,proto3" json:"authorizeSpendHash,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -1038,11 +1037,11 @@ func (m *AuthorizePublicInput) XXX_DiscardUnknown() { ...@@ -1038,11 +1037,11 @@ func (m *AuthorizePublicInput) XXX_DiscardUnknown() {
var xxx_messageInfo_AuthorizePublicInput proto.InternalMessageInfo var xxx_messageInfo_AuthorizePublicInput proto.InternalMessageInfo
func (m *AuthorizePublicInput) GetTreeRootHash() []byte { func (m *AuthorizePublicInput) GetTreeRootHash() string {
if m != nil { if m != nil {
return m.TreeRootHash return m.TreeRootHash
} }
return nil return ""
} }
func (m *AuthorizePublicInput) GetAuthorizePubKey() string { func (m *AuthorizePublicInput) GetAuthorizePubKey() string {
...@@ -1052,18 +1051,18 @@ func (m *AuthorizePublicInput) GetAuthorizePubKey() string { ...@@ -1052,18 +1051,18 @@ func (m *AuthorizePublicInput) GetAuthorizePubKey() string {
return "" return ""
} }
func (m *AuthorizePublicInput) GetAuthorizeHash() []byte { func (m *AuthorizePublicInput) GetAuthorizeHash() string {
if m != nil { if m != nil {
return m.AuthorizeHash return m.AuthorizeHash
} }
return nil return ""
} }
func (m *AuthorizePublicInput) GetAuthorizeSpendHash() []byte { func (m *AuthorizePublicInput) GetAuthorizeSpendHash() string {
if m != nil { if m != nil {
return m.AuthorizeSpendHash return m.AuthorizeSpendHash
} }
return nil return ""
} }
type ExistValue struct { type ExistValue struct {
...@@ -1188,6 +1187,7 @@ type CommitTreeProve struct { ...@@ -1188,6 +1187,7 @@ type CommitTreeProve struct {
ProofSet []string `protobuf:"bytes,2,rep,name=proofSet,proto3" json:"proofSet,omitempty"` ProofSet []string `protobuf:"bytes,2,rep,name=proofSet,proto3" json:"proofSet,omitempty"`
ProofIndex uint32 `protobuf:"varint,3,opt,name=proofIndex,proto3" json:"proofIndex,omitempty"` ProofIndex uint32 `protobuf:"varint,3,opt,name=proofIndex,proto3" json:"proofIndex,omitempty"`
NumLeaves uint32 `protobuf:"varint,4,opt,name=numLeaves,proto3" json:"numLeaves,omitempty"` NumLeaves uint32 `protobuf:"varint,4,opt,name=numLeaves,proto3" json:"numLeaves,omitempty"`
Helpers string `protobuf:"bytes,5,opt,name=helpers,proto3" json:"helpers,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -1246,6 +1246,60 @@ func (m *CommitTreeProve) GetNumLeaves() uint32 { ...@@ -1246,6 +1246,60 @@ func (m *CommitTreeProve) GetNumLeaves() uint32 {
return 0 return 0
} }
func (m *CommitTreeProve) GetHelpers() string {
if m != nil {
return m.Helpers
}
return ""
}
type TreePathReq struct {
RootHash string `protobuf:"bytes,1,opt,name=rootHash,proto3" json:"rootHash,omitempty"`
LeafHash string `protobuf:"bytes,2,opt,name=leafHash,proto3" json:"leafHash,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *TreePathReq) Reset() { *m = TreePathReq{} }
func (m *TreePathReq) String() string { return proto.CompactTextString(m) }
func (*TreePathReq) ProtoMessage() {}
func (*TreePathReq) Descriptor() ([]byte, []int) {
return fileDescriptor_5c21d519a9be369a, []int{20}
}
func (m *TreePathReq) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_TreePathReq.Unmarshal(m, b)
}
func (m *TreePathReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_TreePathReq.Marshal(b, m, deterministic)
}
func (m *TreePathReq) XXX_Merge(src proto.Message) {
xxx_messageInfo_TreePathReq.Merge(m, src)
}
func (m *TreePathReq) XXX_Size() int {
return xxx_messageInfo_TreePathReq.Size(m)
}
func (m *TreePathReq) XXX_DiscardUnknown() {
xxx_messageInfo_TreePathReq.DiscardUnknown(m)
}
var xxx_messageInfo_TreePathReq proto.InternalMessageInfo
func (m *TreePathReq) GetRootHash() string {
if m != nil {
return m.RootHash
}
return ""
}
func (m *TreePathReq) GetLeafHash() string {
if m != nil {
return m.LeafHash
}
return ""
}
func init() { func init() {
proto.RegisterEnum("types.VerifyType", VerifyType_name, VerifyType_value) proto.RegisterEnum("types.VerifyType", VerifyType_name, VerifyType_value)
proto.RegisterEnum("types.ZkCurveId", ZkCurveId_name, ZkCurveId_value) proto.RegisterEnum("types.ZkCurveId", ZkCurveId_name, ZkCurveId_value)
...@@ -1271,6 +1325,7 @@ func init() { ...@@ -1271,6 +1325,7 @@ func init() {
proto.RegisterType((*CommitTreeLeaves)(nil), "types.CommitTreeLeaves") proto.RegisterType((*CommitTreeLeaves)(nil), "types.CommitTreeLeaves")
proto.RegisterType((*CommitTreeRoots)(nil), "types.CommitTreeRoots") proto.RegisterType((*CommitTreeRoots)(nil), "types.CommitTreeRoots")
proto.RegisterType((*CommitTreeProve)(nil), "types.CommitTreeProve") proto.RegisterType((*CommitTreeProve)(nil), "types.CommitTreeProve")
proto.RegisterType((*TreePathReq)(nil), "types.TreePathReq")
} }
func init() { func init() {
...@@ -1278,67 +1333,69 @@ func init() { ...@@ -1278,67 +1333,69 @@ func init() {
} }
var fileDescriptor_5c21d519a9be369a = []byte{ var fileDescriptor_5c21d519a9be369a = []byte{
// 986 bytes of a gzipped FileDescriptorProto // 1013 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x96, 0xdd, 0x6e, 0x1a, 0x47, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdd, 0x6e, 0xe3, 0x54,
0x14, 0xc7, 0xd9, 0xe5, 0xcb, 0x7b, 0x00, 0x7b, 0x3d, 0xb1, 0x52, 0x52, 0x55, 0x15, 0xdd, 0x26, 0x10, 0x8e, 0xf3, 0x5b, 0x4f, 0x92, 0xd6, 0x3d, 0x5b, 0x2d, 0x5e, 0x84, 0x50, 0x30, 0xbb, 0x4b,
0x29, 0xa2, 0x12, 0x6a, 0x71, 0xeb, 0xb4, 0xea, 0x15, 0xb6, 0xa9, 0xa0, 0x89, 0x01, 0x0d, 0xeb, 0x14, 0xa4, 0x08, 0x52, 0xe8, 0x82, 0xb8, 0x4a, 0xdb, 0xa0, 0x84, 0xdd, 0x26, 0xd1, 0x89, 0xbb,
0xb8, 0xb5, 0xd4, 0x4a, 0x6b, 0x18, 0xea, 0x51, 0x60, 0x17, 0x2d, 0xb3, 0x18, 0x7a, 0xd3, 0xcb, 0x85, 0x4a, 0x20, 0xb9, 0xc9, 0x09, 0xb1, 0x9a, 0xd8, 0xc6, 0x39, 0x4e, 0x13, 0x6e, 0x78, 0x16,
0x3e, 0x45, 0x5f, 0xa3, 0x17, 0x7d, 0x8c, 0x4a, 0x7d, 0x9f, 0x6a, 0x3e, 0xf6, 0x8b, 0x60, 0x25, 0xae, 0x78, 0x03, 0x2e, 0x78, 0x0f, 0xee, 0x78, 0x18, 0x74, 0x7e, 0xfc, 0x17, 0x1a, 0x95, 0x4a,
0x96, 0x7a, 0xc7, 0x9c, 0xfd, 0x9d, 0x33, 0xe7, 0x7f, 0xce, 0x61, 0x66, 0xc0, 0x98, 0xd3, 0x75, 0x7b, 0xe7, 0x19, 0x7f, 0x33, 0xe7, 0xfb, 0x66, 0xe6, 0xfc, 0x80, 0xba, 0xb0, 0xd7, 0x4d, 0xcf,
0x73, 0xe1, 0x7b, 0xcc, 0x43, 0x79, 0xb6, 0x59, 0x90, 0xa5, 0xb5, 0x82, 0xd2, 0xf5, 0x9b, 0xd7, 0x77, 0xa9, 0x8b, 0x0a, 0x74, 0xe3, 0x91, 0xa5, 0xb1, 0x82, 0xf2, 0xf5, 0xed, 0x5b, 0xe2, 0xdb,
0xc4, 0xa7, 0xd3, 0xcd, 0x4b, 0xb2, 0x41, 0x0d, 0x28, 0x8e, 0x03, 0x7f, 0x45, 0x7a, 0x93, 0xaa, 0xd3, 0xcd, 0x6b, 0xb2, 0x41, 0x0d, 0x28, 0x8d, 0x03, 0x7f, 0x45, 0x7a, 0x13, 0x5d, 0xa9, 0x29,
0x56, 0xd3, 0xea, 0xfb, 0x2d, 0xb3, 0x29, 0xb8, 0xe6, 0xf5, 0x9b, 0x33, 0x69, 0xc7, 0x21, 0x80, 0xf5, 0xfd, 0x96, 0xd6, 0xe4, 0xb8, 0xe6, 0xf5, 0xed, 0x99, 0xf0, 0xe3, 0x10, 0x80, 0x5e, 0x40,
0x9e, 0x41, 0x8e, 0x7f, 0xab, 0xea, 0x02, 0x3c, 0x54, 0xa0, 0x8c, 0x65, 0x6f, 0x16, 0x04, 0x8b, 0x9e, 0xfd, 0xd3, 0xb3, 0x1c, 0x78, 0x28, 0x81, 0x22, 0x97, 0xb9, 0xf1, 0x08, 0xe6, 0xbf, 0xd1,
0xcf, 0xe8, 0x08, 0xf2, 0x2b, 0x67, 0x16, 0x90, 0x6a, 0xb6, 0xa6, 0xd5, 0x0d, 0x2c, 0x17, 0xd6, 0x11, 0x14, 0x56, 0xd6, 0x3c, 0x20, 0x7a, 0xae, 0xa6, 0xd4, 0x55, 0x2c, 0x0c, 0xe3, 0x04, 0x2a,
0x09, 0x94, 0x13, 0xfb, 0x2e, 0xd1, 0x73, 0xc8, 0x4d, 0x1c, 0xe6, 0x54, 0xb5, 0x5a, 0xb6, 0x5e, 0x89, 0x75, 0x97, 0xe8, 0x25, 0xe4, 0x27, 0x16, 0xb5, 0x74, 0xa5, 0x96, 0xab, 0x97, 0x5b, 0x28,
0x6a, 0xa1, 0x68, 0xd7, 0x08, 0xc1, 0xe2, 0xbb, 0xf5, 0x09, 0x94, 0xda, 0x01, 0xbb, 0x1d, 0x06, 0x5a, 0x35, 0x82, 0x60, 0xfe, 0xdf, 0xf8, 0x08, 0xca, 0xed, 0x80, 0xce, 0x86, 0xc1, 0x0d, 0x0f,
0x37, 0xc2, 0x0d, 0x25, 0xdc, 0x0c, 0x85, 0x7c, 0x06, 0x07, 0x1c, 0xf1, 0x7c, 0xfa, 0x1b, 0x91, 0x43, 0x89, 0x30, 0x55, 0x42, 0x3e, 0x81, 0x03, 0x06, 0x71, 0x7d, 0xfb, 0x57, 0x22, 0x70, 0x3b,
0xdc, 0x3d, 0x39, 0xfc, 0xab, 0xc1, 0xc1, 0x05, 0x5d, 0x9f, 0x79, 0xee, 0x94, 0xfe, 0xda, 0x1e, 0x38, 0xfc, 0xad, 0xc0, 0xc1, 0x85, 0xbd, 0x3e, 0x73, 0x9d, 0xa9, 0xfd, 0x73, 0x7b, 0x4c, 0x6d,
0x33, 0xea, 0xb9, 0xe8, 0x29, 0xe8, 0xf6, 0x46, 0x69, 0x3f, 0x52, 0x59, 0x44, 0x8c, 0x50, 0xa5, 0xd7, 0x41, 0xcf, 0x21, 0x6b, 0x6e, 0xa4, 0xf6, 0x23, 0xc9, 0x22, 0xc2, 0x70, 0x55, 0x59, 0x73,
0xdb, 0x1b, 0xf4, 0x39, 0x14, 0x24, 0xaf, 0xc4, 0x3f, 0xda, 0x26, 0xdb, 0x63, 0x86, 0x15, 0x82, 0x83, 0x3e, 0x85, 0xa2, 0xc0, 0x4b, 0xf1, 0x4f, 0xb6, 0x91, 0xed, 0x31, 0xc5, 0x12, 0x82, 0x5a,
0x5a, 0x60, 0xac, 0x42, 0x15, 0x22, 0x81, 0x9d, 0xfa, 0xba, 0x19, 0x1c, 0x63, 0xa8, 0x05, 0x45, 0xa0, 0xae, 0x42, 0x15, 0x9c, 0xc0, 0xbd, 0xfa, 0xba, 0x19, 0x1c, 0xc3, 0x50, 0x0b, 0x4a, 0x56,
0x27, 0x60, 0xb7, 0xdc, 0x23, 0x27, 0x3c, 0x1e, 0x2b, 0x8f, 0x2d, 0x65, 0xdd, 0x0c, 0x0e, 0xc1, 0x40, 0x67, 0x2c, 0x22, 0xcf, 0x23, 0x9e, 0xca, 0x88, 0x2d, 0x65, 0xdd, 0x0c, 0x0e, 0x81, 0xa7,
0xd3, 0xa2, 0x12, 0x69, 0x75, 0x78, 0x4f, 0x87, 0xbe, 0xe7, 0x4d, 0x7b, 0xee, 0xd4, 0xe3, 0xe2, 0x25, 0x29, 0xd2, 0xe8, 0xb0, 0x9e, 0x0e, 0x7d, 0xd7, 0x9d, 0xf6, 0x9c, 0xa9, 0xcb, 0xc4, 0x7b,
0x17, 0x7c, 0x21, 0x54, 0x19, 0x58, 0x2e, 0x50, 0x0d, 0x4a, 0x8b, 0xe0, 0x66, 0x46, 0xc7, 0x3d, 0xcc, 0xe0, 0xaa, 0x54, 0x2c, 0x0c, 0x54, 0x83, 0xb2, 0x17, 0xdc, 0xcc, 0xed, 0x71, 0xcf, 0xf1,
0x77, 0x11, 0x30, 0xa1, 0xc3, 0xc0, 0x49, 0x93, 0xf5, 0x0b, 0x98, 0x17, 0x74, 0x7d, 0x4e, 0x16, 0x02, 0xca, 0x75, 0xa8, 0x38, 0xe9, 0x32, 0x7e, 0x02, 0xed, 0xc2, 0x5e, 0x9f, 0x13, 0xcf, 0x5d,
0xde, 0x92, 0x32, 0xa5, 0xe5, 0x31, 0x14, 0x9c, 0xb9, 0x17, 0xb8, 0x4c, 0x04, 0xcb, 0x61, 0xb5, 0xda, 0x54, 0x6a, 0x79, 0x0a, 0x45, 0x6b, 0xe1, 0x06, 0x0e, 0xe5, 0xc9, 0xf2, 0x58, 0x5a, 0xa8,
0x42, 0x2d, 0x00, 0x97, 0xdc, 0x9d, 0x79, 0xf3, 0x39, 0x65, 0xcb, 0xaa, 0xbe, 0xd5, 0xc4, 0x28, 0x05, 0xe0, 0x90, 0xbb, 0x33, 0x77, 0xb1, 0xb0, 0xe9, 0x52, 0xcf, 0x6e, 0x35, 0x31, 0xe2, 0x82,
0x17, 0x9c, 0xa0, 0x2c, 0x0a, 0x87, 0x17, 0x74, 0x6d, 0xfb, 0x8e, 0xbb, 0x9c, 0x12, 0x5f, 0x6d, 0x13, 0x28, 0xc3, 0x86, 0xc3, 0x0b, 0x7b, 0x6d, 0xfa, 0x96, 0xb3, 0x9c, 0x12, 0x5f, 0x2e, 0x50,
0x50, 0x87, 0x3c, 0x15, 0x09, 0x69, 0xf7, 0xc6, 0x90, 0x00, 0x6a, 0x40, 0xc1, 0x0b, 0x98, 0xcc, 0x87, 0x82, 0xcd, 0x09, 0x29, 0x3b, 0x73, 0x08, 0x00, 0x6a, 0x40, 0xd1, 0x0d, 0xa8, 0xe0, 0xbe,
0xfd, 0x3e, 0x54, 0x11, 0xd6, 0x58, 0x6c, 0x75, 0x45, 0xd9, 0xed, 0xc4, 0x77, 0xee, 0xde, 0xa1, 0x0b, 0x2a, 0x11, 0xc6, 0x98, 0x2f, 0x75, 0x65, 0xd3, 0xd9, 0xc4, 0xb7, 0xee, 0x1e, 0xd0, 0x72,
0xe5, 0x04, 0xca, 0xcb, 0x05, 0x71, 0x27, 0xef, 0x56, 0x93, 0xe2, 0xac, 0x1f, 0x00, 0x5d, 0xd0, 0x02, 0x95, 0xa5, 0x47, 0x9c, 0xc9, 0xc3, 0x6a, 0x52, 0x38, 0xe3, 0x3b, 0x40, 0x17, 0xf6, 0x3a,
0x75, 0xd4, 0x20, 0xb5, 0xcb, 0x57, 0x50, 0xe2, 0x0d, 0x0a, 0x83, 0xdd, 0x2f, 0x2b, 0x89, 0x59, 0x6a, 0x90, 0x5c, 0xe5, 0x0b, 0x28, 0xb3, 0x06, 0x85, 0xc9, 0x76, 0xcb, 0x4a, 0xc2, 0x8c, 0x3f,
0x7f, 0xe9, 0x60, 0xf0, 0x60, 0x32, 0xc6, 0x3e, 0xe8, 0x4c, 0x0e, 0x65, 0x1e, 0xeb, 0x6c, 0x83, 0xb3, 0xa0, 0xb2, 0x64, 0x22, 0xc7, 0x3e, 0x64, 0xa9, 0x18, 0xca, 0x02, 0xce, 0xd2, 0x0d, 0xfa,
0xbe, 0x80, 0xc2, 0x58, 0x8c, 0x99, 0x68, 0x5b, 0x3c, 0x1c, 0x5b, 0xc3, 0xdc, 0xcd, 0x60, 0xc5, 0x0c, 0x8a, 0x63, 0x3e, 0x66, 0xbc, 0x6d, 0xf1, 0x70, 0x6c, 0x0d, 0x73, 0x37, 0x83, 0x25, 0x0e,
0xa1, 0x63, 0x28, 0x4e, 0x64, 0x23, 0xd5, 0x04, 0x7e, 0x10, 0xbb, 0xa4, 0x3a, 0xcc, 0x07, 0x4a, 0x1d, 0x43, 0x69, 0x22, 0x1a, 0x29, 0x27, 0xf0, 0xbd, 0x38, 0x24, 0xd5, 0x61, 0x36, 0x50, 0x12,
0x91, 0xe8, 0x04, 0xf6, 0xee, 0x54, 0xc9, 0xd4, 0x14, 0x56, 0x63, 0xaf, 0x74, 0x31, 0xbb, 0x19, 0x89, 0x4e, 0x60, 0xef, 0x4e, 0x96, 0x4c, 0x4e, 0xa1, 0x1e, 0x47, 0xa5, 0x8b, 0xd9, 0xcd, 0xe0,
0x1c, 0xb1, 0xdc, 0x8f, 0xa9, 0xae, 0x56, 0xf3, 0xdb, 0x7e, 0xe9, 0x7e, 0x73, 0xbf, 0x90, 0x45, 0x08, 0xcb, 0xe2, 0xa8, 0xec, 0xaa, 0x5e, 0xd8, 0x8e, 0x4b, 0xf7, 0x9b, 0xc5, 0x85, 0x58, 0xf4,
0xdf, 0x82, 0xe1, 0x84, 0xd5, 0xab, 0x16, 0x84, 0xe3, 0x93, 0xd8, 0x71, 0xab, 0xb0, 0xfc, 0xff, 0x35, 0xa8, 0x56, 0x58, 0x3d, 0xbd, 0xc8, 0x03, 0x9f, 0xc5, 0x81, 0x5b, 0x85, 0x65, 0xfb, 0x25,
0x12, 0xd1, 0xf1, 0xec, 0x77, 0x01, 0x29, 0x3d, 0xc3, 0x78, 0x94, 0xd1, 0x87, 0xb0, 0xe7, 0x7a, 0x42, 0xc7, 0xb3, 0xdf, 0x05, 0x24, 0xf5, 0x0c, 0xe3, 0x51, 0x46, 0xef, 0xc3, 0x9e, 0xe3, 0x4e,
0x13, 0xd2, 0x75, 0x96, 0xb7, 0xa2, 0x8c, 0x65, 0x1c, 0xad, 0x13, 0x63, 0x20, 0xff, 0x03, 0x6a, 0x48, 0xd7, 0x5a, 0xce, 0xe4, 0x2e, 0x88, 0xec, 0xc4, 0x18, 0x88, 0x3d, 0x20, 0x2d, 0xe3, 0x0f,
0x65, 0xfd, 0xa9, 0xc1, 0xa3, 0x50, 0x64, 0x32, 0x96, 0x05, 0x65, 0xe6, 0x13, 0x82, 0x3d, 0x8f, 0x05, 0x9e, 0x84, 0x22, 0x93, 0xb9, 0x0c, 0xa8, 0x50, 0x9f, 0x10, 0xec, 0xba, 0x34, 0x91, 0x2f,
0x25, 0xe2, 0xa5, 0x6c, 0xe8, 0x29, 0x54, 0xdc, 0x60, 0x36, 0xa3, 0x53, 0x4a, 0x7c, 0x01, 0xe9, 0xe5, 0x43, 0xcf, 0xa1, 0xea, 0x04, 0xf3, 0xb9, 0x3d, 0xb5, 0x89, 0xcf, 0x41, 0x22, 0x75, 0xda,
0x02, 0x4a, 0x1b, 0x39, 0x15, 0x29, 0x10, 0x54, 0x56, 0x52, 0x29, 0x63, 0x22, 0xbf, 0x5c, 0x2a, 0x89, 0x9a, 0x80, 0x22, 0x05, 0x23, 0x36, 0x49, 0x1c, 0x2a, 0x8e, 0xa8, 0x7b, 0xfe, 0x24, 0x98,
0xbf, 0x7f, 0x34, 0xa8, 0x86, 0xc5, 0x14, 0x99, 0x3d, 0x34, 0x49, 0x0b, 0xca, 0x63, 0x31, 0x6e, 0xe6, 0x53, 0x4c, 0xff, 0x51, 0x40, 0x0f, 0xcb, 0xca, 0x39, 0x3e, 0x96, 0xae, 0x01, 0x95, 0x31,
0xaf, 0x79, 0xe5, 0x7e, 0x54, 0xf2, 0x53, 0xb6, 0x2d, 0xe6, 0x27, 0x75, 0x7e, 0xa6, 0x6c, 0x6f, 0x1f, 0xbc, 0xb7, 0xac, 0x86, 0xdf, 0x4b, 0xb6, 0x29, 0xdf, 0x16, 0xe6, 0x07, 0x49, 0x33, 0xe5,
0xcb, 0xc8, 0xed, 0x92, 0xf1, 0x56, 0x49, 0xf2, 0x3b, 0x4a, 0x62, 0xfd, 0x0e, 0x4f, 0x42, 0x4d, 0xdb, 0x21, 0x28, 0xbf, 0x53, 0xd0, 0x7f, 0xca, 0x54, 0xb8, 0xa7, 0x4c, 0xc6, 0x6f, 0xf0, 0x2c,
0x03, 0xf1, 0xd7, 0x7d, 0xdf, 0x2e, 0xfe, 0x4f, 0x62, 0xac, 0xbf, 0x35, 0x38, 0x4a, 0x9e, 0xb1, 0x54, 0x37, 0xe0, 0xdb, 0xf9, 0xff, 0x76, 0xf6, 0x1d, 0xc9, 0x32, 0xfe, 0x52, 0xe0, 0x28, 0x79,
0x0f, 0xaa, 0x68, 0x1d, 0x0e, 0x9c, 0xf4, 0xf9, 0xac, 0xf2, 0xd8, 0x36, 0xbf, 0x67, 0xeb, 0x9b, 0xee, 0x3e, 0xaa, 0xb6, 0x75, 0x38, 0xb0, 0xd2, 0x67, 0xb6, 0xe4, 0xb1, 0xed, 0x66, 0xd5, 0x88,
0x80, 0x22, 0xc3, 0x88, 0x1f, 0x35, 0x89, 0xf2, 0xee, 0xf8, 0x62, 0xd5, 0x00, 0x3a, 0x6b, 0xba, 0x5c, 0x89, 0x49, 0x48, 0x3b, 0x1f, 0x5b, 0x63, 0xa3, 0x06, 0xd0, 0x59, 0xdb, 0x4b, 0xa1, 0x25,
0x94, 0x5a, 0x12, 0x77, 0xa3, 0x56, 0xdf, 0x53, 0x77, 0xe3, 0x73, 0x30, 0xe5, 0x11, 0x63, 0xfb, 0x71, 0x5f, 0x2a, 0xf5, 0x3d, 0x79, 0x5f, 0xbe, 0x04, 0x4d, 0x1c, 0x3b, 0xa6, 0x4f, 0xc8, 0x1b,
0x84, 0xbc, 0x22, 0xce, 0x8a, 0xa4, 0xef, 0xd0, 0xb2, 0xe2, 0x9e, 0xc1, 0x41, 0xcc, 0x71, 0x7d, 0x62, 0xad, 0x48, 0xfa, 0x5e, 0xad, 0x48, 0xdc, 0x0b, 0x38, 0x88, 0x71, 0x4c, 0xdf, 0xfd, 0xb0,
0xbb, 0xb1, 0x3f, 0xb4, 0x24, 0x37, 0xf4, 0xbd, 0x15, 0xe1, 0x5d, 0xf2, 0x93, 0x45, 0x32, 0x70, 0xdf, 0x95, 0x24, 0x6e, 0xe8, 0xbb, 0x2b, 0xc2, 0xba, 0xe4, 0xa7, 0x8b, 0x14, 0xd9, 0xec, 0x1f,
0xb4, 0xe6, 0xdf, 0xc4, 0xed, 0x33, 0x22, 0xf2, 0xd4, 0x36, 0x70, 0xb4, 0x46, 0x1f, 0x03, 0x2c, 0xbf, 0x91, 0x46, 0x44, 0x9c, 0xe4, 0x2a, 0x8e, 0x6c, 0xf4, 0x21, 0x80, 0x27, 0x0e, 0xc8, 0x09,
0xe4, 0x61, 0x38, 0x21, 0x6b, 0x51, 0x8f, 0x0a, 0x4e, 0x58, 0xd0, 0x47, 0x60, 0xb8, 0xc1, 0x5c, 0x59, 0xf3, 0x7a, 0x54, 0x71, 0xc2, 0x83, 0x3e, 0x00, 0xd5, 0x09, 0x16, 0x82, 0x33, 0xaf, 0x41,
0xe6, 0x2c, 0x6a, 0x50, 0xc1, 0xb1, 0xa1, 0xf1, 0x33, 0x40, 0xfc, 0xf2, 0x40, 0x25, 0x28, 0x9e, 0x15, 0xc7, 0x0e, 0xa4, 0x43, 0x69, 0x46, 0xe6, 0x1e, 0xf1, 0x97, 0x72, 0xb0, 0x42, 0x93, 0xdd,
0x77, 0x86, 0x83, 0x51, 0xcf, 0x36, 0x33, 0xa8, 0x0c, 0x7b, 0x57, 0x3d, 0xbb, 0x7b, 0x8e, 0xdb, 0x90, 0x9c, 0x9c, 0x45, 0x67, 0x98, 0xfc, 0xf2, 0x10, 0xbd, 0x39, 0xb1, 0xa6, 0x89, 0x5d, 0x1c,
0x57, 0xa6, 0x86, 0x0e, 0xa1, 0x62, 0xe3, 0x76, 0x7f, 0xf4, 0x7d, 0x07, 0xf7, 0xfa, 0xc3, 0x4b, 0xd9, 0x8d, 0x1f, 0x01, 0xe2, 0xe7, 0x0e, 0x2a, 0x43, 0xe9, 0xbc, 0x33, 0x1c, 0x8c, 0x7a, 0xa6,
0xdb, 0xd4, 0x11, 0x82, 0xfd, 0xd0, 0x34, 0xb8, 0xb4, 0xb9, 0x2d, 0x8b, 0x2a, 0x60, 0xb4, 0x2f, 0x96, 0x41, 0x15, 0xd8, 0xbb, 0xea, 0x99, 0xdd, 0x73, 0xdc, 0xbe, 0xd2, 0x14, 0x74, 0x08, 0x55,
0xed, 0xee, 0x00, 0xf7, 0xae, 0x3b, 0x66, 0xae, 0xf1, 0x1d, 0x18, 0xd1, 0x0b, 0x88, 0x47, 0xbf, 0x13, 0xb7, 0xfb, 0xa3, 0x6f, 0x3b, 0xb8, 0xd7, 0x1f, 0x5e, 0x9a, 0x5a, 0x16, 0x21, 0xd8, 0x0f,
0xec, 0xbf, 0xec, 0x0f, 0xae, 0xfa, 0x66, 0x06, 0x01, 0x14, 0x4e, 0x5f, 0x8d, 0x8e, 0x5f, 0xbc, 0x5d, 0x83, 0x4b, 0x93, 0xf9, 0x72, 0xa8, 0x0a, 0x6a, 0xfb, 0xd2, 0xec, 0x0e, 0x70, 0xef, 0xba,
0x30, 0xb5, 0xf0, 0xf7, 0x37, 0x5f, 0x9a, 0x3a, 0x32, 0x20, 0x7f, 0xda, 0x6f, 0x7d, 0x7d, 0x62, 0xa3, 0xe5, 0x1b, 0xdf, 0x80, 0x1a, 0x3d, 0xbb, 0x58, 0xf6, 0xcb, 0xfe, 0xeb, 0xfe, 0xe0, 0xaa,
0x66, 0x1b, 0x4d, 0xa8, 0xa4, 0x9e, 0x10, 0x3c, 0x78, 0x74, 0xef, 0x9b, 0x19, 0xb4, 0x0f, 0x10, 0xaf, 0x65, 0x10, 0x40, 0xf1, 0xf4, 0xcd, 0xe8, 0xf8, 0xd5, 0x2b, 0x4d, 0x09, 0xbf, 0xbf, 0xfa,
0xbf, 0x69, 0x4c, 0xad, 0xf1, 0x29, 0x94, 0x93, 0x27, 0x39, 0x2a, 0x42, 0xb6, 0x3d, 0x99, 0xc8, 0x5c, 0xcb, 0x22, 0x15, 0x0a, 0xa7, 0xfd, 0xd6, 0x97, 0x27, 0x5a, 0xae, 0xd1, 0x84, 0x6a, 0xea,
0xbd, 0xce, 0xc9, 0x8c, 0x30, 0x62, 0x6a, 0x37, 0x05, 0xf1, 0x8c, 0x3b, 0xfe, 0x2f, 0x00, 0x00, 0xdd, 0xc2, 0x92, 0x47, 0x8f, 0x0d, 0x2d, 0x83, 0xf6, 0x01, 0xe2, 0x87, 0x94, 0xa6, 0x34, 0x3e,
0xff, 0xff, 0x0c, 0x83, 0xfc, 0xbb, 0xd3, 0x09, 0x00, 0x00, 0x86, 0x4a, 0xf2, 0xfa, 0x40, 0x25, 0xc8, 0xb5, 0x27, 0x13, 0xb1, 0xd6, 0x39, 0x99, 0x13, 0x4a,
0x34, 0xe5, 0xa6, 0xc8, 0xdf, 0x8e, 0xc7, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x98, 0xff, 0x1c,
0xdb, 0x48, 0x0a, 0x00, 0x00,
} }
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