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

support token asset to mix

parent ffc16dbd
......@@ -203,6 +203,17 @@ useBalance=false
ethMapFromExecutor="paracross"
ethMapFromSymbol="coins.bty"
[exec.sub.mix]
#私对私的交易费,交易比较大,需要多的手续费
txFee=0
#私对私token转账,花费token(true)还是BTY(false),
tokenFee=false
#curve H point
pointHX="10190477835300927557649934238820360529458681672073866116232821892325659279502"
pointHY="7969140283216448215269095418467361784159407896899334866715345504515077887397"
#电路最大支持1024个叶子hash,10 level, 配置可以小于1024,但不能大于
maxTreeLeaves=1024
#系统中所有的fork,默认用chain33的测试网络的
#但是我们可以替换
[fork.system]
......
......@@ -289,6 +289,17 @@ evmGasLimit=2000000
#evm内部调试输出,指令级的,默认关闭,0:关闭;1:打开
evmDebugEnable=0
[exec.sub.mix]
#私对私的交易费,交易比较大,需要多的手续费
txFee=100000000
#私对私token转账,花费token(true)还是BTY(false),
tokenFee=false
#curve H point
pointHX="10190477835300927557649934238820360529458681672073866116232821892325659279502"
pointHY="7969140283216448215269095418467361784159407896899334866715345504515077887397"
#电路最大支持1024个叶子hash,10 level, 配置可以小于1024,但不能大于
maxTreeLeaves=1024
[metrics]
#是否使能发送metrics数据的发送
enableMetrics=false
......
This diff is collapsed.
This diff is collapsed.
......@@ -15,11 +15,11 @@ import (
"github.com/pkg/errors"
)
func (a *action) authParamCheck(input *mixTy.AuthorizePublicInput) error {
func (a *action) authParamCheck(exec, symbol string, input *mixTy.AuthorizePublicInput) error {
//check tree rootHash exist
exist, err := checkTreeRootHashExist(a.db, mixTy.Str2Byte(input.TreeRootHash))
exist, err := checkTreeRootHashExist(a.db, exec, symbol, mixTy.Str2Byte(input.TreeRootHash))
if err != nil {
return errors.Wrapf(err, "roothash=%s not found", input.TreeRootHash)
return errors.Wrapf(err, "roothash=%s not found,exec=%s,symbol=%s", input.TreeRootHash, exec, symbol)
}
if !exist {
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", input.TreeRootHash)
......@@ -54,7 +54,7 @@ func (a *action) authParamCheck(input *mixTy.AuthorizePublicInput) error {
return nil
}
func (a *action) authorizeVerify(proof *mixTy.ZkProofInfo) (*mixTy.AuthorizePublicInput, error) {
func (a *action) authorizeVerify(exec, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.AuthorizePublicInput, error) {
var input mixTy.AuthorizePublicInput
data, err := hex.DecodeString(proof.PublicInput)
if err != nil {
......@@ -65,7 +65,7 @@ func (a *action) authorizeVerify(proof *mixTy.ZkProofInfo) (*mixTy.AuthorizePubl
return nil, errors.Wrapf(err, "unmarshal string=%s", proof.PublicInput)
}
err = a.authParamCheck(&input)
err = a.authParamCheck(exec, symbol, &input)
if err != nil {
return nil, err
}
......@@ -90,7 +90,8 @@ func (a *action) authorizeVerify(proof *mixTy.ZkProofInfo) (*mixTy.AuthorizePubl
func (a *action) Authorize(authorize *mixTy.MixAuthorizeAction) (*types.Receipt, error) {
var inputs []*mixTy.AuthorizePublicInput
in, err := a.authorizeVerify(authorize.Proof)
execer, symbol := mixTy.GetAssetExecSymbol(a.api.GetConfig(), authorize.AssetExec, authorize.AssetSymbol)
in, err := a.authorizeVerify(execer, symbol, authorize.Proof)
if err != nil {
return nil, err
}
......
This diff is collapsed.
......@@ -158,7 +158,7 @@ func (a *action) ConfigDeleteAuthPubKey(key string) (*types.Receipt, error) {
}
func makeConfigPaymentKeyReceipt(data *mixTy.PaymentKey) *types.Receipt {
key := getPaymentPubKey(data.Addr)
key := calcReceivingKey(data.Addr)
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
......@@ -172,7 +172,7 @@ func makeConfigPaymentKeyReceipt(data *mixTy.PaymentKey) *types.Receipt {
}
func GetPaymentPubKey(db dbm.KV, addr string) (*mixTy.PaymentKey, error) {
key := getPaymentPubKey(addr)
key := calcReceivingKey(addr)
v, err := db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db")
......
......@@ -97,9 +97,10 @@ func (a *action) Deposit(deposit *mixTy.MixDepositAction) (*types.Receipt, error
//存款
cfg := a.api.GetConfig()
accoutDb, err := createAccount(cfg, "", "", a.db)
execer, symbol := mixTy.GetAssetExecSymbol(cfg, deposit.AssetExec, deposit.AssetSymbol)
accoutDb, err := createAccount(cfg, execer, symbol, a.db)
if err != nil {
return nil, errors.Wrapf(err, "createAccount")
return nil, errors.Wrapf(err, "createAccount,execer=%s,symbol=%s", execer, symbol)
}
//主链上存入toAddr为mix 执行器地址,平行链上为user.p.{}.mix执行器地址,execAddr和toAddr一致
execAddr := address.ExecAddress(string(a.tx.Execer))
......@@ -112,7 +113,9 @@ func (a *action) Deposit(deposit *mixTy.MixDepositAction) (*types.Receipt, error
for _, n := range notes {
leaves = append(leaves, mixTy.Str2Byte(n))
}
rpt, err := pushTree(a.db, leaves)
conf := types.ConfSub(cfg, mixTy.MixX)
maxTreeLeaves := conf.GInt("maxTreeLeaves")
rpt, err := pushTree(a.db, execer, symbol, leaves, int32(maxTreeLeaves))
if err != nil {
return nil, errors.Wrap(err, "pushTree")
}
......
......@@ -9,9 +9,9 @@ import (
)
var (
verifyKeys string
authPubKeys string
paymentPubKey string
verifyKeys string
authPubKeys string
receivingKey string
commitTreeCurrentStatus string
commitTreeSubRoots string
......@@ -27,7 +27,7 @@ var (
func setPrefix() {
verifyKeys = "mavl-mix-verify-keys-"
authPubKeys = "mavl-mix-auth-pubkeys-"
paymentPubKey = "mavl-mix-payment-pubkey-"
receivingKey = "mavl-mix-receiving-key-"
commitTreeCurrentStatus = "mavl-mix-commitTree-current-status-"
......@@ -51,28 +51,28 @@ func getAuthPubKeysKey() []byte {
return []byte(fmt.Sprintf(authPubKeys))
}
func getPaymentPubKey(addr string) []byte {
return []byte(fmt.Sprintf(paymentPubKey+"%s", addr))
func calcReceivingKey(addr string) []byte {
return []byte(fmt.Sprintf(receivingKey+"%s", addr))
}
func calcCommitTreeCurrentStatusKey() []byte {
return []byte(fmt.Sprintf(commitTreeCurrentStatus))
func calcCommitTreeCurrentStatusKey(exec, symbol string) []byte {
return []byte(fmt.Sprintf(commitTreeCurrentStatus+"%s-%s", exec, symbol))
}
func calcArchiveRootsKey(seq uint64) []byte {
return []byte(fmt.Sprintf(commitTreeArchiveRoots+"%022d", seq))
func calcArchiveRootsKey(exec, symbol string, seq uint64) []byte {
return []byte(fmt.Sprintf(commitTreeArchiveRoots+"%s-%s-%022d", exec, symbol, seq))
}
func calcSubRootsKey(seq int32) []byte {
return []byte(fmt.Sprintf(commitTreeSubRoots+"%010d", seq))
func calcSubRootsKey(exec, symbol string, seq int32) []byte {
return []byte(fmt.Sprintf(commitTreeSubRoots+"%s-%s-%010d", exec, symbol, seq))
}
func calcSubLeavesKey(seq int32) []byte {
return []byte(fmt.Sprintf(commitTreeSubLeaves+"%010d", seq))
func calcSubLeavesKey(exec, symbol string, seq int32) []byte {
return []byte(fmt.Sprintf(commitTreeSubLeaves+"%s-%s-%010d", exec, symbol, seq))
}
func calcCommitTreeRootLeaves(rootHash string) []byte {
return []byte(fmt.Sprintf(commitTreeRootLeaves+"%s", rootHash))
func calcCommitTreeRootLeaves(exec, symbol string, rootHash string) []byte {
return []byte(fmt.Sprintf(commitTreeRootLeaves+"%s-%s-%s", exec, symbol, rootHash))
}
func calcAuthorizeHashKey(hash string) []byte {
......
......@@ -63,7 +63,8 @@ func (m *Mix) CheckTx(tx *types.Transaction, index int) error {
// mix隐私交易,只私对私需要特殊签名验证
return m.DriverBase.CheckTx(tx, index)
}
_, _, err := MixTransferInfoVerify(m.GetStateDB(), action.GetTransfer())
_, _, err := MixTransferInfoVerify(m.GetAPI().GetConfig(), m.GetStateDB(), action.GetTransfer())
if err != nil {
mlog.Error("checkTx", "err", err, "txhash", common.ToHex(tx.Hash()))
return err
......
......@@ -5,6 +5,7 @@
package executor
import (
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
......@@ -16,7 +17,7 @@ func (m *Mix) Query_GetTreePath(in *mixTy.TreeInfoReq) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
return CalcTreeProve(m.GetStateDB(), in.RootHash, in.LeafHash)
return CalcTreeProve(m.GetStateDB(), in.AssetExec, in.AssetSymbol, in.RootHash, in.LeafHash)
}
// Query_GetTreeList query paracross title
......@@ -27,18 +28,18 @@ func (m *Mix) Query_GetLeavesList(in *mixTy.TreeInfoReq) (types.Message, error)
var leaves *mixTy.CommitTreeLeaves
if len(in.RootHash) > 0 {
l, err := getCommitLeaves(m.GetStateDB(), calcCommitTreeRootLeaves(in.RootHash))
l, err := getCommitLeaves(m.GetStateDB(), calcCommitTreeRootLeaves(in.AssetExec, in.AssetSymbol, in.RootHash))
if err != nil {
return nil, err
}
leaves.Leaves = append(leaves.Leaves, l.Leaves...)
} else {
status, err := getCommitTreeStatus(m.GetStateDB())
status, err := getCommitTreeStatus(m.GetStateDB(), in.AssetExec, in.AssetSymbol)
if err != nil {
return nil, err
}
for i := int32(1); i <= status.SubLeavesSeq; i++ {
l, err := getCommitLeaves(m.GetStateDB(), calcSubLeavesKey(i))
l, err := getCommitLeaves(m.GetStateDB(), calcSubLeavesKey(in.AssetExec, in.AssetSymbol, i))
if err != nil {
return nil, errors.Wrapf(err, "get leaves of seq=%d", i)
}
......@@ -57,21 +58,21 @@ func (m *Mix) Query_GetLeavesList(in *mixTy.TreeInfoReq) (types.Message, error)
}
// Query_GetRootList query title
func (m *Mix) Query_GetRootList(in *types.ReqInt) (types.Message, error) {
func (m *Mix) Query_GetRootList(in *mixTy.TreeInfoReq) (types.Message, error) {
var roots mixTy.CommitTreeRoots
if in.Height > 0 {
r, err := getArchiveRoots(m.GetStateDB(), uint64(in.Height))
if in.RootHeight > 0 {
r, err := getArchiveRoots(m.GetStateDB(), in.AssetExec, in.AssetSymbol, in.RootHeight)
if err != nil {
return nil, err
}
roots.Roots = append(roots.Roots, r.Roots...)
} else {
status, err := getCommitTreeStatus(m.GetStateDB())
status, err := getCommitTreeStatus(m.GetStateDB(), in.AssetExec, in.AssetSymbol)
if err != nil {
return nil, err
}
for i := int32(1); i <= status.SubLeavesSeq; i++ {
r, err := getSubRoots(m.GetStateDB(), i)
r, err := getSubRoots(m.GetStateDB(), in.AssetExec, in.AssetSymbol, i)
if err != nil {
return nil, errors.Wrapf(err, "get roots of seq=%d", i)
}
......@@ -87,8 +88,8 @@ func (m *Mix) Query_GetRootList(in *types.ReqInt) (types.Message, error) {
return &resp, nil
}
func (m *Mix) Query_GetTreeStatus(in *types.ReqNil) (types.Message, error) {
status, err := getCommitTreeStatus(m.GetStateDB())
func (m *Mix) Query_GetTreeStatus(in *mixTy.TreeInfoReq) (types.Message, error) {
status, err := getCommitTreeStatus(m.GetStateDB(), in.AssetExec, in.AssetSymbol)
if err != nil {
return nil, err
}
......@@ -113,7 +114,16 @@ func (m *Mix) Query_PaymentPubKey(addr *types.ReqString) (types.Message, error)
}
// Query_PaymentPubKey 批量查询
// Query_VerifyProof 批量查询
func (m *Mix) Query_VerifyProof(req *mixTy.VerifyProofInfo) (types.Message, error) {
return &types.ReqNil{}, zkProofVerify(m.GetStateDB(), req.Proof, req.Ty)
}
// Query_TokenFeeAddr 私对私token转账,代扣地址查询, 需预先转账主代币到相应资产地址下面才能完成私对私的转账,代扣地址coins不能提回
func (m *Mix) Query_TokenFeeAddr(req *mixTy.TokenTxFee) (types.Message, error) {
if req == nil || len(req.AssetExec) == 0 || len(req.AssetSymbol) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "asset exec or symbol not filled")
}
return &types.ReplyString{Data: address.ExecAddress(mixTy.MixX + req.AssetExec + req.AssetSymbol)}, nil
}
......@@ -8,6 +8,8 @@ import (
"encoding/hex"
"encoding/json"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gurvy/bn256/twistededwards"
......@@ -21,7 +23,7 @@ import (
2. check if exist in authorize pool and nullifier pool
*/
func transferInputVerify(db dbm.KV, proof *mixTy.ZkProofInfo) (*mixTy.TransferInputPublicInput, error) {
func transferInputVerify(db dbm.KV, execer, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.TransferInputPublicInput, error) {
var input mixTy.TransferInputPublicInput
data, err := hex.DecodeString(proof.PublicInput)
if err != nil {
......@@ -32,7 +34,7 @@ func transferInputVerify(db dbm.KV, proof *mixTy.ZkProofInfo) (*mixTy.TransferIn
return nil, errors.Wrapf(err, "transferInput verify unmarshal string=%s", proof.PublicInput)
}
err = spendVerify(db, input.TreeRootHash, input.NullifierHash, input.AuthorizeSpendHash)
err = spendVerify(db, execer, symbol, input.TreeRootHash, input.NullifierHash, input.AuthorizeSpendHash)
if err != nil {
return nil, errors.Wrap(err, "transferInput verify spendVerify")
}
......@@ -71,7 +73,7 @@ func transferOutputVerify(db dbm.KV, proof *mixTy.ZkProofInfo) (*mixTy.TransferO
}
func VerifyCommitValues(inputs []*mixTy.TransferInputPublicInput, outputs []*mixTy.TransferOutputPublicInput) bool {
func VerifyCommitValues(inputs []*mixTy.TransferInputPublicInput, outputs []*mixTy.TransferOutputPublicInput, txFee uint64) bool {
var inputPoints, outputPoints []*twistededwards.Point
for _, in := range inputs {
var p twistededwards.Point
......@@ -89,7 +91,7 @@ func VerifyCommitValues(inputs []*mixTy.TransferInputPublicInput, outputs []*mix
//out value add fee
//对于平行链来说, 隐私交易需要一个公共账户扣主链的手续费,隐私交易只需要扣平行链执行器内的费用即可
//由于平行链的隐私交易没有实际扣平行链mix合约的手续费,平行链Mix合约会有手续费留下,平行链隐私可以考虑手续费为0
outputPoints = append(outputPoints, mixTy.MulCurvePointG(uint64(mixTy.Privacy2PrivacyTxFee)))
outputPoints = append(outputPoints, mixTy.MulCurvePointG(txFee))
//sum input and output
sumInput := inputPoints[0]
......@@ -107,13 +109,15 @@ func VerifyCommitValues(inputs []*mixTy.TransferInputPublicInput, outputs []*mix
return false
}
func MixTransferInfoVerify(db dbm.KV, transfer *mixTy.MixTransferAction) ([]*mixTy.TransferInputPublicInput, []*mixTy.TransferOutputPublicInput, error) {
func MixTransferInfoVerify(cfg *types.Chain33Config, db dbm.KV, transfer *mixTy.MixTransferAction) ([]*mixTy.TransferInputPublicInput, []*mixTy.TransferOutputPublicInput, error) {
var inputs []*mixTy.TransferInputPublicInput
var outputs []*mixTy.TransferOutputPublicInput
execer, symbol := mixTy.GetAssetExecSymbol(cfg, transfer.AssetExec, transfer.AssetSymbol)
txFee := mixTy.GetTransferTxFee(cfg, execer)
//inputs
for _, i := range transfer.Inputs {
in, err := transferInputVerify(db, i)
in, err := transferInputVerify(db, execer, symbol, i)
if err != nil {
return nil, nil, err
}
......@@ -134,25 +138,63 @@ func MixTransferInfoVerify(db dbm.KV, transfer *mixTy.MixTransferAction) ([]*mix
}
outputs = append(outputs, change)
if !VerifyCommitValues(inputs, outputs) {
if !VerifyCommitValues(inputs, outputs, uint64(txFee)) {
return nil, nil, errors.Wrap(mixTy.ErrSpendInOutValueNotMatch, "verify shieldValue")
}
return inputs, outputs, nil
}
//1. 如果
func (a *action) processTransferFee(exec, symbol string) (*types.Receipt, error) {
cfg := a.api.GetConfig()
accoutDb, err := createAccount(cfg, exec, symbol, a.db)
if err != nil {
return nil, err
}
txFee := mixTy.GetTransferTxFee(cfg, exec)
execAddr := address.ExecAddress(string(a.tx.Execer))
//需要mix执行器下的mix账户扣fee, 和mix 扣coins或token手续费保持一致,不然会看到mix的coins账户下和mix的mix账户下不一致
accFrom := accoutDb.LoadExecAccount(execAddr, execAddr)
if accFrom.GetBalance()-txFee >= 0 {
copyfrom := *accFrom
accFrom.Balance = accFrom.GetBalance() - txFee
receiptBalance := &types.ReceiptAccountTransfer{Prev: &copyfrom, Current: accFrom}
set := accoutDb.GetExecKVSet(execAddr, accFrom)
feelog := &types.ReceiptLog{Ty: types.TyLogFee, Log: types.Encode(receiptBalance)}
return &types.Receipt{
Ty: types.ExecOk,
KV: set,
Logs: append([]*types.ReceiptLog{}, feelog),
}, nil
}
return nil, types.ErrNoBalance
}
/*
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) {
inputs, outputs, err := MixTransferInfoVerify(a.db, transfer)
inputs, outputs, err := MixTransferInfoVerify(a.api.GetConfig(), a.db, transfer)
if err != nil {
return nil, errors.Wrap(err, "Transfer.MixTransferInfoVerify")
}
receipt := &types.Receipt{Ty: types.ExecOk}
execer, symbol := mixTy.GetAssetExecSymbol(a.api.GetConfig(), transfer.AssetExec, transfer.AssetSymbol)
//扣除交易费
rTxFee, err := a.processTransferFee(execer, symbol)
if err != nil {
return nil, errors.Wrapf(err, "processTransferFee fail")
}
mergeReceipt(receipt, rTxFee)
for _, k := range inputs {
r := makeNullifierSetReceipt(k.NullifierHash, &mixTy.ExistValue{Nullifier: k.NullifierHash, Exist: true})
mergeReceipt(receipt, r)
......@@ -163,7 +205,10 @@ func (a *action) Transfer(transfer *mixTy.MixTransferAction) (*types.Receipt, er
for _, h := range outputs {
leaves = append(leaves, mixTy.Str2Byte(h.NoteHash))
}
rpt, err := pushTree(a.db, leaves)
conf := types.ConfSub(a.api.GetConfig(), mixTy.MixX)
maxTreeLeaves := conf.GInt("maxTreeLeaves")
rpt, err := pushTree(a.db, execer, symbol, leaves, int32(maxTreeLeaves))
if err != nil {
return nil, errors.Wrap(err, "transfer.pushTree")
}
......
......@@ -16,10 +16,10 @@ import (
"github.com/pkg/errors"
)
func spendVerify(db dbm.KV, treeRootHash, nulliferHash, authorizeSpendHash string) error {
func spendVerify(db dbm.KV, exec, symbol string, treeRootHash, nulliferHash, authorizeSpendHash string) error {
//zk-proof校验
//check tree rootHash exist
exist, err := checkTreeRootHashExist(db, mixTy.Str2Byte(treeRootHash))
exist, err := checkTreeRootHashExist(db, exec, symbol, mixTy.Str2Byte(treeRootHash))
if err != nil {
return errors.Wrapf(err, "roothash=%s not found", treeRootHash)
}
......@@ -50,7 +50,7 @@ func spendVerify(db dbm.KV, treeRootHash, nulliferHash, authorizeSpendHash strin
}
func (a *action) withdrawVerify(proof *mixTy.ZkProofInfo) (string, uint64, error) {
func (a *action) withdrawVerify(exec, symbol string, proof *mixTy.ZkProofInfo) (string, uint64, error) {
var input mixTy.WithdrawPublicInput
data, err := hex.DecodeString(proof.PublicInput)
if err != nil {
......@@ -65,7 +65,7 @@ func (a *action) withdrawVerify(proof *mixTy.ZkProofInfo) (string, uint64, error
return "", 0, errors.Wrapf(err, "parseUint=%s", input.Amount)
}
err = spendVerify(a.db, input.TreeRootHash, input.NullifierHash, input.AuthorizeSpendHash)
err = spendVerify(a.db, exec, symbol, input.TreeRootHash, input.NullifierHash, input.AuthorizeSpendHash)
if err != nil {
return "", 0, err
}
......@@ -85,10 +85,12 @@ func (a *action) withdrawVerify(proof *mixTy.ZkProofInfo) (string, uint64, error
3. set nullifier exist
*/
func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, error) {
exec, symbol := mixTy.GetAssetExecSymbol(a.api.GetConfig(), withdraw.AssetExec, withdraw.AssetSymbol)
var nulliferSet []string
var sumValue uint64
for _, k := range withdraw.Proofs {
nulfier, v, err := a.withdrawVerify(k)
nulfier, v, err := a.withdrawVerify(exec, symbol, k)
if err != nil {
return nil, err
}
......@@ -102,7 +104,7 @@ func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, er
//withdraw value
cfg := a.api.GetConfig()
accoutDb, err := createAccount(cfg, "", "", a.db)
accoutDb, err := createAccount(cfg, exec, symbol, a.db)
if err != nil {
return nil, err
}
......
......@@ -60,7 +60,8 @@ message MixConfigAction {
oneof value {
ZkVerifyKey verifyKey = 3;
string authKey = 4;
PaymentKey paymentKey = 5;
PaymentKey paymentKey = 5;
}
}
......@@ -84,25 +85,34 @@ message ZkProofInfo {
}
message MixDepositAction {
repeated ZkProofInfo proofs = 1;
string assetExec = 1;
string assetSymbol = 2;
repeated ZkProofInfo proofs = 3;
}
message MixTransferAction {
repeated ZkProofInfo inputs = 1;
ZkProofInfo output = 2;
ZkProofInfo change = 3;
string assetExec = 1;
string assetSymbol = 2;
repeated ZkProofInfo inputs = 3;
ZkProofInfo output = 4;
ZkProofInfo change = 5;
}
message MixWithdrawAction {
uint64 amount = 1;
repeated ZkProofInfo proofs = 2;
string assetExec = 1;
string assetSymbol = 2;
uint64 amount = 3;
repeated ZkProofInfo proofs = 4;
}
message MixAuthorizeAction {
ZkProofInfo proof = 1;
string assetExec = 1;
string assetSymbol = 2;
ZkProofInfo proof = 3;
}
......@@ -190,6 +200,8 @@ message CommitTreeStatus{
int32 subLeavesSeq = 2;
//root的归档 从1开始,数据库占位,不然全空会往前搜索
uint64 archiveRootsSeq = 3;
string assetExec = 4;
string assetSymbol = 5;
}
......@@ -239,6 +251,9 @@ message CommitTreeProve {
message TreeInfoReq{
string rootHash = 1;
string leafHash = 2;
string assetExec = 3;
string assetSymbol = 4;
uint64 rootHeight = 5;
}
message TreeListResp{
......@@ -295,6 +310,8 @@ message SecretData{
string authorizeKey = 3;
string amount = 4;
string noteRandom = 5;
string assetExec = 6;
string assetSymbol = 7;
}
......@@ -351,17 +368,6 @@ message WithdrawTxReq{
}
message WithdrawProofRe{
SecretData secret = 1;
string nullifierHash = 2;
string authorizeSpendHash = 3;
string noteHash = 4;
string spendPrivKey = 5;
string spendFlag = 6;
string authorizeFlag = 7;
TreePathProof treeProof = 8;
}
//只授权一个note,超过一个,toAddr不好设置
message AuthTxReq{
......@@ -370,17 +376,6 @@ message AuthTxReq{
string zkPath = 4;
}
message AuthProofRe{
SecretData proof = 1;
string authPubKey = 2;
string authPrivKey = 3;
string authHash = 4;
string authorizeSpendHash = 5;
string noteHash = 6;
string spendFlag = 7;
TreePathProof treeProof = 8;
}
message TransferInputTxReq{
string noteHashs = 1;
......@@ -403,33 +398,7 @@ message ShieldAmount{
string Y = 2;
}
message TransferInputProof{
SecretData proof = 1;
string nullifierHash = 2;
string authorizeSpendHash = 3;
string noteHash = 4;
string spendPrivKey = 5;
string spendFlag = 6;
string authorizeFlag = 7;
TreePathProof treeProof = 8;
ShieldAmount shieldAmount = 9;
string amountRandom = 10;
}
message TransferOutputProof{
SecretData proof = 1;
string noteHash = 2;
DHSecretGroup secrets = 3;
ShieldAmount shieldAmount = 4;
string amountRandom = 5;
}
message TransferProofResp{
TransferInputProof transferInput = 1;
TransferOutputProof targetOutput = 2;
TransferOutputProof changeOutput = 3;
}
message ShieldAmountRst{
repeated string inputRandoms = 1;
......@@ -445,7 +414,7 @@ message CreateRawTxReq{
int32 actionTy = 1;
bytes data = 4;
string assetExec = 2;
string assetToken = 3;
string assetSymbol = 3;
string title = 6; //平行链名字
int32 privacy = 7; //1:打印隐私数据
int32 verify = 8; //0:链上验证,1:本地验证
......@@ -476,6 +445,7 @@ message WalletNoteInfo {
string authorizeHash = 4;
string account = 5; //账户地址
NoteStatus status = 6;
SecretData secret = 7;
}
......@@ -487,14 +457,14 @@ message WalletDbMixInfo {
message WalletMixIndexReq {
string noteHash = 1;
string nullifier = 2;
string noteHash = 1;
string nullifier = 2;
string authorizeSpendHash = 3;
string authorizeHash = 4;
string account = 5;
int32 status = 6;
int32 count = 7;
int32 direction = 8;
string account = 5;
int32 status = 6;
int32 count = 7;
int32 direction = 8;
}
message WalletNoteResp {
......
......@@ -6,14 +6,13 @@ package types
import (
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
var tlog = log15.New("module", MixX)
const (
MaxTreeLeaves = 1024
TreeLevel = 10
//MaxTreeLeaves = 1024
TreeLevel = 10
)
// 执行器的日志类型
......@@ -45,15 +44,6 @@ const (
MixActionAuth
)
//curve H point
const (
PointHX = "10190477835300927557649934238820360529458681672073866116232821892325659279502"
PointHY = "7969140283216448215269095418467361784159407896899334866715345504515077887397"
)
//mix transfer tx fee
const Privacy2PrivacyTxFee = types.Coin
//circuits default file name
const (
DepositCircuit = "circuit_deposit.r1cs"
......
This diff is collapsed.
......@@ -13,7 +13,9 @@ import (
"github.com/pkg/errors"
log "github.com/33cn/chain33/common/log/log15"
coins "github.com/33cn/chain33/system/dapp/coins/types"
"github.com/33cn/chain33/types"
token "github.com/33cn/plugin/plugin/dapp/token/types"
"github.com/consensys/gurvy/bn256/fr"
"github.com/consensys/gurvy/bn256/twistededwards"
)
......@@ -150,12 +152,12 @@ func MulCurvePointG(val interface{}) *twistededwards.Point {
return &point
}
func MulCurvePointH(val string) *twistededwards.Point {
func MulCurvePointH(pointHX, pointHY, val string) *twistededwards.Point {
v := fr.FromInterface(val)
var pointV, pointH twistededwards.Point
pointH.X.SetString(PointHX)
pointH.Y.SetString(PointHY)
pointH.X.SetString(pointHX)
pointH.Y.SetString(pointHY)
pointV.ScalarMul(&pointH, *v.FromMont())
return &pointV
......@@ -216,3 +218,25 @@ func GetFrRandom() string {
var f fr.Element
return f.SetRandom().String()
}
func GetAssetExecSymbol(cfg *types.Chain33Config, execer, symbol string) (string, string) {
if symbol == "" {
return coins.CoinsX, cfg.GetCoinSymbol()
}
if execer == "" {
return token.TokenX, symbol
}
return execer, symbol
}
func GetTransferTxFee(cfg *types.Chain33Config, assetExecer string) int64 {
conf := types.ConfSub(cfg, MixX)
txFee := conf.GInt("txFee")
tokenFee := conf.IsEnable("tokenFee")
//一切非coins的token资产 在tokenFee=false都不收txfee,特殊地址代扣
if assetExecer != coins.CoinsX && !tokenFee {
return 0
}
//tokenFee=true或者coins都按txfee数量收txFee
return txFee
}
......@@ -288,7 +288,7 @@ func (p *mixPolicy) rescanNotes() {
// 1 先获取隐私合约地址相关交易
var reqInfo mixTy.MixTxListReq
reqInfo.Direction = 0
reqInfo.Count = int32(MaxTxHashsPerTime)
reqInfo.Count = int32(maxTxHashsPerTime)
if i == 0 {
reqInfo.Height = -1
......@@ -327,7 +327,7 @@ func (p *mixPolicy) rescanNotes() {
}
p.processPrivcyTxs(&ReqHashes)
if txcount < int(MaxTxHashsPerTime) {
if txcount < int(maxTxHashsPerTime) {
break
}
}
......
......@@ -15,17 +15,17 @@ import (
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/log/log15"
coins "github.com/33cn/chain33/system/dapp/coins/types"
"github.com/33cn/chain33/types"
wcom "github.com/33cn/chain33/wallet/common"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
var (
bizlog = log15.New("module", "wallet.mix")
// MaxTxHashsPerTime 单词处理的最大哈希书
MaxTxHashsPerTime int64 = 100
// maxTxNumPerBlock 单个区块最大数
maxTxNumPerBlock int64 = types.MaxTxsPerBlock
maxTxHashsPerTime int64 = 100
)
func init() {
......@@ -168,7 +168,10 @@ func (policy *mixPolicy) SignTransaction(key crypto.PrivKey, req *types.ReqSignR
}
if action.Ty == mixTy.MixActionTransfer {
// 隐私交易的私对私、私对公需要进行特殊签名
policy.signatureTx(tx, action.GetTransfer())
err = policy.signatureTx(tx, action.GetTransfer())
if err != nil {
return
}
} else {
tx.Sign(int32(policy.getWalletOperate().GetSignType()), key)
}
......@@ -178,14 +181,30 @@ func (policy *mixPolicy) SignTransaction(key crypto.PrivKey, req *types.ReqSignR
}
func (policy *mixPolicy) signatureTx(tx *types.Transaction, transfer *mixTy.MixTransferAction) error {
if len(transfer.AssetSymbol) == 0 || len(transfer.AssetExec) == 0 {
return errors.Wrapf(types.ErrInvalidParam, "asset exec or symbol need be fill")
}
//1.如果是coins 执行器,默认符号是BTY,扣mix执行器地址的手续费
//2.如果token执行器, 如果tokenFee=false,则不扣token,且不以token做交易费,需要从另一个特殊地址mixtoken扣bty交易费,chain33发交易费给mixtoken地址
// 不然从mix执行器扣交易费会导致基于coins的隐私余额 入账和出账不平
//3.如果配置项tokenFee=true 则从以token扣手续费,地址是mix执行器的token资产
cfg := policy.getWalletOperate().GetAPI().GetConfig()
conf := types.ConfSub(cfg, mixTy.MixX)
tokenFee := conf.IsEnable("tokenFee")
payFeeAddr := mixTy.MixX
if transfer.AssetExec != coins.CoinsX && !tokenFee {
payFeeAddr = mixTy.MixX + transfer.AssetExec + transfer.AssetSymbol
}
mixSignData := types.Encode(transfer)
tx.Fee = mixTy.Privacy2PrivacyTxFee
tx.Fee = conf.GInt("txFee")
tx.Signature = &types.Signature{
Ty: MixSignID,
Signature: common.BytesToHash(mixSignData).Bytes(),
// 这里填的是mix合约的公钥,让框架保持一致
Pubkey: address.ExecPubKey(cfg.ExecName(mixTy.MixX)),
Pubkey: address.ExecPubKey(payFeeAddr),
}
return nil
}
......@@ -112,7 +112,7 @@ func (p *mixPolicy) getAuthParms(req *mixTy.AuthTxReq) (*AuthorizeInput, error)
}
//get tree path
treeProof, err := p.getTreeProof(note.NoteHash)
treeProof, err := p.getTreeProof(note.Secret.AssetExec, note.Secret.AssetSymbol, note.NoteHash)
if err != nil {
return nil, errors.Wrapf(err, "getTreeProof for hash=%s", note.NoteHash)
}
......@@ -134,6 +134,10 @@ func (p *mixPolicy) createAuthTx(req *mixTy.CreateRawTxReq) (*types.Transaction,
return nil, err
}
if len(req.AssetExec) == 0 || len(req.AssetSymbol) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "asset exec=%s or symbol=%s not filled", req.AssetExec, req.AssetSymbol)
}
proofInfo, err := getZkProofKeys(auth.ZkPath+mixTy.AuthCircuit, auth.ZkPath+mixTy.AuthPk, *input, req.Privacy)
if err != nil {
return nil, errors.Wrapf(err, "getZkProofKeys note=%s", auth.NoteHash)
......@@ -143,12 +147,14 @@ func (p *mixPolicy) createAuthTx(req *mixTy.CreateRawTxReq) (*types.Transaction,
return nil, errors.Wrapf(err, "verifyProof fail for note=%s", auth.NoteHash)
}
return p.getAuthTx(strings.TrimSpace(req.Title+mixTy.MixX), proofInfo)
return p.getAuthTx(strings.TrimSpace(req.Title+mixTy.MixX), req.AssetExec, req.AssetSymbol, proofInfo)
}
func (p *mixPolicy) getAuthTx(execName string, proof *mixTy.ZkProofInfo) (*types.Transaction, error) {
func (p *mixPolicy) getAuthTx(execName string, exec, symbol string, proof *mixTy.ZkProofInfo) (*types.Transaction, error) {
payload := &mixTy.MixAuthorizeAction{}
payload.Proof = proof
payload.AssetExec = exec
payload.AssetSymbol = symbol
cfg := p.getWalletOperate().GetAPI().GetConfig()
action := &mixTy.MixAction{
......
......@@ -32,12 +32,17 @@ type DepositInput struct {
NoteRandom string `tag:"secret"`
}
func (p *mixPolicy) depositParams(receiver, returner, auth, amount string) (*mixTy.DepositProofResp, error) {
func (p *mixPolicy) depositParams(exec, symbol, receiver, returner, auth, amount string) (*mixTy.DepositProofResp, error) {
if len(receiver) > 0 && len(returner) > 0 && (receiver == returner || receiver == auth || returner == auth) {
return nil, errors.Wrapf(types.ErrInvalidParam, "addrs should not be same to receiver=%s,return=%s,auth=%s",
receiver, returner, auth)
}
//deposit 产生的secret需要确定的资产符号
if len(exec) == 0 || len(symbol) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "asset exec=%s or symbol=%s not filled", exec, symbol)
}
if len(receiver) <= 0 {
return nil, errors.Wrap(types.ErrInvalidParam, "receiver is nil")
}
......@@ -49,6 +54,8 @@ func (p *mixPolicy) depositParams(receiver, returner, auth, amount string) (*mix
var secret mixTy.SecretData
secret.Amount = amount
secret.AssetExec = exec
secret.AssetSymbol = symbol
//1. nullifier 获取随机值
var fr fr_bn256.Element
......@@ -123,14 +130,15 @@ func (p *mixPolicy) depositParams(receiver, returner, auth, amount string) (*mix
secret.Amount,
secret.NoteRandom,
}
//exec,symbol没有计算进去,不然在电路中也要引入资产,noteRandom应该足够随机区分一个note了,不然Nullifier也要区分资产
resp.NoteHash = mixTy.Byte2Str(mimcHashString(keys))
return &resp, nil
}
func (p *mixPolicy) getDepositProof(receiver, returner, auth, amount, zkPath string, verifyOnChain, privacyPrint int32) (*mixTy.ZkProofInfo, error) {
func (p *mixPolicy) getDepositProof(exec, symbol, receiver, returner, auth, amount, zkPath string, verifyOnChain, privacyPrint int32) (*mixTy.ZkProofInfo, error) {
resp, err := p.depositParams(receiver, returner, auth, amount)
resp, err := p.depositParams(exec, symbol, receiver, returner, auth, amount)
if err != nil {
return nil, err
}
......@@ -180,20 +188,22 @@ func (p *mixPolicy) createDepositTx(req *mixTy.CreateRawTxReq) (*types.Transacti
var proofs []*mixTy.ZkProofInfo
for i, rcv := range receivers {
p, err := p.getDepositProof(rcv, deposit.Deposit.ReturnAddr, deposit.Deposit.AuthorizeAddr, amounts[i], deposit.ZkPath, req.Verify, req.Privacy)
p, err := p.getDepositProof(req.AssetExec, req.AssetSymbol, rcv, deposit.Deposit.ReturnAddr, deposit.Deposit.AuthorizeAddr, amounts[i], deposit.ZkPath, req.Verify, req.Privacy)
if err != nil {
return nil, errors.Wrapf(err, "get Deposit proof for=%s", rcv)
}
proofs = append(proofs, p)
}
return p.getDepositTx(strings.TrimSpace(req.Title+mixTy.MixX), proofs)
return p.getDepositTx(strings.TrimSpace(req.Title+mixTy.MixX), req.AssetExec, req.AssetSymbol, proofs)
}
func (p *mixPolicy) getDepositTx(execName string, proofs []*mixTy.ZkProofInfo) (*types.Transaction, error) {
func (p *mixPolicy) getDepositTx(execName string, assetExec, assetSymbol string, proofs []*mixTy.ZkProofInfo) (*types.Transaction, error) {
payload := &mixTy.MixDepositAction{}
payload.Proofs = proofs
payload.AssetExec = assetExec
payload.AssetSymbol = assetSymbol
cfg := p.getWalletOperate().GetAPI().GetConfig()
action := &mixTy.MixAction{
......
......@@ -132,7 +132,7 @@ func (p *mixPolicy) getTransferInputPart(note *mixTy.WalletNoteInfo) (*TransferI
input.AuthorizeFlag = "1"
}
treeProof, err := p.getTreeProof(note.NoteHash)
treeProof, err := p.getTreeProof(note.Secret.AssetExec, note.Secret.AssetSymbol, note.NoteHash)
if err != nil {
return nil, errors.Wrapf(err, "getTreeProof for hash=%s", note.NoteHash)
}
......@@ -142,13 +142,13 @@ func (p *mixPolicy) getTransferInputPart(note *mixTy.WalletNoteInfo) (*TransferI
return &input, nil
}
func (p *mixPolicy) getTransferOutput(req *mixTy.DepositInfo) (*TransferOutput, *mixTy.DHSecretGroup, error) {
func (p *mixPolicy) getTransferOutput(exec, symbol string, req *mixTy.DepositInfo) (*TransferOutput, *mixTy.DHSecretGroup, error) {
//目前只支持一个ReceiverAddr
if strings.Contains(req.ReceiverAddrs, ",") || strings.Contains(req.Amounts, ",") {
return nil, nil, errors.Wrapf(types.ErrInvalidParam, "only support one addr or amount,addrs=%s,amount=%s",
req.ReceiverAddrs, req.Amounts)
}
resp, err := p.depositParams(req.ReceiverAddrs, req.ReturnAddr, req.AuthorizeAddr, req.Amounts)
resp, err := p.depositParams(exec, symbol, req.ReceiverAddrs, req.ReturnAddr, req.AuthorizeAddr, req.Amounts)
if err != nil {
return nil, nil, errors.Wrapf(err, "deposit toAddr=%s", req.ReceiverAddrs)
}
......@@ -166,7 +166,7 @@ func (p *mixPolicy) getTransferOutput(req *mixTy.DepositInfo) (*TransferOutput,
}
//input = output+找零+交易费
func getShieldValue(inputAmounts []uint64, outAmount, change, minTxFee uint64) (*mixTy.ShieldAmountRst, error) {
func getShieldValue(cfg *types.Chain33Config, inputAmounts []uint64, outAmount, change, minTxFee uint64) (*mixTy.ShieldAmountRst, error) {
var sum uint64
for _, i := range inputAmounts {
sum += i
......@@ -227,13 +227,17 @@ func getShieldValue(inputAmounts []uint64, outAmount, change, minTxFee uint64) (
return nil, errors.Wrapf(types.ErrInvalidParam, "random sumIn=%s not equal sumOut=%s", rSumIn.String(), rSumOut.String())
}
conf := types.ConfSub(cfg, mixTy.MixX)
pointHX := conf.GStr("pointHX")
pointHY := conf.GStr("pointHY")
var inputHPoints []*twistededwards.Point
for _, i := range rInputs {
inputHPoints = append(inputHPoints, mixTy.MulCurvePointH(i.String()))
inputHPoints = append(inputHPoints, mixTy.MulCurvePointH(pointHX, pointHY, i.String()))
}
//noteH := mixTy.MulCurvePointH(rNote.String())
outH := mixTy.MulCurvePointH(rOut.String())
changeH := mixTy.MulCurvePointH(rChange.String())
outH := mixTy.MulCurvePointH(pointHX, pointHY, rOut.String())
changeH := mixTy.MulCurvePointH(pointHX, pointHY, rChange.String())
//fmt.Println("change",changeRandom.String())
//fmt.Println("transfer",transRandom.String())
//fmt.Println("note",noteRandom.String())
......@@ -275,6 +279,10 @@ func (p *mixPolicy) createTransferTx(req *mixTy.CreateRawTxReq) (*types.Transact
return nil, errors.Wrap(err, "decode req fail")
}
if len(req.AssetExec) == 0 || len(req.AssetSymbol) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "asset exec=%s or symbol=%s not filled", req.AssetExec, req.AssetSymbol)
}
noteHashs := strings.Split(transfer.GetInput().NoteHashs, ",")
var notes []*mixTy.WalletNoteInfo
for _, h := range noteHashs {
......@@ -285,6 +293,10 @@ func (p *mixPolicy) createTransferTx(req *mixTy.CreateRawTxReq) (*types.Transact
if note.Status != mixTy.NoteStatus_VALID && note.Status != mixTy.NoteStatus_UNFROZEN {
return nil, errors.Wrapf(types.ErrNotAllow, "wrong note status=%s", note.Status.String())
}
if note.Secret.AssetExec != req.AssetExec || note.Secret.AssetSymbol != req.AssetSymbol {
return nil, errors.Wrapf(types.ErrInvalidParam, "note=%s,exec=%s,sym=%s not equal req's exec=%s,symbol=%s",
h, note.Secret.AssetExec, note.Secret.AssetSymbol, req.AssetExec, req.AssetSymbol)
}
notes = append(notes, note)
}
......@@ -311,6 +323,12 @@ func (p *mixPolicy) createTransferTx(req *mixTy.CreateRawTxReq) (*types.Transact
}
//2. 获取output
//1.如果平行链,fee可以设为0
//2. 如果token,且不收token费,则txfee=0, 单纯扣特殊地址mixtoken的bty
//3. 如果token,且tokenFee=true,则按fee收token数量作为交易费
txFee := mixTy.GetTransferTxFee(p.walletOperate.GetAPI().GetConfig(), req.AssetExec)
outAmount, err := strconv.ParseUint(transfer.Output.Deposit.Amounts, 10, 64)
if err != nil {
return nil, errors.Wrapf(err, "output part parseUint=%s", transfer.Output.Deposit.Amounts)
......@@ -318,10 +336,10 @@ func (p *mixPolicy) createTransferTx(req *mixTy.CreateRawTxReq) (*types.Transact
if outAmount == 0 {
return nil, errors.Wrapf(err, "output part amount=0, parseUint=%s", transfer.Output.Deposit.Amounts)
}
if sumInput < outAmount+uint64(mixTy.Privacy2PrivacyTxFee) {
return nil, errors.Wrapf(types.ErrInvalidParam, "out amount=%d big than input=%d - fee=%d", outAmount, sumInput, uint64(mixTy.Privacy2PrivacyTxFee))
if sumInput < outAmount+uint64(txFee) {
return nil, errors.Wrapf(types.ErrInvalidParam, "out amount=%d big than input=%d - fee=%d", outAmount, sumInput, uint64(txFee))
}
outPart, outDHSecret, err := p.getTransferOutput(transfer.Output.Deposit)
outPart, outDHSecret, err := p.getTransferOutput(req.AssetExec, req.AssetSymbol, transfer.Output.Deposit)
if err != nil {
return nil, errors.Wrap(err, "getTransferOutput for deposit")
}
......@@ -330,19 +348,19 @@ func (p *mixPolicy) createTransferTx(req *mixTy.CreateRawTxReq) (*types.Transact
//3. 获取找零,并扣除手续费
//如果找零为0也需要设置,否则只有一个输入一个输出,H部分的随机数要相等,就能推测出转账值来
//在transfer output 部分特殊处理,如果amount是0的值则不加进tree
changeAmount := sumInput - outAmount - uint64(mixTy.Privacy2PrivacyTxFee)
changeAmount := sumInput - outAmount - uint64(txFee)
change := &mixTy.DepositInfo{
ReceiverAddrs: notes[0].Account,
Amounts: strconv.FormatUint(changeAmount, 10),
}
changePart, changeDHSecret, err := p.getTransferOutput(change)
changePart, changeDHSecret, err := p.getTransferOutput(req.AssetExec, req.AssetSymbol, change)
if err != nil {
return nil, errors.Wrap(err, "getTransferOutput change part ")
}
bizlog.Info("transferProof deposit to change succ")
//获取shieldValue 输入输出对amount隐藏
shieldValue, err := getShieldValue(inputAmounts, outAmount, changeAmount, uint64(mixTy.Privacy2PrivacyTxFee))
shieldValue, err := getShieldValue(p.walletOperate.GetAPI().GetConfig(), inputAmounts, outAmount, changeAmount, uint64(txFee))
if err != nil {
return nil, err
}
......@@ -396,14 +414,16 @@ func (p *mixPolicy) createTransferTx(req *mixTy.CreateRawTxReq) (*types.Transact
}
changeProof.Secrets = changeDHSecret
return p.getTransferTx(strings.TrimSpace(req.Title+mixTy.MixX), inputProofs, outputProof, changeProof)
return p.getTransferTx(strings.TrimSpace(req.Title+mixTy.MixX), req.AssetExec, req.AssetSymbol, inputProofs, outputProof, changeProof)
}
func (p *mixPolicy) getTransferTx(execName string, inputProofs []*mixTy.ZkProofInfo, proofs ...*mixTy.ZkProofInfo) (*types.Transaction, error) {
func (p *mixPolicy) getTransferTx(execName, assetExec, assetSymbol string, inputProofs []*mixTy.ZkProofInfo, output, change *mixTy.ZkProofInfo) (*types.Transaction, error) {
payload := &mixTy.MixTransferAction{}
payload.AssetExec = assetExec
payload.AssetSymbol = assetSymbol
payload.Inputs = inputProofs
payload.Output = proofs[0]
payload.Change = proofs[1]
payload.Output = output
payload.Change = change
cfg := p.getWalletOperate().GetAPI().GetConfig()
action := &mixTy.MixAction{
......
......@@ -67,7 +67,7 @@ type WithdrawInput struct {
Valid9 string `tag:"secret"`
}
func (p *mixPolicy) getWithdrawParams(noteHash string) (*WithdrawInput, error) {
func (p *mixPolicy) getWithdrawParams(exec, symbol, noteHash string) (*WithdrawInput, error) {
note, err := p.getNoteInfo(noteHash)
if err != nil {
return nil, err
......@@ -76,6 +76,11 @@ func (p *mixPolicy) getWithdrawParams(noteHash string) (*WithdrawInput, error) {
return nil, errors.Wrapf(types.ErrNotAllow, "wrong note status=%s", note.Status.String())
}
if note.Secret.AssetExec != exec || note.Secret.AssetSymbol != symbol {
return nil, errors.Wrapf(types.ErrInvalidParam, "exec=%s,sym=%s not equal req's exec=%s,symbol=%s",
note.Secret.AssetExec, note.Secret.AssetSymbol, exec, symbol)
}
var input WithdrawInput
initTreePath(&input)
input.NullifierHash = note.Nullifier
......@@ -105,7 +110,7 @@ func (p *mixPolicy) getWithdrawParams(noteHash string) (*WithdrawInput, error) {
}
//get tree path
treeProof, err := p.getTreeProof(note.NoteHash)
treeProof, err := p.getTreeProof(note.Secret.AssetExec, note.Secret.AssetSymbol, note.NoteHash)
if err != nil {
return nil, errors.Wrapf(err, "getTreeProof for hash=%s", note.NoteHash)
}
......@@ -122,6 +127,11 @@ func (p *mixPolicy) createWithdrawTx(req *mixTy.CreateRawTxReq) (*types.Transact
if err != nil {
return nil, errors.Wrap(err, "decode req fail")
}
if len(req.AssetExec) == 0 || len(req.AssetSymbol) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "asset exec=%s or symbol=%s not filled", req.AssetExec, req.AssetSymbol)
}
if withdraw.TotalAmount <= 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "totalAmount=%d", withdraw.TotalAmount)
}
......@@ -134,7 +144,7 @@ func (p *mixPolicy) createWithdrawTx(req *mixTy.CreateRawTxReq) (*types.Transact
var sum uint64
for _, note := range notes {
input, err := p.getWithdrawParams(note)
input, err := p.getWithdrawParams(req.AssetExec, req.AssetSymbol, note)
if err != nil {
return nil, errors.Wrapf(err, "getWithdrawParams note=%s", note)
}
......@@ -161,12 +171,14 @@ func (p *mixPolicy) createWithdrawTx(req *mixTy.CreateRawTxReq) (*types.Transact
return nil, errors.Wrapf(types.ErrInvalidParam, "amount not match req=%d,note.sum=%d", withdraw.TotalAmount, sum)
}
return p.getWithdrawTx(strings.TrimSpace(req.Title+mixTy.MixX), withdraw.TotalAmount, proofs)
return p.getWithdrawTx(strings.TrimSpace(req.Title+mixTy.MixX), req.AssetExec, req.AssetSymbol, withdraw.TotalAmount, proofs)
}
func (p *mixPolicy) getWithdrawTx(execName string, amount uint64, proofs []*mixTy.ZkProofInfo) (*types.Transaction, error) {
func (p *mixPolicy) getWithdrawTx(execName, assetExec, assetSymbol string, amount uint64, proofs []*mixTy.ZkProofInfo) (*types.Transaction, error) {
payload := &mixTy.MixWithdrawAction{}
payload.AssetExec = assetExec
payload.AssetSymbol = assetSymbol
payload.Amount = amount
payload.Proofs = proofs
......
......@@ -127,11 +127,11 @@ func (p *mixPolicy) getPaymentKey(addr string) (*mixTy.PaymentKey, error) {
return msg.(*mixTy.PaymentKey), err
}
func (p *mixPolicy) getPathProof(leaf string) (*mixTy.CommitTreeProve, error) {
func (p *mixPolicy) getPathProof(exec, symbol, leaf string) (*mixTy.CommitTreeProve, error) {
msg, err := p.walletOperate.GetAPI().QueryChain(&types.ChainExecutor{
Driver: "mix",
FuncName: "GetTreePath",
Param: types.Encode(&mixTy.TreeInfoReq{LeafHash: leaf}),
Param: types.Encode(&mixTy.TreeInfoReq{AssetExec: exec, AssetSymbol: symbol, LeafHash: leaf}),
})
if err != nil {
return nil, err
......@@ -160,11 +160,11 @@ func (p *mixPolicy) getNoteInfo(noteHash string) (*mixTy.WalletNoteInfo, error)
return note, nil
}
func (p *mixPolicy) getTreeProof(leaf string) (*mixTy.TreePathProof, error) {
func (p *mixPolicy) getTreeProof(exec, symbol, leaf string) (*mixTy.TreePathProof, error) {
//get tree path
path, err := p.getPathProof(leaf)
path, err := p.getPathProof(exec, symbol, leaf)
if err != nil {
return nil, errors.Wrapf(err, "get tree proof for noteHash=%s", leaf)
return nil, errors.Wrapf(err, "get tree proof for noteHash=%s,exec=%s,symbol=%s", leaf, exec, symbol)
}
var proof mixTy.TreePathProof
proof.TreePath = path.ProofSet[1:]
......
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