OSDN Git Service

module claim
authormars <mars@bytom.io>
Thu, 28 Mar 2019 14:30:44 +0000 (22:30 +0800)
committermars <mars@bytom.io>
Fri, 29 Mar 2019 01:06:47 +0000 (09:06 +0800)
51 files changed:
account/dpos_builder.go
api/cliam_transact.go
api/main_transact.go
api/query.go
api/receivers.go
blockchain/txbuilder/finalize.go
blockchain/txbuilder/mainchain/types.go [deleted file]
claim/bytom/mainchain/builder.go [moved from blockchain/txbuilder/mainchain/builder.go with 84% similarity]
claim/bytom/mainchain/constraint.go [moved from blockchain/txbuilder/mainchain/constraint.go with 100% similarity]
claim/bytom/mainchain/data_witness.go [moved from blockchain/txbuilder/mainchain/data_witness.go with 100% similarity]
claim/bytom/mainchain/rawtxsig_witness.go [moved from blockchain/txbuilder/mainchain/rawtxsig_witness.go with 100% similarity]
claim/bytom/mainchain/signature_program.go [moved from blockchain/txbuilder/mainchain/signature_program.go with 100% similarity]
claim/bytom/mainchain/signature_witness.go [moved from blockchain/txbuilder/mainchain/signature_witness.go with 100% similarity]
claim/bytom/mainchain/signing_instruction.go [moved from blockchain/txbuilder/mainchain/signing_instruction.go with 100% similarity]
claim/bytom/mainchain/types.go [new file with mode: 0644]
claim/bytom/mainchain/witness.go [moved from blockchain/txbuilder/mainchain/witness.go with 100% similarity]
claim/bytom/protocolbc/block.go [moved from protocol/bc/types/bytom/block.go with 89% similarity]
claim/bytom/protocolbc/general.go [moved from protocol/bc/types/bytom/general.go with 99% similarity]
claim/bytom/protocolbc/tx.go [moved from protocol/bc/types/bytom/tx.go with 99% similarity]
claim/bytom/protocolbc/types/block.go [moved from protocol/bc/types/bytom/types/block.go with 100% similarity]
claim/bytom/protocolbc/types/block_commitment.go [moved from protocol/bc/types/bytom/types/block_commitment.go with 100% similarity]
claim/bytom/protocolbc/types/block_header.go [moved from protocol/bc/types/bytom/types/block_header.go with 100% similarity]
claim/bytom/protocolbc/types/block_test.go [moved from protocol/bc/types/bytom/types/block_test.go with 100% similarity]
claim/bytom/protocolbc/types/coinbase.go [moved from protocol/bc/types/bytom/types/coinbase.go with 100% similarity]
claim/bytom/protocolbc/types/map.go [moved from protocol/bc/types/bytom/types/map.go with 99% similarity]
claim/bytom/protocolbc/types/output_commitment.go [moved from protocol/bc/types/bytom/types/output_commitment.go with 100% similarity]
claim/bytom/protocolbc/types/spend.go [moved from protocol/bc/types/bytom/types/spend.go with 100% similarity]
claim/bytom/protocolbc/types/spend_commitment.go [moved from protocol/bc/types/bytom/types/spend_commitment.go with 100% similarity]
claim/bytom/protocolbc/types/transaction.go [moved from protocol/bc/types/bytom/types/transaction.go with 98% similarity]
claim/bytom/protocolbc/types/txinput.go [moved from protocol/bc/types/bytom/types/txinput.go with 100% similarity]
claim/bytom/protocolbc/types/txoutput.go [moved from protocol/bc/types/bytom/types/txoutput.go with 100% similarity]
claim/bytom_validation.go [new file with mode: 0644]
claim/claim.go [new file with mode: 0644]
claim/rpc/bytom/bytom_claim_tx.go [new file with mode: 0644]
claim/rpc/bytom/bytom_main_tx.go [new file with mode: 0644]
claim/rpc/bytom/estimate.go [moved from api/estimate.go with 98% similarity]
claim/rpc/claim_tx.go [new file with mode: 0644]
claim/rpc/main_tx.go [new file with mode: 0644]
claim/rpc/pegin.go [new file with mode: 0644]
claim/rpc/pegin_address.go [new file with mode: 0644]
protocol/bc/bc.pb.go
protocol/bc/bc.proto
protocol/bc/dpos.go [deleted file]
protocol/bc/types/dpos.go [deleted file]
protocol/bc/types/map.go
protocol/bc/types/txinput.go
protocol/block.go
protocol/validation/tx.go
tools/monitor_tx/main.go
tools/side_chain_tool/app/api/transaction.py
util/call_rpc.go

index 64f5061..6652a91 100644 (file)
@@ -167,46 +167,6 @@ func (a *DopsAction) ActionType() string {
        return "dpos"
 }
 
-// DposInputs convert an utxo to the txinput
-func DposTx(from, to string, stake uint64, u *UTXO, txType types.TxType, h uint64) (*types.TxInput, *txbuilder.SigningInstruction, error) {
-       txInput := types.NewDpos(nil, from, to, u.SourceID, u.AssetID, stake, u.Amount, u.SourcePos, u.ControlProgram, txType, h)
-       sigInst := &txbuilder.SigningInstruction{}
-       var xpubs []chainkd.XPub
-       var xprv chainkd.XPrv
-       xprv.UnmarshalText([]byte(config.CommonConfig.Consensus.XPrv))
-       xpubs = append(xpubs, xprv.XPub())
-       quorum := len(xpubs)
-       if u.Address == "" {
-               sigInst.AddWitnessKeysWithOutPath(xpubs, quorum)
-               return txInput, sigInst, nil
-       }
-
-       address, err := common.DecodeAddress(u.Address, &consensus.ActiveNetParams)
-       if err != nil {
-               return nil, nil, err
-       }
-       sigInst.AddRawWitnessKeysWithoutPath(xpubs, quorum)
-       switch address.(type) {
-       case *common.AddressWitnessPubKeyHash:
-               derivedPK := xpubs[0].PublicKey()
-               sigInst.WitnessComponents = append(sigInst.WitnessComponents, txbuilder.DataWitness([]byte(derivedPK)))
-
-       case *common.AddressWitnessScriptHash:
-               derivedXPubs := xpubs
-               derivedPKs := chainkd.XPubKeys(derivedXPubs)
-               script, err := vmutil.P2SPMultiSigProgram(derivedPKs, quorum)
-               if err != nil {
-                       return nil, nil, err
-               }
-               sigInst.WitnessComponents = append(sigInst.WitnessComponents, txbuilder.DataWitness(script))
-
-       default:
-               return nil, nil, errors.New("unsupport address type")
-       }
-
-       return txInput, sigInst, nil
-}
-
 // spendInput convert an utxo to the txinput
 func spendInput(u *UTXO) (*types.TxInput, *txbuilder.SigningInstruction, error) {
        txSpendInput := types.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)
index b6dc449..33af428 100644 (file)
 package api
 
 import (
-       "bytes"
        "context"
-       "encoding/json"
-       "strconv"
-       "time"
 
-       log "github.com/sirupsen/logrus"
-       "github.com/vapor/account"
-       "github.com/vapor/blockchain/txbuilder"
-       "github.com/vapor/consensus"
-       "github.com/vapor/crypto/sha3pool"
-       chainjson "github.com/vapor/encoding/json"
-       "github.com/vapor/errors"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-       bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
-       "github.com/vapor/protocol/validation"
-       "github.com/vapor/util"
+       "github.com/vapor/claim/rpc"
+       claimtx "github.com/vapor/claim/rpc/bytom"
 )
 
-func getPeginTxnOutputIndex(rawTx bytomtypes.Tx, controlProg []byte) int {
-       for index, output := range rawTx.Outputs {
-               if bytes.Equal(output.ControlProgram, controlProg) {
-                       return index
-               }
-       }
-       return -1
-}
+func (a *API) claimPeginTx(ctx context.Context, ins rpc.ClaimTxParam) Response {
 
-func toHash(hexBytes []chainjson.HexBytes) (hashs []*bc.Hash) {
-       for _, data := range hexBytes {
-               b32 := [32]byte{}
-               copy(b32[:], data)
-               res := bc.NewHash(b32)
-               hashs = append(hashs, &res)
+       c := &claimtx.BytomClaimTx{
+               ClaimTxParam: ins,
+               Wallet:       a.wallet,
+               Chain:        a.chain,
        }
-       return
-}
+       resp, err := c.ClaimPeginTx(ctx)
 
-func (a *API) claimPeginTx(ctx context.Context, ins struct {
-       Password     string                 `json:"password"`
-       RawTx        bytomtypes.Tx          `json:"raw_transaction"`
-       BlockHeader  bytomtypes.BlockHeader `json:"block_header"`
-       TxHashes     []chainjson.HexBytes   `json:"tx_hashes"`
-       StatusHashes []chainjson.HexBytes   `json:"status_hashes"`
-       Flags        []uint32               `json:"flags"`
-       MatchedTxIDs []chainjson.HexBytes   `json:"matched_tx_ids"`
-       ClaimScript  chainjson.HexBytes     `json:"claim_script"`
-}) Response {
-       tmpl, err := a.createRawPegin(ctx, ins)
        if err != nil {
-               log.WithField("build err", err).Error("fail on createrawpegin.")
-               return NewErrorResponse(err)
-       }
-       // 交易签名
-       if err := txbuilder.Sign(ctx, tmpl, ins.Password, a.PseudohsmSignTemplate); err != nil {
-               log.WithField("build err", err).Error("fail on sign transaction.")
                return NewErrorResponse(err)
        }
 
-       // submit
-       if err := txbuilder.FinalizeTx(ctx, a.chain, tmpl.Transaction); err != nil {
-               return NewErrorResponse(err)
-       }
-
-       log.WithField("tx_id", tmpl.Transaction.ID.String()).Info("claim script tx")
-       return NewSuccessResponse(&submitTxResp{TxID: &tmpl.Transaction.ID})
+       return NewSuccessResponse(resp)
 }
 
-func (a *API) createRawPegin(ctx context.Context, ins struct {
-       Password     string                 `json:"password"`
-       RawTx        bytomtypes.Tx          `json:"raw_transaction"`
-       BlockHeader  bytomtypes.BlockHeader `json:"block_header"`
-       TxHashes     []chainjson.HexBytes   `json:"tx_hashes"`
-       StatusHashes []chainjson.HexBytes   `json:"status_hashes"`
-       Flags        []uint32               `json:"flags"`
-       MatchedTxIDs []chainjson.HexBytes   `json:"matched_tx_ids"`
-       ClaimScript  chainjson.HexBytes     `json:"claim_script"`
-}) (*txbuilder.Template, error) {
-       // proof验证
-       var flags []uint8
-       for flag := range ins.Flags {
-               flags = append(flags, uint8(flag))
-       }
-       txHashes := toHash(ins.TxHashes)
-       matchedTxIDs := toHash(ins.MatchedTxIDs)
-       statusHashes := toHash(ins.StatusHashes)
-       if !types.ValidateTxMerkleTreeProof(txHashes, flags, matchedTxIDs, ins.BlockHeader.BlockCommitment.TransactionsMerkleRoot) {
-               return nil, errors.New("Merkleblock validation failed")
-       }
-       // CheckBytomProof
-       //difficulty.CheckBytomProofOfWork(ins.BlockHeader.Hash(), ins.BlockHeader)
-       // 增加spv验证以及连接主链api查询交易的确认数
-       if util.ValidatePegin {
-               if err := util.IsConfirmedBytomBlock(ins.BlockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
-                       return nil, err
-               }
-       }
-       // 找出与claim script有关联的交易的输出
-       var claimScript []byte
-       nOut := len(ins.RawTx.Outputs)
-       if ins.ClaimScript == nil {
-               // 遍历寻找与交易输出有关的claim script
-               cps, err := a.wallet.AccountMgr.ListControlProgram()
-               if err != nil {
-                       return nil, err
-               }
-
-               for _, cp := range cps {
-                       _, controlProg := a.wallet.AccountMgr.GetPeginControlPrograms(cp.ControlProgram)
-                       if controlProg == nil {
-                               continue
-                       }
-                       // 获取交易的输出
-                       nOut = getPeginTxnOutputIndex(ins.RawTx, controlProg)
-                       if nOut != len(ins.RawTx.Outputs) {
-                               claimScript = cp.ControlProgram
-                       }
-               }
-       } else {
-               claimScript = ins.ClaimScript
-               _, controlProg := a.wallet.AccountMgr.GetPeginControlPrograms(claimScript)
-               // 获取交易的输出
-               nOut = getPeginTxnOutputIndex(ins.RawTx, controlProg)
-       }
-       if nOut == len(ins.RawTx.Outputs) || nOut == -1 {
-               return nil, errors.New("Failed to find output in bytom to the mainchain_address from getpeginaddress")
-       }
-
-       // 根据ClaimScript 获取account id
-       var hash [32]byte
-       sha3pool.Sum256(hash[:], claimScript)
-       data := a.wallet.DB.Get(account.ContractKey(hash))
-       if data == nil {
-               return nil, errors.New("Failed to find control program through claim script")
-       }
-
-       cp := &account.CtrlProgram{}
-       if err := json.Unmarshal(data, cp); err != nil {
-               return nil, errors.New("Failed on unmarshal control program")
-       }
-
-       // 构造交易
-       // 用输出作为交易输入 生成新的交易
-       builder := txbuilder.NewBuilder(time.Now())
-       // TODO 根据raw tx生成一个utxo
-       sourceID := *ins.RawTx.OutputID(nOut)
-       outputAccount := ins.RawTx.Outputs[nOut].Amount
-       assetID := *ins.RawTx.Outputs[nOut].AssetId
-
-       txInput := types.NewClaimInput(nil, sourceID, assetID, outputAccount, uint64(nOut), cp.ControlProgram)
-       if err := builder.AddInput(txInput, &txbuilder.SigningInstruction{}); err != nil {
-               return nil, err
-       }
-       program, err := a.wallet.AccountMgr.CreateAddress(cp.AccountID, false)
-       if err != nil {
-               return nil, err
-       }
-
-       if err = builder.AddOutput(types.NewTxOutput(assetID, outputAccount, program.ControlProgram)); err != nil {
-               return nil, err
+func (a *API) claimContractPeginTx(ctx context.Context, ins rpc.ClaimTxParam) Response {
+       c := &claimtx.BytomClaimTx{
+               ClaimTxParam: ins,
+               Wallet:       a.wallet,
+               Chain:        a.chain,
        }
+       resp, err := c.ClaimContractPeginTx(ctx)
 
-       tmpl, txData, err := builder.Build()
        if err != nil {
-               return nil, err
-       }
-
-       // todo把一些主链的信息加到交易的stack中
-       var stack [][]byte
-
-       //amount
-       amount := strconv.FormatUint(ins.RawTx.Outputs[nOut].Amount, 10)
-       stack = append(stack, []byte(amount))
-       // 主链的gennesisBlockHash
-       stack = append(stack, []byte(consensus.ActiveNetParams.ParentGenesisBlockHash))
-       // claim script
-       stack = append(stack, claimScript)
-       // raw tx
-       tx, _ := json.Marshal(ins.RawTx)
-       stack = append(stack, tx)
-       // proof
-       blockHeader, err := ins.BlockHeader.MarshalText()
-       if err != nil {
-               return nil, err
-       }
-       merkleBlock := validation.MerkleBlock{
-               BlockHeader:  blockHeader,
-               TxHashes:     txHashes,
-               StatusHashes: statusHashes,
-               Flags:        ins.Flags,
-               MatchedTxIDs: matchedTxIDs,
-       }
-
-       txOutProof, _ := json.Marshal(merkleBlock)
-
-       stack = append(stack, txOutProof)
-
-       //      tmpl.Transaction.Inputs[0].Peginwitness = stack
-       txData.Inputs[0].Peginwitness = stack
-
-       //交易费估算
-       txGasResp, err := EstimateTxGas(*tmpl)
-       if err != nil {
-               return nil, err
-       }
-       txData.Outputs[0].Amount = txData.Outputs[0].Amount - uint64(txGasResp.TotalNeu)
-       //重设置Transaction
-       tmpl.Transaction = types.NewTx(*txData)
-       return tmpl, nil
-}
-
-func (a *API) claimContractPeginTx(ctx context.Context, ins struct {
-       Password     string                 `json:"password"`
-       RawTx        bytomtypes.Tx          `json:"raw_transaction"`
-       BlockHeader  bytomtypes.BlockHeader `json:"block_header"`
-       TxHashes     []chainjson.HexBytes   `json:"tx_hashes"`
-       StatusHashes []chainjson.HexBytes   `json:"status_hashes"`
-       Flags        []uint32               `json:"flags"`
-       MatchedTxIDs []chainjson.HexBytes   `json:"matched_tx_ids"`
-       ClaimScript  chainjson.HexBytes     `json:"claim_script"`
-}) Response {
-       tmpl, err := a.createContractRawPegin(ctx, ins)
-       if err != nil {
-               log.WithField("build err", err).Error("fail on claimContractPeginTx.")
-               return NewErrorResponse(err)
-       }
-       // 交易签名
-       if err := txbuilder.Sign(ctx, tmpl, ins.Password, a.PseudohsmSignTemplate); err != nil {
-               log.WithField("build err", err).Error("fail on sign transaction.")
-               return NewErrorResponse(err)
-       }
-
-       // submit
-       if err := txbuilder.FinalizeTx(ctx, a.chain, tmpl.Transaction); err != nil {
                return NewErrorResponse(err)
        }
 
-       log.WithField("tx_id", tmpl.Transaction.ID.String()).Info("claim script tx")
-       return NewSuccessResponse(&submitTxResp{TxID: &tmpl.Transaction.ID})
-}
-
-func (a *API) createContractRawPegin(ctx context.Context, ins struct {
-       Password     string                 `json:"password"`
-       RawTx        bytomtypes.Tx          `json:"raw_transaction"`
-       BlockHeader  bytomtypes.BlockHeader `json:"block_header"`
-       TxHashes     []chainjson.HexBytes   `json:"tx_hashes"`
-       StatusHashes []chainjson.HexBytes   `json:"status_hashes"`
-       Flags        []uint32               `json:"flags"`
-       MatchedTxIDs []chainjson.HexBytes   `json:"matched_tx_ids"`
-       ClaimScript  chainjson.HexBytes     `json:"claim_script"`
-}) (*txbuilder.Template, error) {
-       // proof验证
-       var flags []uint8
-       for flag := range ins.Flags {
-               flags = append(flags, uint8(flag))
-       }
-       txHashes := toHash(ins.TxHashes)
-       matchedTxIDs := toHash(ins.MatchedTxIDs)
-       statusHashes := toHash(ins.StatusHashes)
-       if !types.ValidateTxMerkleTreeProof(txHashes, flags, matchedTxIDs, ins.BlockHeader.BlockCommitment.TransactionsMerkleRoot) {
-               return nil, errors.New("Merkleblock validation failed")
-       }
-       // CheckBytomProof
-       //difficulty.CheckBytomProofOfWork(ins.BlockHeader.Hash(), ins.BlockHeader)
-       // 增加spv验证以及连接主链api查询交易的确认数
-       if util.ValidatePegin {
-               if err := util.IsConfirmedBytomBlock(ins.BlockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
-                       return nil, err
-               }
-       }
-       // 找出与claim script有关联的交易的输出
-       var claimScript []byte
-       nOut := len(ins.RawTx.Outputs)
-       if ins.ClaimScript == nil {
-               // 遍历寻找与交易输出有关的claim script
-               cps, err := a.wallet.AccountMgr.ListControlProgram()
-               if err != nil {
-                       return nil, err
-               }
-
-               for _, cp := range cps {
-                       _, controlProg := a.wallet.AccountMgr.GetPeginContractControlPrograms(claimScript)
-                       // 获取交易的输出
-                       nOut = getPeginTxnOutputIndex(ins.RawTx, controlProg)
-                       if nOut != len(ins.RawTx.Outputs) {
-                               claimScript = cp.ControlProgram
-                       }
-               }
-       } else {
-               claimScript = ins.ClaimScript
-               _, controlProg := a.wallet.AccountMgr.GetPeginContractControlPrograms(claimScript)
-               // 获取交易的输出
-               nOut = getPeginTxnOutputIndex(ins.RawTx, controlProg)
-       }
-       if nOut == len(ins.RawTx.Outputs) || nOut == -1 {
-               return nil, errors.New("Failed to find output in bytom to the mainchain_address from createContractRawPegin")
-       }
-
-       // 根据ClaimScript 获取account id
-       var hash [32]byte
-       sha3pool.Sum256(hash[:], claimScript)
-       data := a.wallet.DB.Get(account.ContractKey(hash))
-       if data == nil {
-               return nil, errors.New("Failed to find control program through claim script")
-       }
-
-       cp := &account.CtrlProgram{}
-       if err := json.Unmarshal(data, cp); err != nil {
-               return nil, errors.New("Failed on unmarshal control program")
-       }
-
-       // 构造交易
-       // 用输出作为交易输入 生成新的交易
-       builder := txbuilder.NewBuilder(time.Now())
-       // TODO 根据raw tx生成一个utxo
-
-       sourceID := *ins.RawTx.OutputID(nOut)
-       outputAccount := ins.RawTx.Outputs[nOut].Amount
-       assetID := *ins.RawTx.Outputs[nOut].AssetId
-
-       txInput := types.NewClaimInput(nil, sourceID, assetID, outputAccount, uint64(nOut), cp.ControlProgram)
-       if err := builder.AddInput(txInput, &txbuilder.SigningInstruction{}); err != nil {
-               return nil, err
-       }
-       program, err := a.wallet.AccountMgr.CreateAddress(cp.AccountID, false)
-       if err != nil {
-               return nil, err
-       }
-
-       if err = builder.AddOutput(types.NewTxOutput(assetID, outputAccount, program.ControlProgram)); err != nil {
-               return nil, err
-       }
-
-       tmpl, txData, err := builder.Build()
-       if err != nil {
-               return nil, err
-       }
-
-       // todo把一些主链的信息加到交易的stack中
-       var stack [][]byte
-
-       //amount
-       amount := strconv.FormatUint(ins.RawTx.Outputs[nOut].Amount, 10)
-       stack = append(stack, []byte(amount))
-       // 主链的gennesisBlockHash
-       stack = append(stack, []byte(consensus.ActiveNetParams.ParentGenesisBlockHash))
-       // claim script
-       stack = append(stack, claimScript)
-       // raw tx
-       tx, _ := ins.RawTx.MarshalText()
-       //tx, _ := json.Marshal(ins.RawTx)
-       stack = append(stack, tx)
-       // proof
-       blockHeader, err := ins.BlockHeader.MarshalText()
-       if err != nil {
-               return nil, err
-       }
-       merkleBlock := validation.MerkleBlock{
-               BlockHeader:  blockHeader,
-               TxHashes:     txHashes,
-               StatusHashes: statusHashes,
-               Flags:        ins.Flags,
-               MatchedTxIDs: matchedTxIDs,
-       }
-       txOutProof, _ := json.Marshal(merkleBlock)
-       stack = append(stack, txOutProof)
-       //      tmpl.Transaction.Inputs[0].Peginwitness = stack
-       txData.Inputs[0].Peginwitness = stack
-
-       //交易费估算
-       txGasResp, err := EstimateTxGas(*tmpl)
-       if err != nil {
-               return nil, err
-       }
-       txData.Outputs[0].Amount = txData.Outputs[0].Amount - uint64(txGasResp.TotalNeu)
-       //重设置Transaction
-       tmpl.Transaction = types.NewTx(*txData)
-       return tmpl, nil
+       return NewSuccessResponse(resp)
 }
index 4bb63c8..fdce0b0 100644 (file)
 package api
 
 import (
-       "bytes"
-       "crypto/hmac"
-       "crypto/sha256"
-       "time"
-
-       log "github.com/sirupsen/logrus"
-
-       "github.com/vapor/account"
-       "github.com/vapor/blockchain/txbuilder"
-       "github.com/vapor/blockchain/txbuilder/mainchain"
-       "github.com/vapor/common"
-       "github.com/vapor/consensus"
-       "github.com/vapor/crypto/ed25519/chainkd"
+       "github.com/vapor/claim/rpc"
+       maintx "github.com/vapor/claim/rpc/bytom"
        chainjson "github.com/vapor/encoding/json"
-       "github.com/vapor/equity/pegin_contract"
-       "github.com/vapor/errors"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-       bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
-       "github.com/vapor/protocol/vm/vmutil"
 )
 
-func (a *API) buildMainChainTxForContract(ins struct {
-       Utxo           account.UTXO       `json:"utxo"`
-       Tx             types.Tx           `json:"raw_transaction"`
-       RootXPubs      []chainkd.XPub     `json:"root_xpubs"`
-       ControlProgram string             `json:"control_program"`
-       ClaimScript    chainjson.HexBytes `json:"claim_script"`
-}) Response {
-
-       var xpubs []chainkd.XPub
-       for _, xpub := range ins.RootXPubs {
-               // pub + scriptPubKey 生成一个随机数A
-               var tmp [32]byte
-               h := hmac.New(sha256.New, xpub[:])
-               h.Write(ins.ClaimScript)
-               tweak := h.Sum(tmp[:])
-               // pub +  A 生成一个新的公钥pub_new
-               chaildXPub := xpub.Child(tweak)
-               xpubs = append(xpubs, chaildXPub)
-       }
-
-       txInput, sigInst, err := contractToInputs(a, &ins.Utxo, xpubs, ins.ClaimScript)
-       builder := mainchain.NewBuilder(time.Now())
-       builder.AddInput(txInput, sigInst)
-       changeAmount := uint64(0)
-       retire := false
-       for _, key := range ins.Tx.GetResultIds() {
-               output, err := ins.Tx.Retire(*key)
-               if err != nil {
-                       log.WithFields(log.Fields{"moudle": "transact", "err": err}).Warn("buildMainChainTx error")
-                       continue
-               }
-               retire = true
-               var controlProgram []byte
-               retBool := true
-               if controlProgram, retBool = getInput(ins.Tx.Entries, *key, ins.ControlProgram); !retBool {
-                       return NewErrorResponse(errors.New("The corresponding input cannot be found"))
-               }
-
-               assetID := *output.Source.Value.AssetId
-               out := bytomtypes.NewTxOutput(assetID, output.Source.Value.Amount, controlProgram)
-               builder.AddOutput(out)
-               changeAmount = ins.Utxo.Amount - output.Source.Value.Amount
-
-       }
-
-       if !retire {
-               return NewErrorResponse(errors.New("It's not a transaction to retire assets"))
-       }
-
-       if changeAmount > 0 {
-               u := ins.Utxo
-               out := bytomtypes.NewTxOutput(u.AssetID, changeAmount, ins.Utxo.ControlProgram)
-               builder.AddOutput(out)
-       }
-
-       tmpl, tx, err := builder.Build()
-       if err != nil {
-               return NewErrorResponse(err)
-       }
-
-       for i, out := range tmpl.Transaction.Outputs {
-               if bytes.Equal(out.ControlProgram, ins.Utxo.ControlProgram) {
-                       //tx.Outputs[i].Amount = changeAmount - uint64(txGasResp.TotalNeu)
-                       tx.Outputs[i].Amount = changeAmount - 100000000
-               }
-       }
-       tmpl.Transaction = bytomtypes.NewTx(*tx)
-       return NewSuccessResponse(tmpl)
+type mainTxResp struct {
+       Tx chainjson.HexBytes `json:"tx"`
 }
 
-func (a *API) buildMainChainTx(ins struct {
-       Utxo           account.UTXO       `json:"utxo"`
-       Tx             types.Tx           `json:"raw_transaction"`
-       RootXPubs      []chainkd.XPub     `json:"root_xpubs"`
-       ControlProgram string             `json:"control_program"`
-       ClaimScript    chainjson.HexBytes `json:"claim_script"`
-}) Response {
-
-       var xpubs []chainkd.XPub
-       for _, xpub := range ins.RootXPubs {
-               // pub + scriptPubKey 生成一个随机数A
-               var tmp [32]byte
-               h := hmac.New(sha256.New, xpub[:])
-               h.Write(ins.ClaimScript)
-               tweak := h.Sum(tmp[:])
-               // pub +  A 生成一个新的公钥pub_new
-               chaildXPub := xpub.Child(tweak)
-               xpubs = append(xpubs, chaildXPub)
+func (a *API) buildMainChainTxForContract(ins rpc.MainTxParam) Response {
+       main := &maintx.BytomMainTx{
+               MainTxParam: ins,
        }
 
-       txInput, sigInst, err := utxoToInputs(xpubs, &ins.Utxo)
-       if err != nil {
-               return NewErrorResponse(err)
-       }
-
-       builder := mainchain.NewBuilder(time.Now())
-       builder.AddInput(txInput, sigInst)
-       changeAmount := uint64(0)
-       retire := false
-       for _, key := range ins.Tx.GetResultIds() {
-               output, err := ins.Tx.Retire(*key)
-               if err != nil {
-                       log.WithFields(log.Fields{"moudle": "transact", "err": err}).Warn("buildMainChainTx error")
-                       continue
-               }
-               retire = true
-               var controlProgram []byte
-               retBool := true
-               if controlProgram, retBool = getInput(ins.Tx.Entries, *key, ins.ControlProgram); !retBool {
-                       return NewErrorResponse(errors.New("The corresponding input cannot be found"))
-               }
-
-               assetID := *output.Source.Value.AssetId
-               out := bytomtypes.NewTxOutput(assetID, output.Source.Value.Amount, controlProgram)
-               builder.AddOutput(out)
-               changeAmount = ins.Utxo.Amount - output.Source.Value.Amount
-
-       }
-
-       if !retire {
-               return NewErrorResponse(errors.New("It's not a transaction to retire assets"))
-       }
-
-       if changeAmount > 0 {
-               u := ins.Utxo
-               out := bytomtypes.NewTxOutput(u.AssetID, changeAmount, ins.Utxo.ControlProgram)
-               builder.AddOutput(out)
-       }
-
-       tmpl, tx, err := builder.Build()
-       if err != nil {
-               return NewErrorResponse(err)
-       }
-       //交易费估算
-       txGasResp, err := EstimateTxGasForMainchain(*tmpl)
+       resp, err := main.BuildMainChainTxForContract()
        if err != nil {
                return NewErrorResponse(err)
        }
-       for i, out := range tmpl.Transaction.Outputs {
-               if bytes.Equal(out.ControlProgram, ins.Utxo.ControlProgram) {
-                       tx.Outputs[i].Amount = changeAmount - uint64(txGasResp.TotalNeu)
-               }
-       }
-       tmpl.Transaction = bytomtypes.NewTx(*tx)
-       return NewSuccessResponse(tmpl)
-}
-
-//
-func getInput(entry map[bc.Hash]bc.Entry, outputID bc.Hash, controlProgram string) ([]byte, bool) {
-       output := entry[outputID].(*bc.Retirement)
-       mux := entry[*output.Source.Ref].(*bc.Mux)
 
-       for _, valueSource := range mux.GetSources() {
-               spend := entry[*valueSource.Ref].(*bc.Spend)
-               prevout := entry[*spend.SpentOutputId].(*bc.Output)
-
-               var ctrlProgram chainjson.HexBytes
-               ctrlProgram = prevout.ControlProgram.Code
-               tmp, _ := ctrlProgram.MarshalText()
-               if string(tmp) == controlProgram {
-                       return ctrlProgram, true
-               }
-       }
-       return nil, false
+       return NewSuccessResponse(&mainTxResp{Tx: resp})
 }
 
-// UtxoToInputs convert an utxo to the txinput
-func utxoToInputs(xpubs []chainkd.XPub, u *account.UTXO) (*bytomtypes.TxInput, *mainchain.SigningInstruction, error) {
-       txInput := bytomtypes.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)
-       sigInst := &mainchain.SigningInstruction{}
-       quorum := len(xpubs)
-       if u.Address == "" {
-               sigInst.AddWitnessKeys(xpubs, quorum)
-               return txInput, sigInst, nil
+func (a *API) buildMainChainTx(ins rpc.MainTxParam) Response {
+       main := &maintx.BytomMainTx{
+               MainTxParam: ins,
        }
 
-       address, err := common.DecodeBytomAddress(u.Address, &consensus.ActiveNetParams)
+       resp, err := main.BuildMainChainTx()
        if err != nil {
-               return nil, nil, err
-       }
-
-       sigInst.AddRawWitnessKeysWithoutPath(xpubs, quorum)
-
-       switch address.(type) {
-       case *common.AddressWitnessPubKeyHash:
-               derivedPK := xpubs[0].PublicKey()
-               sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness([]byte(derivedPK)))
-
-       case *common.AddressWitnessScriptHash:
-               derivedXPubs := xpubs
-               derivedPKs := chainkd.XPubKeys(derivedXPubs)
-               script, err := vmutil.P2SPMultiSigProgram(derivedPKs, quorum)
-               if err != nil {
-                       return nil, nil, err
-               }
-               sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness(script))
-
-       default:
-               return nil, nil, errors.New("unsupport address type")
+               return NewErrorResponse(err)
        }
 
-       return txInput, sigInst, nil
+       return NewSuccessResponse(&mainTxResp{Tx: resp})
 }
 
-func contractToInputs(a *API, u *account.UTXO, xpubs []chainkd.XPub, ClaimScript chainjson.HexBytes) (*bytomtypes.TxInput, *mainchain.SigningInstruction, error) {
-       txInput := bytomtypes.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)
-       sigInst := &mainchain.SigningInstruction{}
-
-       // raw_tx_signature
-       for _, xpub := range xpubs {
-               xpubsTmp := []chainkd.XPub{xpub}
-               sigInst.AddRawWitnessKeysWithoutPath(xpubsTmp, 1)
+func (a *API) signWithKey(ins rpc.MainTxSignParam) Response {
+       sign := maintx.BytomMainSign{
+               MainTxSignParam: ins,
        }
 
-       // data
-       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(ClaimScript)
+       resp, err := sign.SignWithKey()
        if err != nil {
-               return nil, nil, err
-       }
-       sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness(peginContractPrograms))
-
-       return txInput, sigInst, nil
-}
-
-type signRespForMainchain struct {
-       Tx           *mainchain.Template `json:"transaction"`
-       SignComplete bool                `json:"sign_complete"`
-}
-
-func (a *API) signWithKey(ins struct {
-       Xprv        string             `json:"xprv"`
-       XPub        chainkd.XPub       `json:"xpub"`
-       Txs         mainchain.Template `json:"transaction"`
-       ClaimScript chainjson.HexBytes `json:"claim_script"`
-}) Response {
-       xprv := &chainkd.XPrv{}
-       if err := xprv.UnmarshalText([]byte(ins.Xprv)); err != nil {
                return NewErrorResponse(err)
        }
-       // pub + scriptPubKey 生成一个随机数A
-       var tmp [32]byte
-       h := hmac.New(sha256.New, ins.XPub[:])
-       h.Write(ins.ClaimScript)
-       tweak := h.Sum(tmp[:])
-       // pub +  A 生成一个新的公钥pub_new
-       privateKey := xprv.Child(tweak, false)
-
-       if err := sign(&ins.Txs, privateKey); err != nil {
-               return NewErrorResponse(err)
-       }
-       log.Info("Sign Transaction complete.")
-       log.Info(mainchain.SignProgress(&ins.Txs))
-       return NewSuccessResponse(&signRespForMainchain{Tx: &ins.Txs, SignComplete: mainchain.SignProgress(&ins.Txs)})
-}
-
-func sign(tmpl *mainchain.Template, xprv chainkd.XPrv) error {
-       for i, sigInst := range tmpl.SigningInstructions {
-               for j, wc := range sigInst.WitnessComponents {
-                       switch sw := wc.(type) {
-                       case *mainchain.SignatureWitness:
-                               err := sw.Sign(tmpl, uint32(i), xprv)
-                               if err != nil {
-                                       return errors.WithDetailf(err, "adding signature(s) to signature witness component %d of input %d", j, i)
-                               }
-                       case *mainchain.RawTxSigWitness:
-                               err := sw.Sign(tmpl, uint32(i), xprv)
-                               if err != nil {
-                                       return errors.WithDetailf(err, "adding signature(s) to raw-signature witness component %d of input %d", j, i)
-                               }
-                       }
-               }
-       }
-       return materializeWitnesses(tmpl)
-}
-
-func materializeWitnesses(txTemplate *mainchain.Template) error {
-       msg := txTemplate.Transaction
-
-       if msg == nil {
-               return errors.Wrap(txbuilder.ErrMissingRawTx)
-       }
-
-       if len(txTemplate.SigningInstructions) > len(msg.Inputs) {
-               return errors.Wrap(txbuilder.ErrBadInstructionCount)
-       }
-
-       for i, sigInst := range txTemplate.SigningInstructions {
-               if msg.Inputs[sigInst.Position] == nil {
-                       return errors.WithDetailf(txbuilder.ErrBadTxInputIdx, "signing instruction %d references missing tx input %d", i, sigInst.Position)
-               }
-
-               var witness [][]byte
-               for j, wc := range sigInst.WitnessComponents {
-                       err := wc.Materialize(&witness)
-                       if err != nil {
-                               return errors.WithDetailf(err, "error in witness component %d of input %d", j, i)
-                       }
-               }
-               msg.SetInputArguments(sigInst.Position, witness)
-       }
-
-       return nil
+       return NewSuccessResponse(resp)
 }
index 79ab3a9..b59af89 100644 (file)
@@ -3,6 +3,7 @@ package api
 import (
        "context"
        "encoding/hex"
+       "encoding/json"
        "fmt"
 
        "github.com/vapor/blockchain/txbuilder"
@@ -13,13 +14,13 @@ import (
        "github.com/vapor/account"
        "github.com/vapor/blockchain/query"
        "github.com/vapor/blockchain/signers"
+       bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
        "github.com/vapor/consensus"
        "github.com/vapor/crypto/ed25519/chainkd"
        chainjson "github.com/vapor/encoding/json"
        "github.com/vapor/errors"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
-       bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
 )
 
 // POST /list-accounts
@@ -477,7 +478,7 @@ func (a *API) getSideRawTransaction(ins struct {
 }
 
 type utxoResp struct {
-       Utxo account.UTXO `json:"utxo"`
+       Utxo []byte `json:"utxo"`
 }
 
 func (a *API) getUnspentOutputs(ins struct {
@@ -488,8 +489,7 @@ func (a *API) getUnspentOutputs(ins struct {
 }) Response {
        var rawTransaction *bytomtypes.Tx
        block := &bytomtypes.Block{}
-       err := block.UnmarshalText([]byte(ins.RawBlock))
-       if err != nil {
+       if err := block.UnmarshalText([]byte(ins.RawBlock)); err != nil {
                return NewErrorResponse(err)
        }
 
@@ -544,5 +544,10 @@ func (a *API) getUnspentOutputs(ins struct {
                }
        }
 
-       return NewSuccessResponse(&utxoResp{Utxo: utxo})
+       resp, err := json.Marshal(&utxo)
+       if err != nil {
+               return NewErrorResponse(err)
+       }
+
+       return NewSuccessResponse(&utxoResp{Utxo: resp})
 }
index 7ccffc0..87cab43 100644 (file)
@@ -4,6 +4,7 @@ import (
        "context"
 
        "github.com/vapor/blockchain/txbuilder"
+       "github.com/vapor/claim/rpc"
        chainjson "github.com/vapor/encoding/json"
 )
 
@@ -38,55 +39,33 @@ type fundingResp struct {
        ClaimScript      chainjson.HexBytes `json:"claim_script"`
 }
 
-func (a *API) getPeginAddress(ctx context.Context, ins struct {
-       AccountID    string `json:"account_id"`
-       AccountAlias string `json:"account_alias"`
-}) Response {
-
-       accountID := ins.AccountID
-       if ins.AccountAlias != "" {
-               account, err := a.wallet.AccountMgr.FindByAlias(ins.AccountAlias)
-               if err != nil {
-                       return NewErrorResponse(err)
-               }
+func (a *API) getPeginAddress(ctx context.Context, ins rpc.ClaimArgs) Response {
 
-               accountID = account.ID
+       pegin := &rpc.BytomPeginRpc{
+               ClaimArgs: ins,
+               Wallet:    a.wallet,
        }
 
-       mainchainAddress, claimScript, err := a.wallet.AccountMgr.CreatePeginAddress(accountID, false)
+       resp, err := pegin.GetPeginAddress()
        if err != nil {
                return NewErrorResponse(err)
        }
 
-       return NewSuccessResponse(fundingResp{
-               MainchainAddress: mainchainAddress,
-               ClaimScript:      claimScript,
-       })
+       return NewSuccessResponse(resp)
 }
 
 func (a *API) getPeginContractAddress(ctx context.Context, ins struct {
        AccountID    string `json:"account_id"`
        AccountAlias string `json:"account_alias"`
 }) Response {
-
-       accountID := ins.AccountID
-       if ins.AccountAlias != "" {
-               account, err := a.wallet.AccountMgr.FindByAlias(ins.AccountAlias)
-               if err != nil {
-                       return NewErrorResponse(err)
-               }
-
-               accountID = account.ID
+       pegin := &rpc.BytomPeginRpc{
+               ClaimArgs: ins,
+               Wallet:    a.wallet,
        }
-
-       mainchainAddress, controlProgram, claimScript, err := a.wallet.AccountMgr.CreatePeginContractAddress(accountID, false)
+       resp, err := pegin.GetPeginContractAddress()
        if err != nil {
                return NewErrorResponse(err)
        }
 
-       return NewSuccessResponse(fundingResp{
-               MainchainAddress: mainchainAddress,
-               ControlProgram:   controlProgram,
-               ClaimScript:      claimScript,
-       })
+       return NewSuccessResponse(resp)
 }
index 1cafe4f..daa6308 100644 (file)
@@ -88,8 +88,6 @@ func checkTxSighashCommitment(tx *types.Tx) error {
                        args = t.Arguments
                case *types.ClaimInput:
                        args = t.Arguments
-               case *types.DposTx:
-                       args = t.Arguments
                }
                // Note: These numbers will need to change if more args are added such that the minimum length changes
                switch {
@@ -133,7 +131,7 @@ func CalculateTxFee(tx *types.Tx) (fee uint64) {
        totalOutputBTM := uint64(0)
 
        for _, input := range tx.Inputs {
-               if input.InputType() != types.CoinbaseInputType && input.InputType() != types.DposInputType && input.AssetID() == *consensus.BTMAssetID {
+               if input.InputType() != types.CoinbaseInputType && input.AssetID() == *consensus.BTMAssetID {
                        totalInputBTM += input.Amount()
                }
        }
diff --git a/blockchain/txbuilder/mainchain/types.go b/blockchain/txbuilder/mainchain/types.go
deleted file mode 100644 (file)
index d0497a1..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-package mainchain
-
-import (
-       "context"
-       "encoding/json"
-
-       "github.com/vapor/crypto/ed25519/chainkd"
-       chainjson "github.com/vapor/encoding/json"
-       "github.com/vapor/protocol/bc"
-       bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
-)
-
-// Template represents a partially- or fully-signed transaction.
-type Template struct {
-       Transaction         *bytomtypes.Tx        `json:"raw_transaction"`
-       SigningInstructions []*SigningInstruction `json:"signing_instructions"`
-
-       // AllowAdditional affects whether Sign commits to the tx sighash or
-       // to individual details of the tx so far. When true, signatures
-       // commit to tx details, and new details may be added but existing
-       // ones cannot be changed. When false, signatures commit to the tx
-       // as a whole, and any change to the tx invalidates the signature.
-       AllowAdditional bool `json:"allow_additional_actions"`
-}
-
-// Hash return sign hash
-func (t *Template) Hash(idx uint32) bc.Hash {
-       return t.Transaction.SigHash(idx)
-}
-
-// Action is a interface
-type Action interface {
-       Build(context.Context, *TemplateBuilder) error
-}
-
-// Receiver encapsulates information about where to send assets.
-type Receiver struct {
-       ControlProgram chainjson.HexBytes `json:"control_program,omitempty"`
-       Address        string             `json:"address,omitempty"`
-}
-
-// ContractArgument for smart contract
-type ContractArgument struct {
-       Type    string          `json:"type"`
-       RawData json.RawMessage `json:"raw_data"`
-}
-
-// RawTxSigArgument is signature-related argument for run contract
-type RawTxSigArgument struct {
-       RootXPub chainkd.XPub         `json:"xpub"`
-       Path     []chainjson.HexBytes `json:"derivation_path"`
-}
-
-// DataArgument is the other argument for run contract
-type DataArgument struct {
-       Value string `json:"value"`
-}
similarity index 84%
rename from blockchain/txbuilder/mainchain/builder.go
rename to claim/bytom/mainchain/builder.go
index ad12483..e11003d 100644 (file)
@@ -5,8 +5,9 @@ import (
        "time"
 
        "github.com/vapor/blockchain/txbuilder"
+       bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
+       "github.com/vapor/consensus"
        "github.com/vapor/errors"
-       bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
 )
 
 // NewBuilder return new TemplateBuilder instance
@@ -128,5 +129,27 @@ func (b *TemplateBuilder) Build() (*Template, *bytomtypes.TxData, error) {
        }
 
        tpl.Transaction = bytomtypes.NewTx(*tx)
+       tpl.Fee = CalculateTxFee(tpl.Transaction)
        return tpl, tx, nil
 }
+
+// CalculateTxFee calculate transaction fee
+func CalculateTxFee(tx *bytomtypes.Tx) (fee uint64) {
+       totalInputBTM := uint64(0)
+       totalOutputBTM := uint64(0)
+
+       for _, input := range tx.Inputs {
+               if input.InputType() != bytomtypes.CoinbaseInputType && input.AssetID() == *consensus.BTMAssetID {
+                       totalInputBTM += input.Amount()
+               }
+       }
+
+       for _, output := range tx.Outputs {
+               if *output.AssetId == *consensus.BTMAssetID {
+                       totalOutputBTM += output.Amount
+               }
+       }
+
+       fee = totalInputBTM - totalOutputBTM
+       return
+}
diff --git a/claim/bytom/mainchain/types.go b/claim/bytom/mainchain/types.go
new file mode 100644 (file)
index 0000000..ddb0f94
--- /dev/null
@@ -0,0 +1,170 @@
+package mainchain
+
+import (
+       "context"
+       "encoding/hex"
+       "encoding/json"
+       "fmt"
+
+       bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
+       "github.com/vapor/crypto/ed25519/chainkd"
+       "github.com/vapor/encoding/blockchain"
+       "github.com/vapor/encoding/bufpool"
+       chainjson "github.com/vapor/encoding/json"
+       "github.com/vapor/errors"
+       "github.com/vapor/protocol/bc"
+)
+
+// Template represents a partially- or fully-signed transaction.
+type Template struct {
+       Transaction         *bytomtypes.Tx        `json:"raw_transaction"`
+       SigningInstructions []*SigningInstruction `json:"signing_instructions"`
+       Fee                 uint64                `json:"fee"`
+       // AllowAdditional affects whether Sign commits to the tx sighash or
+       // to individual details of the tx so far. When true, signatures
+       // commit to tx details, and new details may be added but existing
+       // ones cannot be changed. When false, signatures commit to the tx
+       // as a whole, and any change to the tx invalidates the signature.
+       AllowAdditional bool `json:"allow_additional_actions"`
+}
+
+// Hash return sign hash
+func (t *Template) Hash(idx uint32) bc.Hash {
+       return t.Transaction.SigHash(idx)
+}
+
+func MarshalText(t *Template) ([]byte, error) {
+       buf := bufpool.Get()
+       defer bufpool.Put(buf)
+
+       ew := errors.NewWriter(buf)
+       transaction, err := t.Transaction.MarshalText()
+       if err != nil {
+               return nil, err
+       }
+
+       if _, err := blockchain.WriteVarstr31(ew, transaction); err != nil {
+               return nil, err
+       }
+
+       if _, err := blockchain.WriteVarint31(ew, uint64(len(t.SigningInstructions))); err != nil {
+               return nil, err
+       }
+
+       for _, signingInstruction := range t.SigningInstructions {
+               b, err := json.MarshalIndent(signingInstruction, "", "  ")
+               if err != nil {
+                       return nil, err
+               }
+               if _, err := blockchain.WriteVarstr31(ew, b); err != nil {
+                       return nil, err
+               }
+       }
+
+       if _, err := blockchain.WriteVarint63(ew, t.Fee); err != nil {
+               return nil, err
+       }
+
+       allowAdditional, err := json.Marshal(t.AllowAdditional)
+       if err != nil {
+               return nil, err
+       }
+       if _, err := blockchain.WriteVarstr31(ew, allowAdditional); err != nil {
+               return nil, err
+       }
+
+       if ew.Err() != nil {
+               return nil, ew.Err()
+       }
+
+       enc := make([]byte, hex.EncodedLen(buf.Len()))
+       hex.Encode(enc, buf.Bytes())
+       return enc, nil
+}
+
+func UnmarshalText(text []byte, t *Template) error {
+       decoded := make([]byte, hex.DecodedLen(len(text)))
+       if _, err := hex.Decode(decoded, text); err != nil {
+               return err
+       }
+
+       r := blockchain.NewReader(decoded)
+
+       b, err := blockchain.ReadVarstr31(r)
+       if err != nil {
+               return err
+       }
+
+       t.Transaction = &bytomtypes.Tx{}
+
+       if err = t.Transaction.UnmarshalText(b); err != nil {
+               return err
+       }
+
+       n, err := blockchain.ReadVarint31(r)
+       if err != nil {
+               return errors.Wrap(err, "reading number of transactions")
+       }
+
+       for ; n > 0; n-- {
+               var signingInstruction SigningInstruction
+               b, err := blockchain.ReadVarstr31(r)
+               if err != nil {
+                       return err
+               }
+               err = json.Unmarshal(b, &signingInstruction)
+               if err != nil {
+                       fmt.Errorf("error on input %s: %s", b, err)
+               }
+
+               t.SigningInstructions = append(t.SigningInstructions, &signingInstruction)
+       }
+
+       if t.Fee, err = blockchain.ReadVarint63(r); err != nil {
+               return err
+       }
+
+       b, err = blockchain.ReadVarstr31(r)
+       if err != nil {
+               return err
+       }
+
+       err = json.Unmarshal(b, &t.AllowAdditional)
+       if err != nil {
+               fmt.Errorf("error on input %s: %s", b, err)
+       }
+
+       if trailing := r.Len(); trailing > 0 {
+               return fmt.Errorf("trailing garbage (%d bytes)", trailing)
+       }
+
+       return nil
+}
+
+// Action is a interface
+type Action interface {
+       Build(context.Context, *TemplateBuilder) error
+}
+
+// Receiver encapsulates information about where to send assets.
+type Receiver struct {
+       ControlProgram chainjson.HexBytes `json:"control_program,omitempty"`
+       Address        string             `json:"address,omitempty"`
+}
+
+// ContractArgument for smart contract
+type ContractArgument struct {
+       Type    string          `json:"type"`
+       RawData json.RawMessage `json:"raw_data"`
+}
+
+// RawTxSigArgument is signature-related argument for run contract
+type RawTxSigArgument struct {
+       RootXPub chainkd.XPub         `json:"xpub"`
+       Path     []chainjson.HexBytes `json:"derivation_path"`
+}
+
+// DataArgument is the other argument for run contract
+type DataArgument struct {
+       Value string `json:"value"`
+}
similarity index 89%
rename from protocol/bc/types/bytom/block.go
rename to claim/bytom/protocolbc/block.go
index 38611a0..2d0fceb 100644 (file)
@@ -1,4 +1,4 @@
-package bytom
+package protocolbc
 
 import "github.com/vapor/protocol/bc"
 
similarity index 99%
rename from protocol/bc/types/bytom/general.go
rename to claim/bytom/protocolbc/general.go
index 9fa860f..513fb12 100644 (file)
@@ -1,4 +1,4 @@
-package bytom
+package protocolbc
 
 import (
        "encoding/binary"
similarity index 99%
rename from protocol/bc/types/bytom/tx.go
rename to claim/bytom/protocolbc/tx.go
index a5fa896..3af6518 100644 (file)
@@ -1,4 +1,4 @@
-package bytom
+package protocolbc
 
 import (
        "github.com/vapor/crypto/sha3pool"
similarity index 99%
rename from protocol/bc/types/bytom/types/map.go
rename to claim/bytom/protocolbc/types/map.go
index 4892c19..92beecb 100644 (file)
@@ -1,10 +1,10 @@
 package types
 
 import (
+       bytom "github.com/vapor/claim/bytom/protocolbc"
        "github.com/vapor/consensus"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
-       "github.com/vapor/protocol/bc/types/bytom"
        "github.com/vapor/protocol/vm"
        "github.com/vapor/protocol/vm/vmutil"
 )
similarity index 98%
rename from protocol/bc/types/bytom/types/transaction.go
rename to claim/bytom/protocolbc/types/transaction.go
index c1aa00b..235154b 100644 (file)
@@ -6,10 +6,10 @@ import (
        "fmt"
        "io"
 
+       bytom "github.com/vapor/claim/bytom/protocolbc"
        "github.com/vapor/encoding/blockchain"
        "github.com/vapor/errors"
        "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types/bytom"
 )
 
 const serRequired = 0x7 // Bit mask accepted serialization flag.
@@ -70,7 +70,7 @@ type TxData struct {
 func (tx *TxData) MarshalText() ([]byte, error) {
        var buf bytes.Buffer
        if _, err := tx.WriteTo(&buf); err != nil {
-               return nil, nil
+               return nil, err
        }
 
        b := make([]byte, hex.EncodedLen(buf.Len()))
diff --git a/claim/bytom_validation.go b/claim/bytom_validation.go
new file mode 100644 (file)
index 0000000..252e3dd
--- /dev/null
@@ -0,0 +1,131 @@
+package claim
+
+import (
+       "bytes"
+       "encoding/json"
+       "strconv"
+
+       bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
+       "github.com/vapor/consensus"
+       "github.com/vapor/crypto"
+       "github.com/vapor/equity/pegin_contract"
+       "github.com/vapor/errors"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+       "github.com/vapor/protocol/vm/vmutil"
+       "github.com/vapor/util"
+)
+
+type MerkleBlock struct {
+       BlockHeader  []byte     `json:"block_header"`
+       TxHashes     []*bc.Hash `json:"tx_hashes"`
+       StatusHashes []*bc.Hash `json:"status_hashes"`
+       Flags        []uint32   `json:"flags"`
+       MatchedTxIDs []*bc.Hash `json:"matched_tx_ids"`
+}
+
+type BytomClaimValidation struct {
+}
+
+func (b *BytomClaimValidation) IsValidPeginWitness(peginWitness [][]byte, prevout bc.Output) (err error) {
+
+       assetAmount := &bc.AssetAmount{
+               AssetId: prevout.Source.Value.AssetId,
+               Amount:  prevout.Source.Value.Amount,
+       }
+
+       src := &bc.ValueSource{
+               Ref:      prevout.Source.Ref,
+               Value:    assetAmount,
+               Position: prevout.Source.Position,
+       }
+       prog := &bc.Program{prevout.ControlProgram.VmVersion, prevout.ControlProgram.Code}
+       bytomPrevout := bc.NewOutput(src, prog, prevout.Source.Position)
+
+       if len(peginWitness) != 5 {
+               return errors.New("peginWitness is error")
+       }
+       amount, err := strconv.ParseUint(string(peginWitness[0]), 10, 64)
+       if err != nil {
+               return err
+       }
+       if !consensus.MoneyRange(amount) {
+               return errors.New("Amount out of range")
+       }
+       /*
+               if len(peginWitness[1]) != 32 {
+                       return errors.New("The length of gennesisBlockHash is not correct")
+               }
+       */
+       claimScript := peginWitness[2]
+
+       rawTx := &bytomtypes.Tx{}
+       err = rawTx.UnmarshalText(peginWitness[3])
+       if err != nil {
+               return err
+       }
+
+       merkleBlock := &MerkleBlock{}
+       err = json.Unmarshal(peginWitness[4], merkleBlock)
+       if err != nil {
+               return err
+       }
+       // proof验证
+       var flags []uint8
+       for flag := range merkleBlock.Flags {
+               flags = append(flags, uint8(flag))
+       }
+       blockHeader := &bytomtypes.BlockHeader{}
+       if err = blockHeader.UnmarshalText(merkleBlock.BlockHeader); err != nil {
+               return err
+       }
+
+       if !types.ValidateTxMerkleTreeProof(merkleBlock.TxHashes, flags, merkleBlock.MatchedTxIDs, blockHeader.BlockCommitment.TransactionsMerkleRoot) {
+               return errors.New("Merkleblock validation failed")
+       }
+
+       // 交易进行验证
+       if err = b.checkPeginTx(rawTx, bytomPrevout, amount, claimScript); err != nil {
+               return err
+       }
+       var hash bc.Hash
+       hash.UnmarshalText(peginWitness[1])
+       // Check the genesis block corresponds to a valid peg (only one for now)
+       if hash.String() != consensus.ActiveNetParams.ParentGenesisBlockHash {
+               return errors.New("ParentGenesisBlockHash don't match")
+       }
+       // TODO Finally, validate peg-in via rpc call
+
+       if util.ValidatePegin {
+               if err := util.IsConfirmedBytomBlock(blockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
+
+func (b *BytomClaimValidation) checkPeginTx(rawTx *bytomtypes.Tx, prevout *bc.Output, claimAmount uint64, claimScript []byte) error {
+       // Check the transaction nout/value matches
+       amount := rawTx.Outputs[prevout.Source.Position].Amount
+       if claimAmount != amount {
+               return errors.New("transaction nout/value do not matches")
+       }
+       // Check that the witness program matches the p2ch on the p2sh-p2wsh transaction output
+       //federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
+       //scriptHash := crypto.Sha256(federationRedeemScript)
+       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(claimScript)
+       if err != nil {
+               return err
+       }
+
+       scriptHash := crypto.Sha256(peginContractPrograms)
+       controlProg, err := vmutil.P2WSHProgram(scriptHash)
+       if err != nil {
+               return err
+       }
+       if !bytes.Equal(rawTx.Outputs[prevout.Source.Position].ControlProgram, controlProg) {
+               return errors.New("The output control program of transaction does not match the control program of the system's alliance contract")
+       }
+       return nil
+}
diff --git a/claim/claim.go b/claim/claim.go
new file mode 100644 (file)
index 0000000..fd9273d
--- /dev/null
@@ -0,0 +1,4 @@
+package claim
+
+type Claim interface {
+}
diff --git a/claim/rpc/bytom/bytom_claim_tx.go b/claim/rpc/bytom/bytom_claim_tx.go
new file mode 100644 (file)
index 0000000..f7a13f2
--- /dev/null
@@ -0,0 +1,496 @@
+package bytom
+
+import (
+       "bytes"
+       "context"
+       "encoding/json"
+       "math"
+       "strconv"
+       "time"
+
+       log "github.com/sirupsen/logrus"
+
+       "github.com/vapor/account"
+       "github.com/vapor/blockchain/txbuilder"
+       "github.com/vapor/claim"
+       bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
+       "github.com/vapor/claim/rpc"
+       "github.com/vapor/consensus"
+       "github.com/vapor/consensus/segwit"
+       "github.com/vapor/crypto/ed25519/chainkd"
+       "github.com/vapor/crypto/sha3pool"
+       chainjson "github.com/vapor/encoding/json"
+       "github.com/vapor/errors"
+       "github.com/vapor/math/checked"
+       "github.com/vapor/protocol"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+       "github.com/vapor/util"
+       "github.com/vapor/wallet"
+)
+
+func getPeginTxnOutputIndex(rawTx bytomtypes.Tx, controlProg []byte) int {
+       for index, output := range rawTx.Outputs {
+               if bytes.Equal(output.ControlProgram, controlProg) {
+                       return index
+               }
+       }
+       return -1
+}
+
+func toHash(hexBytes []chainjson.HexBytes) (hashs []*bc.Hash) {
+       for _, data := range hexBytes {
+               b32 := [32]byte{}
+               copy(b32[:], data)
+               res := bc.NewHash(b32)
+               hashs = append(hashs, &res)
+       }
+       return
+}
+
+type BytomClaimTx struct {
+       rpc.ClaimTxParam
+       Wallet *wallet.Wallet
+       Chain  *protocol.Chain
+}
+
+func (b *BytomClaimTx) pseudohsmSignTemplate(ctx context.Context, xpub chainkd.XPub, path [][]byte, data [32]byte, password string) ([]byte, error) {
+       return b.Wallet.Hsm.XSign(xpub, path, data[:], password)
+}
+
+func (b *BytomClaimTx) ClaimPeginTx(ctx context.Context) (interface{}, error) {
+       tmpl, err := b.createRawPegin(b.ClaimTxParam)
+       if err != nil {
+               log.WithField("build err", err).Error("fail on createrawpegin.")
+               return nil, err
+       }
+
+       // 交易签名
+       if err := txbuilder.Sign(ctx, tmpl, b.ClaimTxParam.Password, b.pseudohsmSignTemplate); err != nil {
+               log.WithField("build err", err).Error("fail on sign transaction.")
+               return nil, err
+       }
+
+       // submit
+       if err := txbuilder.FinalizeTx(ctx, b.Chain, tmpl.Transaction); err != nil {
+               return nil, err
+       }
+
+       log.WithField("tx_id", tmpl.Transaction.ID.String()).Info("claim script tx")
+       return &struct {
+               TxID *bc.Hash `json:"tx_id"`
+       }{TxID: &tmpl.Transaction.ID}, nil
+}
+
+func (b *BytomClaimTx) createRawPegin(ins rpc.ClaimTxParam) (*txbuilder.Template, error) {
+       // proof验证
+       var flags []uint8
+       for flag := range ins.Flags {
+               flags = append(flags, uint8(flag))
+       }
+       txHashes := toHash(ins.TxHashes)
+       matchedTxIDs := toHash(ins.MatchedTxIDs)
+       statusHashes := toHash(ins.StatusHashes)
+       blockHeader := &bytomtypes.BlockHeader{}
+       if err := blockHeader.UnmarshalText([]byte(ins.BlockHeader)); err != nil {
+               return nil, err
+       }
+       if !types.ValidateTxMerkleTreeProof(txHashes, flags, matchedTxIDs, blockHeader.BlockCommitment.TransactionsMerkleRoot) {
+               return nil, errors.New("Merkleblock validation failed")
+       }
+       // CheckBytomProof
+       //difficulty.CheckBytomProofOfWork(ins.BlockHeader.Hash(), ins.BlockHeader)
+       // 增加spv验证以及连接主链api查询交易的确认数
+       if util.ValidatePegin {
+               if err := util.IsConfirmedBytomBlock(blockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
+                       return nil, err
+               }
+       }
+       // 找出与claim script有关联的交易的输出
+       var claimScript []byte
+       rawTx := &bytomtypes.Tx{}
+       if err := rawTx.UnmarshalText([]byte(ins.RawTx)); err != nil {
+               return nil, err
+       }
+       nOut := len(rawTx.Outputs)
+       if ins.ClaimScript == nil {
+               // 遍历寻找与交易输出有关的claim script
+               cps, err := b.Wallet.AccountMgr.ListControlProgram()
+               if err != nil {
+                       return nil, err
+               }
+
+               for _, cp := range cps {
+                       _, controlProg := b.Wallet.AccountMgr.GetPeginControlPrograms(cp.ControlProgram)
+                       if controlProg == nil {
+                               continue
+                       }
+                       // 获取交易的输出
+                       nOut = getPeginTxnOutputIndex(*rawTx, controlProg)
+                       if nOut != len(rawTx.Outputs) {
+                               claimScript = cp.ControlProgram
+                       }
+               }
+       } else {
+               claimScript = ins.ClaimScript
+               _, controlProg := b.Wallet.AccountMgr.GetPeginControlPrograms(claimScript)
+               // 获取交易的输出
+               nOut = getPeginTxnOutputIndex(*rawTx, controlProg)
+       }
+       if nOut == len(rawTx.Outputs) || nOut == -1 {
+               return nil, errors.New("Failed to find output in bytom to the mainchain_address from getpeginaddress")
+       }
+
+       // 根据ClaimScript 获取account id
+       var hash [32]byte
+       sha3pool.Sum256(hash[:], claimScript)
+       data := b.Wallet.DB.Get(account.ContractKey(hash))
+       if data == nil {
+               return nil, errors.New("Failed to find control program through claim script")
+       }
+
+       cp := &account.CtrlProgram{}
+       if err := json.Unmarshal(data, cp); err != nil {
+               return nil, errors.New("Failed on unmarshal control program")
+       }
+
+       // 构造交易
+       // 用输出作为交易输入 生成新的交易
+       builder := txbuilder.NewBuilder(time.Now())
+       // TODO 根据raw tx生成一个utxo
+       sourceID := *rawTx.OutputID(nOut)
+       outputAccount := rawTx.Outputs[nOut].Amount
+       assetID := *rawTx.Outputs[nOut].AssetId
+
+       txInput := types.NewClaimInput(nil, sourceID, assetID, outputAccount, uint64(nOut), cp.ControlProgram)
+       if err := builder.AddInput(txInput, &txbuilder.SigningInstruction{}); err != nil {
+               return nil, err
+       }
+       program, err := b.Wallet.AccountMgr.CreateAddress(cp.AccountID, false)
+       if err != nil {
+               return nil, err
+       }
+
+       if err = builder.AddOutput(types.NewTxOutput(assetID, outputAccount, program.ControlProgram)); err != nil {
+               return nil, err
+       }
+
+       tmpl, txData, err := builder.Build()
+       if err != nil {
+               return nil, err
+       }
+
+       // todo把一些主链的信息加到交易的stack中
+       var stack [][]byte
+
+       //amount
+       amount := strconv.FormatUint(rawTx.Outputs[nOut].Amount, 10)
+       stack = append(stack, []byte(amount))
+       // 主链的gennesisBlockHash
+       stack = append(stack, []byte(consensus.ActiveNetParams.ParentGenesisBlockHash))
+       // claim script
+       stack = append(stack, claimScript)
+       // raw tx
+       tx, _ := json.Marshal(rawTx)
+       stack = append(stack, tx)
+       // proof
+       blockHeaderByte, err := blockHeader.MarshalText()
+       if err != nil {
+               return nil, err
+       }
+       merkleBlock := claim.MerkleBlock{
+               BlockHeader:  blockHeaderByte,
+               TxHashes:     txHashes,
+               StatusHashes: statusHashes,
+               Flags:        ins.Flags,
+               MatchedTxIDs: matchedTxIDs,
+       }
+
+       txOutProof, _ := json.Marshal(merkleBlock)
+
+       stack = append(stack, txOutProof)
+
+       //      tmpl.Transaction.Inputs[0].Peginwitness = stack
+       txData.Inputs[0].Peginwitness = stack
+
+       //交易费估算
+       txGasResp, err := EstimateTxGas(*tmpl)
+       if err != nil {
+               return nil, err
+       }
+       txData.Outputs[0].Amount = txData.Outputs[0].Amount - uint64(txGasResp.TotalNeu)
+       //重设置Transaction
+       tmpl.Transaction = types.NewTx(*txData)
+       return tmpl, nil
+}
+
+func (b *BytomClaimTx) ClaimContractPeginTx(ctx context.Context) (interface{}, error) {
+       tmpl, err := b.createContractRawPegin(b.ClaimTxParam)
+       if err != nil {
+               log.WithField("build err", err).Error("fail on claimContractPeginTx.")
+               return nil, err
+       }
+       // 交易签名
+       if err := txbuilder.Sign(ctx, tmpl, b.Password, b.pseudohsmSignTemplate); err != nil {
+               log.WithField("build err", err).Error("fail on sign transaction.")
+               return nil, err
+       }
+
+       // submit
+       if err := txbuilder.FinalizeTx(ctx, b.Chain, tmpl.Transaction); err != nil {
+               return nil, err
+       }
+
+       log.WithField("tx_id", tmpl.Transaction.ID.String()).Info("claim script tx")
+       return &struct {
+               TxID *bc.Hash `json:"tx_id"`
+       }{TxID: &tmpl.Transaction.ID}, nil
+}
+
+func (b *BytomClaimTx) createContractRawPegin(ins rpc.ClaimTxParam) (*txbuilder.Template, error) {
+       // proof验证
+       var flags []uint8
+       for flag := range ins.Flags {
+               flags = append(flags, uint8(flag))
+       }
+       txHashes := toHash(ins.TxHashes)
+       matchedTxIDs := toHash(ins.MatchedTxIDs)
+       statusHashes := toHash(ins.StatusHashes)
+       blockHeader := &bytomtypes.BlockHeader{}
+       if err := blockHeader.UnmarshalText([]byte(ins.BlockHeader)); err != nil {
+               return nil, err
+       }
+
+       if !types.ValidateTxMerkleTreeProof(txHashes, flags, matchedTxIDs, blockHeader.BlockCommitment.TransactionsMerkleRoot) {
+               return nil, errors.New("Merkleblock validation failed")
+       }
+       // CheckBytomProof
+       //difficulty.CheckBytomProofOfWork(ins.BlockHeader.Hash(), ins.BlockHeader)
+       // 增加spv验证以及连接主链api查询交易的确认数
+       if util.ValidatePegin {
+               if err := util.IsConfirmedBytomBlock(blockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
+                       return nil, err
+               }
+       }
+       // 找出与claim script有关联的交易的输出
+       var claimScript []byte
+       rawTx := &bytomtypes.Tx{}
+       if err := rawTx.UnmarshalText([]byte(ins.RawTx)); err != nil {
+               return nil, err
+       }
+
+       nOut := len(rawTx.Outputs)
+       if ins.ClaimScript == nil {
+               // 遍历寻找与交易输出有关的claim script
+               cps, err := b.Wallet.AccountMgr.ListControlProgram()
+               if err != nil {
+                       return nil, err
+               }
+
+               for _, cp := range cps {
+                       _, controlProg := b.Wallet.AccountMgr.GetPeginContractControlPrograms(claimScript)
+                       // 获取交易的输出
+                       nOut = getPeginTxnOutputIndex(*rawTx, controlProg)
+                       if nOut != len(rawTx.Outputs) {
+                               claimScript = cp.ControlProgram
+                       }
+               }
+       } else {
+               claimScript = ins.ClaimScript
+               _, controlProg := b.Wallet.AccountMgr.GetPeginContractControlPrograms(claimScript)
+               // 获取交易的输出
+               nOut = getPeginTxnOutputIndex(*rawTx, controlProg)
+       }
+       if nOut == len(rawTx.Outputs) || nOut == -1 {
+               return nil, errors.New("Failed to find output in bytom to the mainchain_address from createContractRawPegin")
+       }
+
+       // 根据ClaimScript 获取account id
+       var hash [32]byte
+       sha3pool.Sum256(hash[:], claimScript)
+       data := b.Wallet.DB.Get(account.ContractKey(hash))
+       if data == nil {
+               return nil, errors.New("Failed to find control program through claim script")
+       }
+
+       cp := &account.CtrlProgram{}
+       if err := json.Unmarshal(data, cp); err != nil {
+               return nil, errors.New("Failed on unmarshal control program")
+       }
+
+       // 构造交易
+       // 用输出作为交易输入 生成新的交易
+       builder := txbuilder.NewBuilder(time.Now())
+       // TODO 根据raw tx生成一个utxo
+
+       sourceID := *rawTx.OutputID(nOut)
+       outputAccount := rawTx.Outputs[nOut].Amount
+       assetID := *rawTx.Outputs[nOut].AssetId
+
+       txInput := types.NewClaimInput(nil, sourceID, assetID, outputAccount, uint64(nOut), cp.ControlProgram)
+       if err := builder.AddInput(txInput, &txbuilder.SigningInstruction{}); err != nil {
+               return nil, err
+       }
+       program, err := b.Wallet.AccountMgr.CreateAddress(cp.AccountID, false)
+       if err != nil {
+               return nil, err
+       }
+
+       if err = builder.AddOutput(types.NewTxOutput(assetID, outputAccount, program.ControlProgram)); err != nil {
+               return nil, err
+       }
+
+       tmpl, txData, err := builder.Build()
+       if err != nil {
+               return nil, err
+       }
+
+       // todo把一些主链的信息加到交易的stack中
+       var stack [][]byte
+
+       //amount
+       amount := strconv.FormatUint(rawTx.Outputs[nOut].Amount, 10)
+       stack = append(stack, []byte(amount))
+       // 主链的gennesisBlockHash
+       stack = append(stack, []byte(consensus.ActiveNetParams.ParentGenesisBlockHash))
+       // claim script
+       stack = append(stack, claimScript)
+       // raw tx
+       tx, _ := rawTx.MarshalText()
+       stack = append(stack, tx)
+       // proof
+       blockHeaderByte, err := blockHeader.MarshalText()
+       if err != nil {
+               return nil, err
+       }
+       merkleBlock := claim.MerkleBlock{
+               BlockHeader:  blockHeaderByte,
+               TxHashes:     txHashes,
+               StatusHashes: statusHashes,
+               Flags:        ins.Flags,
+               MatchedTxIDs: matchedTxIDs,
+       }
+       txOutProof, _ := json.Marshal(merkleBlock)
+       stack = append(stack, txOutProof)
+       //      tmpl.Transaction.Inputs[0].Peginwitness = stack
+       txData.Inputs[0].Peginwitness = stack
+
+       //交易费估算
+       txGasResp, err := EstimateTxGas(*tmpl)
+       if err != nil {
+               return nil, err
+       }
+       txData.Outputs[0].Amount = txData.Outputs[0].Amount - uint64(txGasResp.TotalNeu)
+       //重设置Transaction
+       tmpl.Transaction = types.NewTx(*txData)
+       return tmpl, nil
+}
+
+// EstimateTxGasResp estimate transaction consumed gas
+type EstimateTxGasResp struct {
+       TotalNeu   int64 `json:"total_neu"`
+       StorageNeu int64 `json:"storage_neu"`
+       VMNeu      int64 `json:"vm_neu"`
+}
+
+var (
+       defaultBaseRate = float64(100000)
+       flexibleGas     = int64(1800)
+)
+
+// EstimateTxGas estimate consumed neu for transaction
+func EstimateTxGas(template txbuilder.Template) (*EstimateTxGasResp, error) {
+       // base tx size and not include sign
+       data, err := template.Transaction.TxData.MarshalText()
+       if err != nil {
+               return nil, err
+       }
+       baseTxSize := int64(len(data))
+
+       // extra tx size for sign witness parts
+       signSize := estimateSignSize(template.SigningInstructions)
+
+       // total gas for tx storage
+       totalTxSizeGas, ok := checked.MulInt64(baseTxSize+signSize, consensus.StorageGasRate)
+       if !ok {
+               return nil, errors.New("calculate txsize gas got a math error")
+       }
+
+       // consume gas for run VM
+       totalP2WPKHGas := int64(0)
+       totalP2WSHGas := int64(0)
+       baseP2WPKHGas := int64(1419)
+       // flexible Gas is used for handle need extra utxo situation
+
+       for pos, inpID := range template.Transaction.Tx.InputIDs {
+               sp, err := template.Transaction.Spend(inpID)
+               if err != nil {
+                       continue
+               }
+
+               resOut, err := template.Transaction.Output(*sp.SpentOutputId)
+               if err != nil {
+                       continue
+               }
+
+               if segwit.IsP2WPKHScript(resOut.ControlProgram.Code) {
+                       totalP2WPKHGas += baseP2WPKHGas
+               } else if segwit.IsP2WSHScript(resOut.ControlProgram.Code) {
+                       sigInst := template.SigningInstructions[pos]
+                       totalP2WSHGas += estimateP2WSHGas(sigInst)
+               }
+       }
+
+       // total estimate gas
+       totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas + flexibleGas
+
+       // rounding totalNeu with base rate 100000
+       totalNeu := float64(totalGas*consensus.VMGasRate) / defaultBaseRate
+       roundingNeu := math.Ceil(totalNeu)
+       estimateNeu := int64(roundingNeu) * int64(defaultBaseRate)
+
+       // TODO add priority
+
+       return &EstimateTxGasResp{
+               TotalNeu:   estimateNeu,
+               StorageNeu: totalTxSizeGas * consensus.VMGasRate,
+               VMNeu:      (totalP2WPKHGas + totalP2WSHGas) * consensus.VMGasRate,
+       }, nil
+}
+
+// estimate p2wsh gas.
+// OP_CHECKMULTISIG consume (984 * a - 72 * b - 63) gas,
+// where a represent the num of public keys, and b represent the num of quorum.
+func estimateP2WSHGas(sigInst *txbuilder.SigningInstruction) int64 {
+       P2WSHGas := int64(0)
+       baseP2WSHGas := int64(738)
+
+       for _, witness := range sigInst.WitnessComponents {
+               switch t := witness.(type) {
+               case *txbuilder.SignatureWitness:
+                       P2WSHGas += baseP2WSHGas + (984*int64(len(t.Keys)) - 72*int64(t.Quorum) - 63)
+               case *txbuilder.RawTxSigWitness:
+                       P2WSHGas += baseP2WSHGas + (984*int64(len(t.Keys)) - 72*int64(t.Quorum) - 63)
+               }
+       }
+       return P2WSHGas
+}
+
+// estimate signature part size.
+// if need multi-sign, calculate the size according to the length of keys.
+func estimateSignSize(signingInstructions []*txbuilder.SigningInstruction) int64 {
+       signSize := int64(0)
+       baseWitnessSize := int64(300)
+
+       for _, sigInst := range signingInstructions {
+               for _, witness := range sigInst.WitnessComponents {
+                       switch t := witness.(type) {
+                       case *txbuilder.SignatureWitness:
+                               signSize += int64(t.Quorum) * baseWitnessSize
+                       case *txbuilder.RawTxSigWitness:
+                               signSize += int64(t.Quorum) * baseWitnessSize
+                       }
+               }
+       }
+       return signSize
+}
diff --git a/claim/rpc/bytom/bytom_main_tx.go b/claim/rpc/bytom/bytom_main_tx.go
new file mode 100644 (file)
index 0000000..344d111
--- /dev/null
@@ -0,0 +1,366 @@
+package bytom
+
+import (
+       "bytes"
+       "crypto/hmac"
+       "crypto/sha256"
+       "encoding/json"
+       "time"
+
+       log "github.com/sirupsen/logrus"
+
+       "github.com/vapor/account"
+       "github.com/vapor/blockchain/txbuilder"
+       "github.com/vapor/claim/bytom/mainchain"
+       bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
+       "github.com/vapor/claim/rpc"
+       "github.com/vapor/common"
+       "github.com/vapor/consensus"
+       "github.com/vapor/crypto/ed25519/chainkd"
+       chainjson "github.com/vapor/encoding/json"
+       "github.com/vapor/equity/pegin_contract"
+       "github.com/vapor/errors"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+       "github.com/vapor/protocol/vm/vmutil"
+)
+
+type BytomMainTx struct {
+       rpc.MainTxParam
+}
+
+func (b *BytomMainTx) BuildMainChainTxForContract() ([]byte, error) {
+       var xpubs []chainkd.XPub
+       for _, pub := range b.Pubs {
+               xpub := chainkd.XPub{}
+               if err := xpub.UnmarshalText([]byte(pub)); err != nil {
+                       return nil, err
+               }
+               // pub + scriptPubKey 生成一个随机数A
+               var tmp [32]byte
+               h := hmac.New(sha256.New, xpub[:])
+               h.Write(b.ClaimScript)
+               tweak := h.Sum(tmp[:])
+               // pub +  A 生成一个新的公钥pub_new
+               chaildXPub := xpub.Child(tweak)
+               xpubs = append(xpubs, chaildXPub)
+       }
+
+       utxo := &account.UTXO{}
+       if err := json.Unmarshal([]byte(b.Utxo), utxo); err != nil {
+               return nil, err
+       }
+       txInput, sigInst, err := contractToInputs(utxo, xpubs, b.ClaimScript)
+       builder := mainchain.NewBuilder(time.Now())
+       builder.AddInput(txInput, sigInst)
+       changeAmount := uint64(0)
+       retire := false
+       tx := &types.Tx{}
+       if err := tx.UnmarshalText([]byte(b.Tx)); err != nil {
+               return nil, err
+       }
+       for _, key := range tx.GetResultIds() {
+               output, err := tx.Retire(*key)
+               if err != nil {
+                       log.WithFields(log.Fields{"moudle": "transact", "err": err}).Warn("buildMainChainTx error")
+                       continue
+               }
+               retire = true
+               var controlProgram []byte
+               retBool := true
+               if controlProgram, retBool = getInput(tx.Entries, *key, b.ControlProgram); !retBool {
+                       return nil, errors.New("The corresponding input cannot be found")
+               }
+
+               assetID := *output.Source.Value.AssetId
+               out := bytomtypes.NewTxOutput(assetID, output.Source.Value.Amount, controlProgram)
+               builder.AddOutput(out)
+               changeAmount = utxo.Amount - output.Source.Value.Amount
+       }
+
+       if !retire {
+               return nil, errors.New("It's not a transaction to retire assets")
+       }
+
+       if changeAmount > 100000000 {
+               u := utxo
+               out := bytomtypes.NewTxOutput(u.AssetID, changeAmount, utxo.ControlProgram)
+               builder.AddOutput(out)
+       }
+
+       tmpl, txData, err := builder.Build()
+       if err != nil {
+               return nil, err
+       }
+
+       for i, out := range tmpl.Transaction.Outputs {
+               if bytes.Equal(out.ControlProgram, utxo.ControlProgram) {
+                       if changeAmount-100000000 > 0 {
+                               txData.Outputs[i].Amount = changeAmount - 100000000
+                       }
+               }
+       }
+       tmpl.Transaction = bytomtypes.NewTx(*txData)
+       resp, err := mainchain.MarshalText(tmpl)
+       if err != nil {
+               return nil, err
+       }
+       return resp, nil
+}
+
+func (b *BytomMainTx) BuildMainChainTx() ([]byte, error) {
+       var xpubs []chainkd.XPub
+       for _, pub := range b.Pubs {
+
+               xpub := chainkd.XPub{}
+               if err := xpub.UnmarshalText([]byte(pub)); err != nil {
+                       return nil, err
+               }
+               // pub + scriptPubKey 生成一个随机数A
+               var tmp [32]byte
+               h := hmac.New(sha256.New, xpub[:])
+               h.Write(b.ClaimScript)
+               tweak := h.Sum(tmp[:])
+               // pub +  A 生成一个新的公钥pub_new
+               chaildXPub := xpub.Child(tweak)
+               xpubs = append(xpubs, chaildXPub)
+       }
+
+       utxo := &account.UTXO{}
+       if err := json.Unmarshal([]byte(b.Utxo), utxo); err != nil {
+               return nil, err
+       }
+
+       txInput, sigInst, err := utxoToInputs(xpubs, utxo)
+       if err != nil {
+               return nil, err
+       }
+
+       builder := mainchain.NewBuilder(time.Now())
+       builder.AddInput(txInput, sigInst)
+       changeAmount := uint64(0)
+       retire := false
+       tx := &types.Tx{}
+       if err := tx.UnmarshalText([]byte(b.Tx)); err != nil {
+               return nil, err
+       }
+       for _, key := range tx.GetResultIds() {
+               output, err := tx.Retire(*key)
+               if err != nil {
+                       log.WithFields(log.Fields{"moudle": "transact", "err": err}).Warn("buildMainChainTx error")
+                       continue
+               }
+               retire = true
+               var controlProgram []byte
+               retBool := true
+               if controlProgram, retBool = getInput(tx.Entries, *key, b.ControlProgram); !retBool {
+                       return nil, errors.New("The corresponding input cannot be found")
+               }
+
+               assetID := *output.Source.Value.AssetId
+               out := bytomtypes.NewTxOutput(assetID, output.Source.Value.Amount, controlProgram)
+               builder.AddOutput(out)
+               changeAmount = utxo.Amount - output.Source.Value.Amount
+
+       }
+
+       if !retire {
+               return nil, errors.New("It's not a transaction to retire assets")
+       }
+
+       if changeAmount > 0 {
+               u := utxo
+               out := bytomtypes.NewTxOutput(u.AssetID, changeAmount, utxo.ControlProgram)
+               builder.AddOutput(out)
+       }
+
+       tmpl, txData, err := builder.Build()
+       if err != nil {
+               return nil, err
+       }
+       /*
+               //交易费估算
+               txGasResp, err := EstimateTxGasForMainchain(*tmpl)
+               if err != nil {
+                       return nil, err
+               }
+       */
+       for i, out := range tmpl.Transaction.Outputs {
+               if bytes.Equal(out.ControlProgram, utxo.ControlProgram) {
+                       //tx.Outputs[i].Amount = changeAmount - uint64(txGasResp.TotalNeu)
+                       tx.Outputs[i].Amount = changeAmount - 100000000
+               }
+       }
+       tmpl.Transaction = bytomtypes.NewTx(*txData)
+       resp, err := json.Marshal(tmpl)
+
+       if err != nil {
+               return nil, err
+       }
+
+       return resp, nil
+}
+
+type BytomMainSign struct {
+       rpc.MainTxSignParam
+}
+
+func (b *BytomMainSign) SignWithKey() (interface{}, error) {
+       xprv := &chainkd.XPrv{}
+       if err := xprv.UnmarshalText([]byte(b.Xprv)); err != nil {
+               return nil, err
+       }
+
+       xpub := &chainkd.XPub{}
+       if err := xpub.UnmarshalText([]byte(b.XPub)); err != nil {
+               return nil, err
+       }
+
+       // pub + scriptPubKey 生成一个随机数A
+       var tmp [32]byte
+       h := hmac.New(sha256.New, xpub[:])
+       h.Write(b.ClaimScript)
+       tweak := h.Sum(tmp[:])
+       // pub +  A 生成一个新的公钥pub_new
+       privateKey := xprv.Child(tweak, false)
+
+       txs := &mainchain.Template{}
+       if err := mainchain.UnmarshalText([]byte(b.Txs), txs); err != nil {
+               return nil, err
+       }
+
+       if err := sign(txs, privateKey); err != nil {
+               return nil, err
+       }
+       log.Info("Sign Transaction complete.")
+       return struct {
+               Tx           *mainchain.Template `json:"transaction"`
+               SignComplete bool                `json:"sign_complete"`
+       }{Tx: txs, SignComplete: mainchain.SignProgress(txs)}, nil
+}
+
+func sign(tmpl *mainchain.Template, xprv chainkd.XPrv) error {
+       for i, sigInst := range tmpl.SigningInstructions {
+               for j, wc := range sigInst.WitnessComponents {
+                       switch sw := wc.(type) {
+                       case *mainchain.SignatureWitness:
+                               err := sw.Sign(tmpl, uint32(i), xprv)
+                               if err != nil {
+                                       return errors.WithDetailf(err, "adding signature(s) to signature witness component %d of input %d", j, i)
+                               }
+                       case *mainchain.RawTxSigWitness:
+                               err := sw.Sign(tmpl, uint32(i), xprv)
+                               if err != nil {
+                                       return errors.WithDetailf(err, "adding signature(s) to raw-signature witness component %d of input %d", j, i)
+                               }
+                       }
+               }
+       }
+       return materializeWitnesses(tmpl)
+}
+
+func materializeWitnesses(txTemplate *mainchain.Template) error {
+       msg := txTemplate.Transaction
+
+       if msg == nil {
+               return errors.Wrap(txbuilder.ErrMissingRawTx)
+       }
+
+       if len(txTemplate.SigningInstructions) > len(msg.Inputs) {
+               return errors.Wrap(txbuilder.ErrBadInstructionCount)
+       }
+
+       for i, sigInst := range txTemplate.SigningInstructions {
+               if msg.Inputs[sigInst.Position] == nil {
+                       return errors.WithDetailf(txbuilder.ErrBadTxInputIdx, "signing instruction %d references missing tx input %d", i, sigInst.Position)
+               }
+
+               var witness [][]byte
+               for j, wc := range sigInst.WitnessComponents {
+                       err := wc.Materialize(&witness)
+                       if err != nil {
+                               return errors.WithDetailf(err, "error in witness component %d of input %d", j, i)
+                       }
+               }
+               msg.SetInputArguments(sigInst.Position, witness)
+       }
+
+       return nil
+}
+
+//
+func getInput(entry map[bc.Hash]bc.Entry, outputID bc.Hash, controlProgram string) ([]byte, bool) {
+       output := entry[outputID].(*bc.Retirement)
+       mux := entry[*output.Source.Ref].(*bc.Mux)
+
+       for _, valueSource := range mux.GetSources() {
+               spend := entry[*valueSource.Ref].(*bc.Spend)
+               prevout := entry[*spend.SpentOutputId].(*bc.Output)
+
+               var ctrlProgram chainjson.HexBytes
+               ctrlProgram = prevout.ControlProgram.Code
+               tmp, _ := ctrlProgram.MarshalText()
+               if string(tmp) == controlProgram {
+                       return ctrlProgram, true
+               }
+       }
+       return nil, false
+}
+
+// UtxoToInputs convert an utxo to the txinput
+func utxoToInputs(xpubs []chainkd.XPub, u *account.UTXO) (*bytomtypes.TxInput, *mainchain.SigningInstruction, error) {
+       txInput := bytomtypes.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)
+       sigInst := &mainchain.SigningInstruction{}
+       quorum := len(xpubs)
+       if u.Address == "" {
+               sigInst.AddWitnessKeys(xpubs, quorum)
+               return txInput, sigInst, nil
+       }
+
+       address, err := common.DecodeBytomAddress(u.Address, &consensus.ActiveNetParams)
+       if err != nil {
+               return nil, nil, err
+       }
+
+       sigInst.AddRawWitnessKeysWithoutPath(xpubs, quorum)
+
+       switch address.(type) {
+       case *common.AddressWitnessPubKeyHash:
+               derivedPK := xpubs[0].PublicKey()
+               sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness([]byte(derivedPK)))
+
+       case *common.AddressWitnessScriptHash:
+               derivedXPubs := xpubs
+               derivedPKs := chainkd.XPubKeys(derivedXPubs)
+               script, err := vmutil.P2SPMultiSigProgram(derivedPKs, quorum)
+               if err != nil {
+                       return nil, nil, err
+               }
+               sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness(script))
+
+       default:
+               return nil, nil, errors.New("unsupport address type")
+       }
+
+       return txInput, sigInst, nil
+}
+
+func contractToInputs(u *account.UTXO, xpubs []chainkd.XPub, ClaimScript chainjson.HexBytes) (*bytomtypes.TxInput, *mainchain.SigningInstruction, error) {
+       txInput := bytomtypes.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)
+       sigInst := &mainchain.SigningInstruction{}
+
+       // raw_tx_signature
+       for _, xpub := range xpubs {
+               xpubsTmp := []chainkd.XPub{xpub}
+               sigInst.AddRawWitnessKeysWithoutPath(xpubsTmp, 1)
+       }
+
+       // data
+       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(ClaimScript)
+       if err != nil {
+               return nil, nil, err
+       }
+       sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness(peginContractPrograms))
+
+       return txInput, sigInst, nil
+}
similarity index 98%
rename from api/estimate.go
rename to claim/rpc/bytom/estimate.go
index 406f9dd..4b88d2d 100644 (file)
@@ -1,9 +1,9 @@
-package api
+package bytom
 
 import (
        "math"
 
-       "github.com/vapor/blockchain/txbuilder/mainchain"
+       "github.com/vapor/claim/bytom/mainchain"
        "github.com/vapor/consensus"
        "github.com/vapor/consensus/segwit"
        "github.com/vapor/errors"
diff --git a/claim/rpc/claim_tx.go b/claim/rpc/claim_tx.go
new file mode 100644 (file)
index 0000000..e89113c
--- /dev/null
@@ -0,0 +1,23 @@
+package rpc
+
+import (
+       "context"
+
+       chainjson "github.com/vapor/encoding/json"
+)
+
+type ClaimTxParam struct {
+       Password     string               `json:"password"`
+       RawTx        string               `json:"raw_transaction"`
+       BlockHeader  string               `json:"block_header"`
+       TxHashes     []chainjson.HexBytes `json:"tx_hashes"`
+       StatusHashes []chainjson.HexBytes `json:"status_hashes"`
+       Flags        []uint32             `json:"flags"`
+       MatchedTxIDs []chainjson.HexBytes `json:"matched_tx_ids"`
+       ClaimScript  chainjson.HexBytes   `json:"claim_script"`
+}
+
+type ClaimTx interface {
+       ClaimPeginTx(ctx context.Context) (interface{}, error)
+       ClaimContractPeginTx(ctx context.Context) (interface{}, error)
+}
diff --git a/claim/rpc/main_tx.go b/claim/rpc/main_tx.go
new file mode 100644 (file)
index 0000000..245ed4d
--- /dev/null
@@ -0,0 +1,20 @@
+package rpc
+
+import (
+       chainjson "github.com/vapor/encoding/json"
+)
+
+type MainTxSignParam struct {
+       Xprv        string             `json:"xprv"`
+       XPub        string             `json:"xpub"`
+       Txs         chainjson.HexBytes `json:"transaction"`
+       ClaimScript chainjson.HexBytes `json:"claim_script"`
+}
+
+type MainTxParam struct {
+       Utxo           []byte             `json:"utxo"`
+       Tx             string             `json:"raw_transaction"`
+       Pubs           []string           `json:"pubs"`
+       ControlProgram string             `json:"control_program"`
+       ClaimScript    chainjson.HexBytes `json:"claim_script"`
+}
diff --git a/claim/rpc/pegin.go b/claim/rpc/pegin.go
new file mode 100644 (file)
index 0000000..529001f
--- /dev/null
@@ -0,0 +1,6 @@
+package rpc
+
+type PeginRpc interface {
+       GetPeginAddress() (interface{}, error)
+       GetPeginContractAddress() (interface{}, error)
+}
diff --git a/claim/rpc/pegin_address.go b/claim/rpc/pegin_address.go
new file mode 100644 (file)
index 0000000..910696c
--- /dev/null
@@ -0,0 +1,188 @@
+package rpc
+
+import (
+       "encoding/hex"
+
+       "github.com/vapor/common"
+       "github.com/vapor/consensus"
+       "github.com/vapor/crypto"
+       chainjson "github.com/vapor/encoding/json"
+       "github.com/vapor/equity/pegin_contract"
+       "github.com/vapor/protocol/vm/vmutil"
+       "github.com/vapor/wallet"
+)
+
+type fundingResp struct {
+       MainchainAddress string             `json:"mainchain_address"`
+       ControlProgram   chainjson.HexBytes `json:"control_program,omitempty"`
+       ClaimScript      chainjson.HexBytes `json:"claim_script"`
+}
+
+type BytomPeginRpc struct {
+       ClaimArgs
+       Wallet *wallet.Wallet
+}
+
+type ClaimArgs struct {
+       AccountID    string `json:"account_id"`
+       AccountAlias string `json:"account_alias"`
+}
+
+func (b *BytomPeginRpc) GetPeginAddress() (interface{}, error) {
+
+       accountID := b.AccountID
+       if b.AccountAlias != "" {
+               account, err := b.Wallet.AccountMgr.FindByAlias(b.AccountAlias)
+               if err != nil {
+                       return nil, err
+               }
+
+               accountID = account.ID
+       }
+
+       mainchainAddress, claimScript, err := b.CreatePeginAddress(accountID, false)
+       if err != nil {
+               return nil, err
+       }
+
+       return &fundingResp{
+               MainchainAddress: mainchainAddress,
+               ClaimScript:      claimScript,
+       }, nil
+}
+
+func (b *BytomPeginRpc) GetPeginContractAddress() (interface{}, error) {
+       accountID := b.AccountID
+       if b.AccountAlias != "" {
+               account, err := b.Wallet.AccountMgr.FindByAlias(b.AccountAlias)
+               if err != nil {
+                       return nil, err
+               }
+
+               accountID = account.ID
+       }
+
+       mainchainAddress, controlProgram, claimScript, err := b.CreatePeginContractAddress(accountID, false)
+       if err != nil {
+               return nil, err
+       }
+
+       return &fundingResp{
+               MainchainAddress: mainchainAddress,
+               ControlProgram:   controlProgram,
+               ClaimScript:      claimScript,
+       }, nil
+}
+
+func (b *BytomPeginRpc) CreatePeginAddress(accountID string, change bool) (string, []byte, error) {
+       // 通过配置获取
+       claimCtrlProg, err := b.Wallet.AccountMgr.CreateAddress(b.AccountID, change)
+       if err != nil {
+               return "", nil, err
+       }
+       claimScript := claimCtrlProg.ControlProgram
+
+       federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
+
+       scriptHash := crypto.Sha256(federationRedeemScript)
+
+       address, err := common.NewPeginAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
+       if err != nil {
+               return "", nil, err
+       }
+
+       return address.EncodeAddress(), claimScript, nil
+
+}
+
+func (b *BytomPeginRpc) GetPeginControlPrograms(claimScript []byte) (string, []byte) {
+       federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
+       scriptHash := crypto.Sha256(federationRedeemScript)
+
+       address, err := common.NewPeginAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
+       if err != nil {
+               return "", nil
+       }
+
+       redeemContract := address.ScriptAddress()
+
+       program := []byte{}
+       program, err = vmutil.P2WSHProgram(redeemContract)
+       if err != nil {
+               return "", nil
+       }
+
+       return address.EncodeAddress(), program
+}
+
+func (b *BytomPeginRpc) CreatePeginContractPrograms(accountID string, change bool) (string, []byte, error) {
+       // 通过配置获取
+       claimCtrlProg, err := b.Wallet.AccountMgr.CreateAddress(accountID, change)
+       if err != nil {
+               return "", nil, err
+       }
+       claimScript := claimCtrlProg.ControlProgram
+
+       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(claimScript)
+       if err != nil {
+               return "", nil, err
+       }
+       return hex.EncodeToString(peginContractPrograms), claimScript, nil
+
+}
+
+func (b *BytomPeginRpc) CreatePeginContractAddress(accountID string, change bool) (string, []byte, []byte, error) {
+       // 通过配置获取
+       claimCtrlProg, err := b.Wallet.AccountMgr.CreateAddress(accountID, change)
+       if err != nil {
+               return "", nil, nil, err
+       }
+       claimScript := claimCtrlProg.ControlProgram
+
+       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(claimScript)
+       if err != nil {
+               return "", nil, nil, err
+       }
+
+       scriptHash := crypto.Sha256(peginContractPrograms)
+
+       address, err := common.NewPeginAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
+       if err != nil {
+               return "", nil, nil, err
+       }
+
+       redeemContract := address.ScriptAddress()
+
+       program := []byte{}
+       program, err = vmutil.P2WSHProgram(redeemContract)
+       if err != nil {
+               return "", nil, nil, err
+       }
+
+       return address.EncodeAddress(), program, claimScript, nil
+
+}
+
+func (b *BytomPeginRpc) GetPeginContractControlPrograms(claimScript []byte) (string, []byte) {
+
+       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(claimScript)
+       if err != nil {
+               return "", nil
+       }
+       scriptHash := crypto.Sha256(peginContractPrograms)
+
+       address, err := common.NewPeginAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
+       if err != nil {
+               return "", nil
+       }
+
+       redeemContract := address.ScriptAddress()
+
+       program := []byte{}
+       program, err = vmutil.P2WSHProgram(redeemContract)
+       if err != nil {
+               return "", nil
+       }
+
+       return address.EncodeAddress(), program
+}
index 984df23..7d1eb81 100644 (file)
@@ -28,7 +28,6 @@ It has these top-level messages:
        Issuance
        Spend
        Claim
-       Dpos
 */
 package bc
 
@@ -820,86 +819,6 @@ func (m *Claim) GetPeginwitness() [][]byte {
        return nil
 }
 
-type Dpos struct {
-       SpentOutputId      *Hash             `protobuf:"bytes,1,opt,name=spent_output_id,json=spentOutputId" json:"spent_output_id,omitempty"`
-       WitnessDestination *ValueDestination `protobuf:"bytes,2,opt,name=witness_destination,json=witnessDestination" json:"witness_destination,omitempty"`
-       WitnessArguments   [][]byte          `protobuf:"bytes,3,rep,name=witness_arguments,json=witnessArguments,proto3" json:"witness_arguments,omitempty"`
-       Ordinal            uint64            `protobuf:"varint,4,opt,name=ordinal" json:"ordinal,omitempty"`
-       Type               uint32            `protobuf:"varint,5,opt,name=type" json:"type,omitempty"`
-       From               string            `protobuf:"bytes,6,opt,name=from" json:"from,omitempty"`
-       To                 string            `protobuf:"bytes,7,opt,name=to" json:"to,omitempty"`
-       Stake              uint64            `protobuf:"varint,8,opt,name=stake" json:"stake,omitempty"`
-       Data               string            `protobuf:"bytes,9,opt,name=data" json:"data,omitempty"`
-}
-
-func (m *Dpos) Reset()                    { *m = Dpos{} }
-func (m *Dpos) String() string            { return proto.CompactTextString(m) }
-func (*Dpos) ProtoMessage()               {}
-func (*Dpos) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} }
-
-func (m *Dpos) GetSpentOutputId() *Hash {
-       if m != nil {
-               return m.SpentOutputId
-       }
-       return nil
-}
-
-func (m *Dpos) GetWitnessDestination() *ValueDestination {
-       if m != nil {
-               return m.WitnessDestination
-       }
-       return nil
-}
-
-func (m *Dpos) GetWitnessArguments() [][]byte {
-       if m != nil {
-               return m.WitnessArguments
-       }
-       return nil
-}
-
-func (m *Dpos) GetOrdinal() uint64 {
-       if m != nil {
-               return m.Ordinal
-       }
-       return 0
-}
-
-func (m *Dpos) GetType() uint32 {
-       if m != nil {
-               return m.Type
-       }
-       return 0
-}
-
-func (m *Dpos) GetFrom() string {
-       if m != nil {
-               return m.From
-       }
-       return ""
-}
-
-func (m *Dpos) GetTo() string {
-       if m != nil {
-               return m.To
-       }
-       return ""
-}
-
-func (m *Dpos) GetStake() uint64 {
-       if m != nil {
-               return m.Stake
-       }
-       return 0
-}
-
-func (m *Dpos) GetData() string {
-       if m != nil {
-               return m.Data
-       }
-       return ""
-}
-
 func init() {
        proto.RegisterType((*Hash)(nil), "bc.Hash")
        proto.RegisterType((*Program)(nil), "bc.Program")
@@ -921,78 +840,74 @@ func init() {
        proto.RegisterType((*Issuance)(nil), "bc.Issuance")
        proto.RegisterType((*Spend)(nil), "bc.Spend")
        proto.RegisterType((*Claim)(nil), "bc.Claim")
-       proto.RegisterType((*Dpos)(nil), "bc.Dpos")
 }
 
 func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-       // 1070 bytes of a gzipped FileDescriptorProto
-       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x57, 0xcd, 0x6e, 0x1b, 0xb7,
-       0x13, 0x87, 0x56, 0xab, 0xaf, 0x91, 0x6c, 0xd9, 0xb4, 0x93, 0xff, 0x22, 0xc8, 0x1f, 0x35, 0x16,
-       0x48, 0x9c, 0xa2, 0x80, 0xe1, 0x8f, 0xb4, 0xbd, 0xf4, 0x50, 0x27, 0x6e, 0x1a, 0x1d, 0x8c, 0x18,
-       0xb4, 0xe1, 0x5b, 0xb1, 0xa0, 0xb4, 0x94, 0x4c, 0x44, 0x5a, 0x6e, 0x49, 0xae, 0x6a, 0xfb, 0x96,
-       0xb7, 0xe9, 0x1b, 0xf4, 0x11, 0x72, 0xea, 0x93, 0xf4, 0x15, 0x7a, 0x28, 0x38, 0xcb, 0x95, 0x56,
-       0xb2, 0xf2, 0x85, 0xa2, 0x28, 0x02, 0xf4, 0xc6, 0x19, 0x0e, 0x7f, 0x33, 0xf3, 0xe3, 0xec, 0x0c,
-       0x17, 0x9a, 0xfd, 0xc1, 0x5e, 0xaa, 0xa4, 0x91, 0xc4, 0xeb, 0x0f, 0xc2, 0x17, 0xe0, 0xbf, 0x64,
-       0xfa, 0x8a, 0xac, 0x83, 0x37, 0xdd, 0x0f, 0x2a, 0x3b, 0x95, 0x27, 0x75, 0xea, 0x4d, 0xf7, 0x51,
-       0x3e, 0x08, 0x3c, 0x27, 0x1f, 0xa0, 0x7c, 0x18, 0x54, 0x9d, 0x7c, 0x88, 0xf2, 0x51, 0xe0, 0x3b,
-       0xf9, 0x28, 0xfc, 0x0e, 0x1a, 0x67, 0x4a, 0x8e, 0x14, 0x9b, 0x90, 0xff, 0x03, 0x4c, 0x27, 0xd1,
-       0x94, 0x2b, 0x2d, 0x64, 0x82, 0x90, 0x3e, 0x6d, 0x4d, 0x27, 0x97, 0xb9, 0x82, 0x10, 0xf0, 0x07,
-       0x32, 0xe6, 0x88, 0xdd, 0xa1, 0xb8, 0x0e, 0x7b, 0xd0, 0x38, 0xd6, 0x9a, 0x9b, 0xde, 0xc9, 0xdf,
-       0x0e, 0xe4, 0x14, 0xda, 0x08, 0x75, 0x3c, 0x91, 0x59, 0x62, 0xc8, 0x63, 0x68, 0x32, 0x2b, 0x46,
-       0x22, 0x46, 0xd0, 0xf6, 0x61, 0x7b, 0xaf, 0x3f, 0xd8, 0x73, 0xde, 0x68, 0x03, 0x37, 0x7b, 0x31,
-       0xb9, 0x0f, 0x75, 0x86, 0x27, 0xd0, 0x95, 0x4f, 0x9d, 0x14, 0x8e, 0xa0, 0x8b, 0xb6, 0x27, 0x7c,
-       0x28, 0x12, 0x61, 0x6c, 0x02, 0xdf, 0xc0, 0x86, 0xd0, 0x3a, 0x63, 0xc9, 0x80, 0x47, 0x69, 0x9e,
-       0x73, 0x19, 0xda, 0xd1, 0x40, 0xbb, 0x85, 0x51, 0xc1, 0xcb, 0x43, 0xf0, 0x63, 0x66, 0x18, 0x3a,
-       0x68, 0x1f, 0x36, 0xad, 0xad, 0xa5, 0x9e, 0xa2, 0x36, 0x1c, 0x43, 0xfb, 0x92, 0x8d, 0x33, 0x7e,
-       0x2e, 0x33, 0x35, 0xe0, 0xe4, 0x01, 0x54, 0x15, 0x1f, 0x3a, 0xdc, 0xb9, 0xad, 0x55, 0x92, 0x47,
-       0x50, 0x9b, 0x5a, 0x53, 0x87, 0xd4, 0x9d, 0x25, 0x94, 0xe7, 0x4c, 0xf3, 0x5d, 0xf2, 0x00, 0x9a,
-       0xa9, 0xd4, 0x18, 0x33, 0xf2, 0xe5, 0xd3, 0x99, 0x1c, 0xfe, 0x0c, 0x1b, 0xe8, 0xed, 0x84, 0x6b,
-       0x23, 0x12, 0x86, 0x79, 0xfd, 0xc3, 0x2e, 0x7f, 0x82, 0xda, 0x99, 0x92, 0x72, 0x68, 0x0b, 0x40,
-       0x8b, 0x51, 0x5e, 0x19, 0x1d, 0x8a, 0x6b, 0xf2, 0x18, 0xd6, 0x07, 0x32, 0x31, 0x4a, 0x8e, 0x1d,
-       0x5b, 0xae, 0x3c, 0x96, 0xb4, 0x24, 0x80, 0x06, 0x8b, 0x63, 0xc5, 0xb5, 0x46, 0xfc, 0x0e, 0x2d,
-       0xc4, 0xf0, 0x4d, 0x15, 0x36, 0x9e, 0xdd, 0x18, 0x39, 0x79, 0x36, 0x96, 0x83, 0xd7, 0x2f, 0x39,
-       0x8b, 0xb9, 0xb2, 0xe6, 0x8b, 0x75, 0x58, 0x88, 0xf6, 0xbe, 0xaf, 0xb8, 0x18, 0x5d, 0xcd, 0xee,
-       0x3b, 0x97, 0xc8, 0x53, 0xd8, 0x4c, 0x15, 0x9f, 0x0a, 0x99, 0xe9, 0xa8, 0x6f, 0x91, 0x6c, 0xe1,
-       0x54, 0x97, 0x28, 0xe9, 0x16, 0x26, 0xe8, 0xab, 0x17, 0x93, 0x87, 0xd0, 0x32, 0x62, 0xc2, 0xb5,
-       0x61, 0x93, 0x14, 0x6b, 0xd1, 0xa7, 0x73, 0x05, 0xf9, 0x1a, 0x36, 0x8d, 0x62, 0x89, 0x66, 0x03,
-       0x4b, 0x84, 0x8e, 0x94, 0x94, 0x26, 0xa8, 0x2d, 0x61, 0x6e, 0x94, 0x4d, 0xa8, 0x94, 0x86, 0x7c,
-       0x0f, 0xff, 0x2b, 0xe9, 0x22, 0x6d, 0x98, 0xc9, 0x74, 0x74, 0xc5, 0xf4, 0x55, 0x50, 0x5f, 0x3a,
-       0x7c, 0xaf, 0x64, 0x78, 0x8e, 0x76, 0xf8, 0x51, 0x6f, 0x43, 0x2d, 0x91, 0xc9, 0x80, 0x07, 0x0d,
-       0x0c, 0x29, 0x17, 0x2c, 0xff, 0x7d, 0x61, 0x74, 0xd0, 0x44, 0x25, 0xae, 0xc9, 0x09, 0x90, 0xbb,
-       0xbe, 0x82, 0x16, 0xba, 0xb9, 0x67, 0xdd, 0x5c, 0x2c, 0x3b, 0xa0, 0x9b, 0x77, 0x7c, 0x86, 0x7f,
-       0x7a, 0xd0, 0xfe, 0x8f, 0xfe, 0x7f, 0x8d, 0xfe, 0xb7, 0x15, 0x68, 0x5e, 0x5c, 0x7f, 0x90, 0xfb,
-       0x5d, 0xe8, 0x6a, 0xae, 0x04, 0x1b, 0x8b, 0x5b, 0x1e, 0x47, 0x5a, 0xdc, 0x72, 0x77, 0x09, 0xeb,
-       0x73, 0xf5, 0xb9, 0xb8, 0xe5, 0xb3, 0x86, 0x55, 0x5d, 0xd5, 0xb0, 0x6c, 0x9b, 0xb7, 0x1c, 0x47,
-       0x8a, 0x25, 0x23, 0x5e, 0x66, 0x9d, 0x5a, 0x05, 0xd9, 0x05, 0x50, 0x5c, 0x67, 0x63, 0xdb, 0x79,
-       0x75, 0x50, 0xdb, 0xa9, 0x2e, 0x40, 0xb4, 0xf2, 0xbd, 0x5e, 0xac, 0xf3, 0x76, 0x10, 0x73, 0x24,
-       0xb5, 0x49, 0x71, 0x1d, 0x1e, 0xc0, 0xfa, 0xc5, 0xf5, 0x25, 0x57, 0x62, 0x78, 0x43, 0xd1, 0x90,
-       0x7c, 0x01, 0x6d, 0x77, 0x03, 0x43, 0x26, 0xc6, 0x98, 0x52, 0x93, 0x42, 0xae, 0x7a, 0xc1, 0xc4,
-       0x38, 0x1c, 0xc2, 0xe6, 0x1d, 0x92, 0xde, 0x43, 0xc2, 0xb7, 0xb0, 0x36, 0x45, 0xfc, 0x82, 0x6c,
-       0x0f, 0x23, 0x24, 0x48, 0xf6, 0x82, 0x6b, 0xda, 0xc9, 0x0d, 0x1d, 0xc9, 0xbf, 0x57, 0xa0, 0x7a,
-       0x9a, 0x5d, 0x93, 0x2f, 0xa1, 0xa1, 0xb1, 0x55, 0xeb, 0xa0, 0x82, 0x47, 0xb1, 0x27, 0x96, 0x5a,
-       0x38, 0x2d, 0xf6, 0xc9, 0x23, 0x68, 0xa4, 0xa5, 0xae, 0xb6, 0x34, 0x27, 0x8a, 0x3d, 0xf2, 0x23,
-       0x6c, 0xff, 0x22, 0x4c, 0xc2, 0xb5, 0x8e, 0xe2, 0x79, 0x5b, 0xb6, 0x8d, 0xce, 0xc2, 0x6f, 0xcf,
-       0xe0, 0x4b, 0x3d, 0x9b, 0x6e, 0xb9, 0x13, 0x25, 0x9d, 0x26, 0x5f, 0xc1, 0x66, 0x01, 0xc4, 0xd4,
-       0x28, 0x9b, 0xf0, 0xc4, 0xe8, 0xc0, 0xdf, 0xa9, 0x3e, 0xe9, 0xd0, 0x0d, 0xb7, 0x71, 0x5c, 0xe8,
-       0x43, 0x09, 0xcd, 0xe7, 0x52, 0x24, 0x7d, 0xa6, 0x39, 0xf9, 0x01, 0xb6, 0x56, 0x44, 0xe0, 0x26,
-       0xc2, 0xea, 0x00, 0xc8, 0xdd, 0x00, 0xec, 0xe7, 0xc8, 0x54, 0x5f, 0x18, 0xc5, 0xd4, 0x8d, 0xeb,
-       0xe3, 0x73, 0x45, 0xf8, 0xa6, 0x02, 0xf5, 0x57, 0x99, 0x49, 0x33, 0x43, 0x76, 0xa1, 0x9e, 0x73,
-       0xe4, 0x5c, 0xdc, 0xa1, 0xd0, 0x6d, 0x93, 0xa7, 0xd0, 0x75, 0x83, 0x20, 0x7a, 0x0f, 0x93, 0x2b,
-       0x86, 0x85, 0x54, 0xb1, 0x48, 0xd8, 0xd8, 0x0d, 0xa3, 0x42, 0x0c, 0x5f, 0x01, 0x50, 0x6e, 0x84,
-       0xe2, 0x96, 0x83, 0x8f, 0x0f, 0xa3, 0x04, 0xe8, 0x2d, 0x02, 0xfe, 0xe6, 0x41, 0xb3, 0xe7, 0xe6,
-       0xbd, 0x2d, 0x7d, 0xfc, 0xd4, 0xf3, 0x66, 0xb1, 0x3c, 0x4f, 0x5b, 0xb8, 0x87, 0x0d, 0xe2, 0x23,
-       0xa7, 0xea, 0x3b, 0xae, 0xa5, 0xfa, 0x89, 0xd7, 0x72, 0x0a, 0xc1, 0xac, 0x2c, 0xf0, 0x49, 0x14,
-       0xcf, 0xde, 0x34, 0xf8, 0xf9, 0xb6, 0x0f, 0xb7, 0x66, 0x01, 0xcc, 0x9f, 0x3b, 0xf4, 0x7e, 0x51,
-       0x32, 0x4b, 0xcf, 0xa0, 0x95, 0x55, 0x56, 0x5b, 0x5d, 0x65, 0x65, 0xe6, 0xea, 0x8b, 0xcc, 0xbd,
-       0xad, 0x40, 0xed, 0x3c, 0xe5, 0x49, 0x4c, 0xf6, 0xa1, 0xab, 0x53, 0x9e, 0x98, 0x48, 0x62, 0x75,
-       0xcc, 0x5f, 0x6c, 0x73, 0xee, 0xd6, 0xd0, 0x20, 0xaf, 0x9e, 0x5e, 0xfc, 0x2e, 0x62, 0xbc, 0x4f,
-       0x24, 0x66, 0x65, 0x26, 0xd5, 0x0f, 0x67, 0xe2, 0x2f, 0x66, 0xf2, 0x47, 0x05, 0x6a, 0xcf, 0xc7,
-       0x4c, 0x4c, 0x3e, 0xf7, 0x4c, 0x48, 0x08, 0x9d, 0x33, 0x3e, 0x12, 0x89, 0x3b, 0xe2, 0x6e, 0x75,
-       0x41, 0x17, 0xfe, 0xea, 0x81, 0x7f, 0x92, 0x4a, 0xfd, 0xd9, 0x27, 0x4b, 0xc0, 0x37, 0x37, 0x29,
-       0xc7, 0x17, 0xc1, 0x1a, 0xc5, 0xb5, 0xd5, 0x0d, 0x95, 0x9c, 0x60, 0xad, 0xb6, 0x28, 0xae, 0xed,
-       0x8f, 0x86, 0x91, 0x38, 0xca, 0x5b, 0xd4, 0x33, 0xd2, 0x4e, 0x77, 0x6d, 0xd8, 0x6b, 0xee, 0x06,
-       0x79, 0x2e, 0xd8, 0x93, 0x38, 0x33, 0x5b, 0xf9, 0x49, 0xbb, 0xee, 0xd7, 0xf1, 0x77, 0xeb, 0xe8,
-       0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x94, 0x81, 0x10, 0xfb, 0x7a, 0x0d, 0x00, 0x00,
+       // 1010 bytes of a gzipped FileDescriptorProto
+       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x57, 0xcd, 0x6e, 0x1b, 0x37,
+       0x10, 0x86, 0xa4, 0x95, 0xb4, 0x1e, 0x29, 0x96, 0x4d, 0x3b, 0xe9, 0x22, 0x48, 0x51, 0x63, 0x81,
+       0xc4, 0x29, 0x0a, 0x18, 0xfe, 0x49, 0xdb, 0x4b, 0x0f, 0x75, 0xe2, 0xa6, 0xd1, 0xc1, 0x88, 0x41,
+       0x1b, 0xbe, 0x15, 0x0b, 0x6a, 0x97, 0x92, 0x89, 0xae, 0x96, 0x2a, 0xc9, 0x55, 0x6d, 0xdf, 0xf2,
+       0x54, 0x7d, 0x84, 0x9c, 0xfa, 0x24, 0x7d, 0x85, 0x1e, 0x0a, 0xce, 0x72, 0xa5, 0x95, 0xac, 0xfc,
+       0xa1, 0x28, 0x8a, 0x02, 0xbd, 0xed, 0x0c, 0x87, 0xdf, 0xcc, 0x7c, 0x1c, 0xce, 0x70, 0xc1, 0x1f,
+       0xc4, 0x7b, 0x13, 0x25, 0x8d, 0x24, 0xf5, 0x41, 0x1c, 0xbe, 0x04, 0xef, 0x15, 0xd3, 0x57, 0x64,
+       0x1d, 0xea, 0xd3, 0xfd, 0xa0, 0xb6, 0x53, 0x7b, 0xda, 0xa2, 0xf5, 0xe9, 0x3e, 0xca, 0x07, 0x41,
+       0xdd, 0xc9, 0x07, 0x28, 0x1f, 0x06, 0x0d, 0x27, 0x1f, 0xa2, 0x7c, 0x14, 0x78, 0x4e, 0x3e, 0x0a,
+       0xbf, 0x83, 0xf6, 0x99, 0x92, 0x23, 0xc5, 0xc6, 0xe4, 0x73, 0x80, 0xe9, 0x38, 0x9a, 0x72, 0xa5,
+       0x85, 0xcc, 0x10, 0xd2, 0xa3, 0x6b, 0xd3, 0xf1, 0x65, 0xa1, 0x20, 0x04, 0xbc, 0x58, 0x26, 0x1c,
+       0xb1, 0xbb, 0x14, 0xbf, 0xc3, 0x3e, 0xb4, 0x8f, 0xb5, 0xe6, 0xa6, 0x7f, 0xf2, 0xb7, 0x03, 0x39,
+       0x85, 0x0e, 0x42, 0x1d, 0x8f, 0x65, 0x9e, 0x19, 0xf2, 0x04, 0x7c, 0x66, 0xc5, 0x48, 0x24, 0x08,
+       0xda, 0x39, 0xec, 0xec, 0x0d, 0xe2, 0x3d, 0xe7, 0x8d, 0xb6, 0x71, 0xb1, 0x9f, 0x90, 0x07, 0xd0,
+       0x62, 0xb8, 0x03, 0x5d, 0x79, 0xd4, 0x49, 0xe1, 0x08, 0x7a, 0x68, 0x7b, 0xc2, 0x87, 0x22, 0x13,
+       0xc6, 0x26, 0xf0, 0x0d, 0x6c, 0x08, 0xad, 0x73, 0x96, 0xc5, 0x3c, 0x9a, 0x14, 0x39, 0x57, 0xa1,
+       0x1d, 0x0d, 0xb4, 0x57, 0x1a, 0x95, 0xbc, 0x3c, 0x02, 0x2f, 0x61, 0x86, 0xa1, 0x83, 0xce, 0xa1,
+       0x6f, 0x6d, 0x2d, 0xf5, 0x14, 0xb5, 0x61, 0x0a, 0x9d, 0x4b, 0x96, 0xe6, 0xfc, 0x5c, 0xe6, 0x2a,
+       0xe6, 0xe4, 0x21, 0x34, 0x14, 0x1f, 0x3a, 0xdc, 0xb9, 0xad, 0x55, 0x92, 0xc7, 0xd0, 0x9c, 0x5a,
+       0x53, 0x87, 0xd4, 0x9b, 0x25, 0x54, 0xe4, 0x4c, 0x8b, 0x55, 0xf2, 0x10, 0xfc, 0x89, 0xd4, 0x18,
+       0x33, 0xf2, 0xe5, 0xd1, 0x99, 0x1c, 0xfe, 0x02, 0x1b, 0xe8, 0xed, 0x84, 0x6b, 0x23, 0x32, 0x86,
+       0x79, 0xfd, 0xc3, 0x2e, 0x7f, 0x82, 0xe6, 0x99, 0x92, 0x72, 0x68, 0x0b, 0x40, 0x8b, 0x51, 0x51,
+       0x19, 0x5d, 0x8a, 0xdf, 0xe4, 0x09, 0xac, 0xc7, 0x32, 0x33, 0x4a, 0xa6, 0x8e, 0x2d, 0x57, 0x1e,
+       0x4b, 0x5a, 0x12, 0x40, 0x9b, 0x25, 0x89, 0xe2, 0x5a, 0x23, 0x7e, 0x97, 0x96, 0x62, 0xf8, 0xa6,
+       0x01, 0x1b, 0xcf, 0x6f, 0x8c, 0x1c, 0x3f, 0x4f, 0x65, 0xfc, 0xf3, 0x2b, 0xce, 0x12, 0xae, 0xac,
+       0xf9, 0x62, 0x1d, 0x96, 0xa2, 0x3d, 0xef, 0x2b, 0x2e, 0x46, 0x57, 0xb3, 0xf3, 0x2e, 0x24, 0xf2,
+       0x0c, 0x36, 0x27, 0x8a, 0x4f, 0x85, 0xcc, 0x75, 0x34, 0xb0, 0x48, 0xb6, 0x70, 0x1a, 0x4b, 0x94,
+       0xf4, 0x4a, 0x13, 0xf4, 0xd5, 0x4f, 0xc8, 0x23, 0x58, 0x33, 0x62, 0xcc, 0xb5, 0x61, 0xe3, 0x09,
+       0xd6, 0xa2, 0x47, 0xe7, 0x0a, 0xf2, 0x35, 0x6c, 0x1a, 0xc5, 0x32, 0xcd, 0x62, 0x4b, 0x84, 0x8e,
+       0x94, 0x94, 0x26, 0x68, 0x2e, 0x61, 0x6e, 0x54, 0x4d, 0xa8, 0x94, 0x86, 0x7c, 0x0f, 0x9f, 0x55,
+       0x74, 0x91, 0x36, 0xcc, 0xe4, 0x3a, 0xba, 0x62, 0xfa, 0x2a, 0x68, 0x2d, 0x6d, 0xbe, 0x5f, 0x31,
+       0x3c, 0x47, 0x3b, 0xbc, 0xd4, 0xdb, 0xd0, 0xcc, 0x64, 0x16, 0xf3, 0xa0, 0x8d, 0x21, 0x15, 0x82,
+       0xe5, 0x7f, 0x20, 0x8c, 0x0e, 0x7c, 0x54, 0xe2, 0x37, 0x39, 0x01, 0x72, 0xd7, 0x57, 0xb0, 0x86,
+       0x6e, 0xee, 0x5b, 0x37, 0x17, 0xcb, 0x0e, 0xe8, 0xe6, 0x1d, 0x9f, 0xe1, 0x9f, 0x75, 0xe8, 0xfc,
+       0x4f, 0xff, 0xbf, 0x46, 0xff, 0xdb, 0x1a, 0xf8, 0x17, 0xd7, 0x1f, 0xe4, 0x7e, 0x17, 0x7a, 0x9a,
+       0x2b, 0xc1, 0x52, 0x71, 0xcb, 0x93, 0x48, 0x8b, 0x5b, 0xee, 0x0e, 0x61, 0x7d, 0xae, 0x3e, 0x17,
+       0xb7, 0x7c, 0xd6, 0xb0, 0x1a, 0xab, 0x1a, 0x96, 0x6d, 0xf3, 0x96, 0xe3, 0x48, 0xb1, 0x6c, 0xc4,
+       0xab, 0xac, 0x53, 0xab, 0x20, 0xbb, 0x00, 0x8a, 0xeb, 0x3c, 0xb5, 0x9d, 0x57, 0x07, 0xcd, 0x9d,
+       0xc6, 0x02, 0xc4, 0x5a, 0xb1, 0xd6, 0x4f, 0x74, 0xd1, 0x0e, 0x12, 0x8e, 0xa4, 0xfa, 0x14, 0xbf,
+       0xc3, 0x03, 0x58, 0xbf, 0xb8, 0xbe, 0xe4, 0x4a, 0x0c, 0x6f, 0x28, 0x1a, 0x92, 0x2f, 0xa0, 0xe3,
+       0x4e, 0x60, 0xc8, 0x44, 0x8a, 0x29, 0xf9, 0x14, 0x0a, 0xd5, 0x4b, 0x26, 0xd2, 0x70, 0x08, 0x9b,
+       0x77, 0x48, 0x7a, 0x0f, 0x09, 0xdf, 0xc2, 0xbd, 0x29, 0xe2, 0x97, 0x64, 0xd7, 0x31, 0x42, 0x82,
+       0x64, 0x2f, 0xb8, 0xa6, 0xdd, 0xc2, 0xd0, 0x91, 0xfc, 0x7b, 0x0d, 0x1a, 0xa7, 0xf9, 0x35, 0xf9,
+       0x12, 0xda, 0x1a, 0x5b, 0xb5, 0x0e, 0x6a, 0xb8, 0x15, 0x7b, 0x62, 0xa5, 0x85, 0xd3, 0x72, 0x9d,
+       0x3c, 0x86, 0xf6, 0xa4, 0xd2, 0xd5, 0x96, 0xe6, 0x44, 0xb9, 0x46, 0x7e, 0x84, 0xed, 0x5f, 0x85,
+       0xc9, 0xb8, 0xd6, 0x51, 0x32, 0x6f, 0xcb, 0xb6, 0xd1, 0x59, 0xf8, 0xed, 0x19, 0x7c, 0xa5, 0x67,
+       0xd3, 0x2d, 0xb7, 0xa3, 0xa2, 0xd3, 0xe4, 0x2b, 0xd8, 0x2c, 0x81, 0x98, 0x1a, 0xe5, 0x63, 0x9e,
+       0x19, 0x1d, 0x78, 0x3b, 0x8d, 0xa7, 0x5d, 0xba, 0xe1, 0x16, 0x8e, 0x4b, 0x7d, 0x28, 0xc1, 0x7f,
+       0x21, 0x45, 0x36, 0x60, 0x9a, 0x93, 0x1f, 0x60, 0x6b, 0x45, 0x04, 0x6e, 0x22, 0xac, 0x0e, 0x80,
+       0xdc, 0x0d, 0xc0, 0x5e, 0x47, 0xa6, 0x06, 0xc2, 0x28, 0xa6, 0x6e, 0x5c, 0x1f, 0x9f, 0x2b, 0xc2,
+       0x37, 0x35, 0x68, 0xbd, 0xce, 0xcd, 0x24, 0x37, 0x64, 0x17, 0x5a, 0x05, 0x47, 0xce, 0xc5, 0x1d,
+       0x0a, 0xdd, 0x32, 0x79, 0x06, 0x3d, 0x37, 0x08, 0xa2, 0xf7, 0x30, 0xb9, 0x62, 0x58, 0x48, 0x95,
+       0x88, 0x8c, 0xa5, 0x6e, 0x18, 0x95, 0x62, 0xf8, 0x1a, 0x80, 0x72, 0x23, 0x14, 0xb7, 0x1c, 0x7c,
+       0x7c, 0x18, 0x15, 0xc0, 0xfa, 0x22, 0xe0, 0x6f, 0x75, 0xf0, 0xfb, 0x6e, 0xde, 0xdb, 0xd2, 0xc7,
+       0xab, 0x5e, 0x34, 0x8b, 0xe5, 0x79, 0xba, 0x86, 0x6b, 0xd8, 0x20, 0x3e, 0x72, 0xaa, 0xbe, 0xe3,
+       0x58, 0x1a, 0x9f, 0x78, 0x2c, 0xa7, 0x10, 0xcc, 0xca, 0x02, 0x9f, 0x44, 0xc9, 0xec, 0x4d, 0x83,
+       0xd7, 0xb7, 0x73, 0xb8, 0x35, 0x0b, 0x60, 0xfe, 0xdc, 0xa1, 0x0f, 0xca, 0x92, 0x59, 0x7a, 0x06,
+       0xad, 0xac, 0xb2, 0xe6, 0xea, 0x2a, 0xab, 0x32, 0xd7, 0x5a, 0x64, 0xee, 0x6d, 0x0d, 0x9a, 0xe7,
+       0x13, 0x9e, 0x25, 0x64, 0x1f, 0x7a, 0x7a, 0xc2, 0x33, 0x13, 0x49, 0xac, 0x8e, 0xf9, 0x8b, 0x6d,
+       0xce, 0xdd, 0x3d, 0x34, 0x28, 0xaa, 0xa7, 0x9f, 0xbc, 0x8b, 0x98, 0xfa, 0x27, 0x12, 0xb3, 0x32,
+       0x93, 0xc6, 0x87, 0x33, 0xf1, 0x16, 0x33, 0xf9, 0xa3, 0x06, 0xcd, 0x17, 0x29, 0x13, 0xe3, 0xff,
+       0x7a, 0x26, 0x24, 0x84, 0xee, 0x19, 0x1f, 0x89, 0xcc, 0x6d, 0x71, 0xa7, 0xba, 0xa0, 0x1b, 0xb4,
+       0xf0, 0x1f, 0xe2, 0xe8, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4f, 0x7a, 0xad, 0x71, 0x4f, 0x0c,
+       0x00, 0x00,
 }
index 0ee23f8..5a38c4c 100644 (file)
@@ -143,14 +143,3 @@ message Claim {
   repeated bytes   Peginwitness        = 5;
 }
 
-message Dpos {
-  Hash             spent_output_id     = 1;
-  ValueDestination witness_destination = 2;
-  repeated bytes   witness_arguments   = 3;
-  uint64           ordinal             = 4;
-  uint32           type                = 5;
-  string           from                = 6;
-  string           to                  = 7;
-  uint64           stake               = 8;
-  string           data                = 9;
-}
diff --git a/protocol/bc/dpos.go b/protocol/bc/dpos.go
deleted file mode 100644 (file)
index 3910637..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-package bc
-
-import (
-       "io"
-)
-
-func (Dpos) typ() string { return "dpos1" }
-func (d *Dpos) writeForHash(w io.Writer) {
-       mustWriteForHash(w, d.SpentOutputId)
-       mustWriteForHash(w, d.Type)
-       mustWriteForHash(w, d.From)
-       mustWriteForHash(w, d.To)
-       mustWriteForHash(w, d.Stake)
-}
-
-// SetDestination will link the spend to the output
-func (d *Dpos) SetDestination(id *Hash, val *AssetAmount, pos uint64) {
-       d.WitnessDestination = &ValueDestination{
-               Ref:      id,
-               Value:    val,
-               Position: pos,
-       }
-}
-
-// NewDpos creates a new Spend.
-func NewDpos(spentOutputID *Hash, ordinal uint64, t uint32, stake uint64, from, to, data string) *Dpos {
-       return &Dpos{
-               SpentOutputId: spentOutputID,
-               Ordinal:       ordinal,
-               Type:          t,
-               From:          from,
-               To:            to,
-               Stake:         stake,
-               Data:          data,
-       }
-}
diff --git a/protocol/bc/types/dpos.go b/protocol/bc/types/dpos.go
deleted file mode 100644 (file)
index 73a600d..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-package types
-
-import (
-       "github.com/vapor/protocol/bc"
-)
-
-type DposTx struct {
-       SpendCommitmentSuffix []byte
-       Type                  TxType
-       From                  string
-       To                    string
-       Amount                uint64
-       Stake                 uint64
-       Arguments             [][]byte
-       Info                  string
-       SpendCommitment
-}
-
-func NewDpos(arguments [][]byte, from, to string, sourceID bc.Hash, assetID bc.AssetID, stake, amount, sourcePos uint64, controlProgram []byte, t TxType, height uint64) *TxInput {
-       var vote string
-
-       sc := SpendCommitment{
-               AssetAmount: bc.AssetAmount{
-                       AssetId: &assetID,
-                       Amount:  amount,
-               },
-               SourceID:       sourceID,
-               SourcePosition: sourcePos,
-               VMVersion:      1,
-               ControlProgram: controlProgram,
-       }
-
-       return &TxInput{
-               AssetVersion: 1,
-               TypedInput: &DposTx{
-                       SpendCommitment: sc,
-                       Type:            t,
-                       Amount:          amount,
-                       Arguments:       arguments,
-                       Info:            vote,
-                       Stake:           stake,
-                       From:            from,
-                       To:              to,
-               },
-       }
-}
-
-// InputType is the interface function for return the input type.
-func (si *DposTx) InputType() uint8 { return DposInputType }
index 9ad4037..99be153 100644 (file)
@@ -37,15 +37,6 @@ func MapTx(oldTx *TxData) *bc.Tx {
                        ord = 0
                case *bc.Claim:
                        ord = 0
-               case *bc.Dpos:
-                       ord = e.Ordinal
-                       //spentOutputIDs[*e.SpentOutputId] = true
-                       /*
-                               if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
-                                       tx.GasInputIDs = append(tx.GasInputIDs, id)
-                               }
-                       */
-                       continue
                default:
                        continue
                }
@@ -72,7 +63,6 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
 
        var (
                spends    []*bc.Spend
-               dposs     []*bc.Dpos
                issuances []*bc.Issuance
                coinbase  *bc.Coinbase
                claim     *bc.Claim
@@ -151,26 +141,6 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
                                Ref:   &claimID,
                                Value: &inp.AssetAmount,
                        }
-               case *DposTx:
-                       // create entry for prevout
-                       prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
-                       src := &bc.ValueSource{
-                               Ref:      &inp.SourceID,
-                               Value:    &inp.AssetAmount,
-                               Position: inp.SourcePosition,
-                       }
-                       prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
-                       prevoutID := addEntry(prevout)
-                       // create entry for dpos
-                       dpos := bc.NewDpos(&prevoutID, uint64(i), uint32(inp.Type), inp.Stake, inp.From, inp.To, inp.Info)
-                       dpos.WitnessArguments = inp.Arguments
-                       dposID := addEntry(dpos)
-                       // setup mux
-                       muxSources[i] = &bc.ValueSource{
-                               Ref:   &dposID,
-                               Value: &inp.AssetAmount,
-                       }
-                       dposs = append(dposs, dpos)
                }
        }
 
@@ -186,12 +156,6 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
                issuance.SetDestination(&muxID, issuance.Value, issuance.Ordinal)
        }
 
-       // connect the inputs to the mux
-       for _, dpos := range dposs {
-               spentOutput := entryMap[*dpos.SpentOutputId].(*bc.Output)
-               dpos.SetDestination(&muxID, spentOutput.Source.Value, dpos.Ordinal)
-       }
-
        if coinbase != nil {
                coinbase.SetDestination(&muxID, mux.Sources[0].Value, 0)
        }
index 58d01d6..8eaafaf 100644 (file)
@@ -15,7 +15,6 @@ const (
        SpendInputType
        CoinbaseInputType
        ClainPeginInputType
-       DposInputType
 )
 
 type (
@@ -49,8 +48,6 @@ func (t *TxInput) AssetAmount() bc.AssetAmount {
                return inp.AssetAmount
        case *ClaimInput:
                return inp.AssetAmount
-       case *DposTx:
-               return inp.AssetAmount
        }
        return bc.AssetAmount{}
 }
@@ -64,8 +61,6 @@ func (t *TxInput) AssetID() bc.AssetID {
                return *inp.AssetId
        case *ClaimInput:
                return *inp.AssetId
-       case *DposTx:
-               return *inp.AssetId
 
        }
        return bc.AssetID{}
@@ -80,8 +75,6 @@ func (t *TxInput) Amount() uint64 {
                return inp.Amount
        case *ClaimInput:
                return inp.Amount
-       case *DposTx:
-               return inp.Amount
        }
        return 0
 }
@@ -119,8 +112,6 @@ func (t *TxInput) Arguments() [][]byte {
                return inp.Arguments
        case *ClaimInput:
                return inp.Arguments
-       case *DposTx:
-               return inp.Arguments
        }
        return nil
 }
@@ -134,8 +125,6 @@ func (t *TxInput) SetArguments(args [][]byte) {
                inp.Arguments = args
        case *ClaimInput:
                inp.Arguments = args
-       case *DposTx:
-               inp.Arguments = args
        }
 }
 
@@ -197,12 +186,6 @@ func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
                        if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
                                return err
                        }
-               case DposInputType:
-                       ci := new(DposTx)
-                       t.TypedInput = ci
-                       if ci.SpendCommitmentSuffix, err = ci.SpendCommitment.readFrom(r, 1); err != nil {
-                               return err
-                       }
                default:
                        return fmt.Errorf("unsupported input type %d", icType[0])
                }
@@ -243,37 +226,6 @@ func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
                        if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
                                return err
                        }
-               case *DposTx:
-                       txType := uint64(0)
-                       if txType, err = blockchain.ReadVarint63(r); err != nil {
-                               return err
-                       }
-                       inp.Type = TxType(txType)
-                       var from []byte
-                       if from, err = blockchain.ReadVarstr31(r); err != nil {
-                               return err
-                       }
-                       inp.From = string(from)
-                       var to []byte
-                       if to, err = blockchain.ReadVarstr31(r); err != nil {
-                               return err
-                       }
-                       inp.To = string(to)
-                       if inp.Amount, err = blockchain.ReadVarint63(r); err != nil {
-                               return err
-                       }
-                       if inp.Stake, err = blockchain.ReadVarint63(r); err != nil {
-                               return err
-                       }
-                       if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
-                               return err
-                       }
-
-                       var info []byte
-                       if info, err = blockchain.ReadVarstr31(r); err != nil {
-                               return err
-                       }
-                       inp.Info = string(info)
                }
                return nil
        })
@@ -334,11 +286,6 @@ func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
                if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
                        return errors.Wrap(err, "writing coinbase arbitrary")
                }
-       case *DposTx:
-               if _, err = w.Write([]byte{DposInputType}); err != nil {
-                       return err
-               }
-               return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
        }
        return nil
 }
@@ -368,28 +315,6 @@ func (t *TxInput) writeInputWitness(w io.Writer) error {
                _, err := blockchain.WriteVarstrList(w, inp.Arguments)
 
                return err
-       case *DposTx:
-               if _, err := blockchain.WriteVarint63(w, uint64(inp.Type)); err != nil {
-                       return err
-               }
-               if _, err := blockchain.WriteVarstr31(w, []byte(inp.From)); err != nil {
-                       return err
-               }
-               if _, err := blockchain.WriteVarstr31(w, []byte(inp.To)); err != nil {
-                       return err
-               }
-               if _, err := blockchain.WriteVarint63(w, inp.Amount); err != nil {
-                       return err
-               }
-               if _, err := blockchain.WriteVarint63(w, inp.Stake); err != nil {
-                       return err
-               }
-               if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
-                       return err
-               }
-               _, err := blockchain.WriteVarstr31(w, []byte(inp.Info))
-
-               return err
        }
        return nil
 }
index 3a8dcee..2f241a9 100644 (file)
@@ -3,8 +3,6 @@ package protocol
 import (
        "encoding/json"
 
-       "github.com/vapor/protocol/vm"
-
        log "github.com/sirupsen/logrus"
 
        "github.com/vapor/common"
@@ -16,6 +14,8 @@ import (
        "github.com/vapor/protocol/bc/types"
        "github.com/vapor/protocol/state"
        "github.com/vapor/protocol/validation"
+       "github.com/vapor/protocol/vm"
+       "github.com/vapor/protocol/vm/vmutil"
 )
 
 var (
@@ -387,6 +387,9 @@ func (c *Chain) CalculateBalance(block *types.Block, fIsAdd bool) map[bc.Hash]ui
                }
                for _, output := range tx.Outputs {
                        fee -= output.Amount
+                       if vmutil.IsUnspendable(output.ControlProgram) {
+                               continue
+                       }
                        value := int64(output.Amount)
                        address, err = common.NewAddressWitnessPubKeyHash(output.ControlProgram[2:], &consensus.ActiveNetParams)
                        if err != nil {
index fdb19ad..e81fe11 100644 (file)
@@ -1,24 +1,16 @@
 package validation
 
 import (
-       "bytes"
-       "encoding/json"
        "fmt"
        "math"
-       "strconv"
 
+       "github.com/vapor/claim"
        "github.com/vapor/consensus"
        "github.com/vapor/consensus/segwit"
-       "github.com/vapor/crypto"
-       "github.com/vapor/equity/pegin_contract"
        "github.com/vapor/errors"
        "github.com/vapor/math/checked"
        "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-       bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
        "github.com/vapor/protocol/vm"
-       "github.com/vapor/protocol/vm/vmutil"
-       "github.com/vapor/util"
 )
 
 // validate transaction error
@@ -148,15 +140,10 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
        case *bc.Mux:
                parity := make(map[bc.AssetID]int64)
                for i, src := range e.Sources {
-                       e, ok := vs.tx.Entries[*src.Ref]
+                       _, ok := vs.tx.Entries[*src.Ref]
                        if !ok {
                                return errors.Wrapf(bc.ErrMissingEntry, "entry for bytom input %x not found", *src.Ref)
                        }
-                       switch e.(type) {
-                       case *bc.Dpos:
-                               continue
-                       default:
-                       }
 
                        if src.Value.Amount > math.MaxInt64 {
                                return errors.WithDetailf(ErrOverflow, "amount %d exceeds maximum value 2^63", src.Value.Amount)
@@ -334,12 +321,12 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        return errors.New("pegin-no-witness")
                }
 
-               if err := IsValidPeginWitness(stack, *spentOutput); err != nil {
+               // 根据claim链类型选择验证类型
+               validation := &claim.BytomClaimValidation{}
+               if err := validation.IsValidPeginWitness(stack, *spentOutput); err != nil {
                        return err
                }
 
-               // 判断cliam tx的输入是否已经被用
-
                eq, err := spentOutput.Source.Value.Equal(e.WitnessDestination.Value)
                if err != nil {
                        return err
@@ -361,8 +348,6 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        return errors.Wrap(err, "checking spend destination")
                }
                vs.gasStatus.GasValid = true
-       case *bc.Dpos:
-               //fmt.Printf("kkkkkkkkkkkkkkkkkkkkkkkkkkk %T\n", e)
        default:
                return fmt.Errorf("entry has unexpected type %T", e)
        }
@@ -370,117 +355,6 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
        return nil
 }
 
-type MerkleBlock struct {
-       BlockHeader  []byte     `json:"block_header"`
-       TxHashes     []*bc.Hash `json:"tx_hashes"`
-       StatusHashes []*bc.Hash `json:"status_hashes"`
-       Flags        []uint32   `json:"flags"`
-       MatchedTxIDs []*bc.Hash `json:"matched_tx_ids"`
-}
-
-func IsValidPeginWitness(peginWitness [][]byte, prevout bc.Output) (err error) {
-
-       assetAmount := &bc.AssetAmount{
-               AssetId: prevout.Source.Value.AssetId,
-               Amount:  prevout.Source.Value.Amount,
-       }
-
-       src := &bc.ValueSource{
-               Ref:      prevout.Source.Ref,
-               Value:    assetAmount,
-               Position: prevout.Source.Position,
-       }
-       prog := &bc.Program{prevout.ControlProgram.VmVersion, prevout.ControlProgram.Code}
-       bytomPrevout := bc.NewOutput(src, prog, prevout.Source.Position)
-
-       if len(peginWitness) != 5 {
-               return errors.New("peginWitness is error")
-       }
-       amount, err := strconv.ParseUint(string(peginWitness[0]), 10, 64)
-       if err != nil {
-               return err
-       }
-       if !consensus.MoneyRange(amount) {
-               return errors.New("Amount out of range")
-       }
-       /*
-               if len(peginWitness[1]) != 32 {
-                       return errors.New("The length of gennesisBlockHash is not correct")
-               }
-       */
-       claimScript := peginWitness[2]
-
-       rawTx := &bytomtypes.Tx{}
-       err = rawTx.UnmarshalText(peginWitness[3])
-       if err != nil {
-               return err
-       }
-
-       merkleBlock := &MerkleBlock{}
-       err = json.Unmarshal(peginWitness[4], merkleBlock)
-       if err != nil {
-               return err
-       }
-       // proof验证
-       var flags []uint8
-       for flag := range merkleBlock.Flags {
-               flags = append(flags, uint8(flag))
-       }
-       blockHeader := &bytomtypes.BlockHeader{}
-       if err = blockHeader.UnmarshalText(merkleBlock.BlockHeader); err != nil {
-               return err
-       }
-
-       if !types.ValidateTxMerkleTreeProof(merkleBlock.TxHashes, flags, merkleBlock.MatchedTxIDs, blockHeader.BlockCommitment.TransactionsMerkleRoot) {
-               return errors.New("Merkleblock validation failed")
-       }
-
-       // 交易进行验证
-       if err = checkPeginTx(rawTx, bytomPrevout, amount, claimScript); err != nil {
-               return err
-       }
-       var b bc.Hash
-       b.UnmarshalText(peginWitness[1])
-       // Check the genesis block corresponds to a valid peg (only one for now)
-       if b.String() != consensus.ActiveNetParams.ParentGenesisBlockHash {
-               return errors.New("ParentGenesisBlockHash don't match")
-       }
-       // TODO Finally, validate peg-in via rpc call
-
-       if util.ValidatePegin {
-               if err := util.IsConfirmedBytomBlock(blockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
-                       return err
-               }
-       }
-
-       return nil
-}
-
-func checkPeginTx(rawTx *bytomtypes.Tx, prevout *bc.Output, claimAmount uint64, claimScript []byte) error {
-       // Check the transaction nout/value matches
-       amount := rawTx.Outputs[prevout.Source.Position].Amount
-       if claimAmount != amount {
-               return errors.New("transaction nout/value do not matches")
-       }
-       // Check that the witness program matches the p2ch on the p2sh-p2wsh transaction output
-       //federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
-       //scriptHash := crypto.Sha256(federationRedeemScript)
-       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(claimScript)
-       if err != nil {
-               return err
-       }
-
-       scriptHash := crypto.Sha256(peginContractPrograms)
-       controlProg, err := vmutil.P2WSHProgram(scriptHash)
-       if err != nil {
-               return err
-       }
-       if !bytes.Equal(rawTx.Outputs[prevout.Source.Position].ControlProgram, controlProg) {
-               return errors.New("The output control program of transaction does not match the control program of the system's alliance contract")
-       }
-       return nil
-}
-
 func checkValidSrc(vstate *validationState, vs *bc.ValueSource) error {
        if vs == nil {
                return errors.Wrap(ErrMissingField, "empty value source")
@@ -533,11 +407,6 @@ func checkValidSrc(vstate *validationState, vs *bc.ValueSource) error {
                        return errors.Wrapf(ErrPosition, "invalid position %d for coinbase source", vs.Position)
                }
                dest = ref.WitnessDestination
-       case *bc.Dpos:
-               if vs.Position != 0 {
-                       return errors.Wrapf(ErrPosition, "invalid position %d for coinbase source", vs.Position)
-               }
-               dest = ref.WitnessDestination
        default:
                return errors.Wrapf(bc.ErrEntryType, "value source is %T, should be coinbase, issuance, spend, or mux", e)
        }
index 15e8b61..dfc7c46 100644 (file)
@@ -10,9 +10,9 @@ import (
        "time"
 
        "github.com/spf13/cobra"
+       bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
        "github.com/vapor/config"
        chainjson "github.com/vapor/encoding/json"
-       bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
        "github.com/vapor/util"
 )
 
index 7de312d..c7c83f1 100644 (file)
@@ -188,12 +188,12 @@ def send_to_mainchain():
     response = connSide.request("/get-utxo-from-transaction",body_json)
     resp_json = json.loads(response.text)
     if resp_json['status'] == 'success':
-        utxo = json.dumps(resp_json['data']).strip('{}')+"}"
+        utxo = json.dumps(resp_json['data']).strip('{}')
     elif resp_json['status'] == 'fail':
         return json_contents(jsonify(code=-1, msg="get-utxo-from-transaction: " + resp_json['msg']))
     else:
         return json_contents(jsonify(code=-1, msg="fail get utxo from transaction"))
-
+    
     block_height = int(request.json['side_block_height'])
     tx_id  = request.json['side_tx_id'].encode('utf-8')
     alias = request.json['alias'].encode('utf-8')
@@ -229,29 +229,32 @@ def send_to_mainchain():
         return json_contents(jsonify(code=-1, msg="get side raw transaction fail"))
 
     # 构建主链交易
-    body_json = '{"claim_script":"%s","raw_transaction": "%s","control_program":"%s","root_xpubs":%s,%s}' % (claim_script,raw_transaction,control_program,root_xpubs,utxo)
+    body_json = '{"claim_script":"%s","raw_transaction": "%s","control_program":"%s","pubs":%s,%s}' % (claim_script,raw_transaction,control_program,root_xpubs,utxo)
     response = connSide.request("/build-mainchain-tx",json.loads(body_json))
     resp_json = json.loads(response.text.encode('utf-8'))
     tmpl = ""
     if resp_json['status'] == 'success':
-        tmpl = json.dumps(resp_json['data'])
+        tmpl = json.dumps(resp_json['data']['tx'])
     elif resp_json['status'] == 'fail':
         print resp_json
         return json_contents(jsonify(code=-1, msg="build-mainchain-tx: " + resp_json['msg']))
     else:
         return json_contents(jsonify(code=-1, msg="build mainchain transaction fail"))
-
     # 签名
     for key,value in key_pair.items():
         body_json = '{"xprv": "%s","xpub":"%s","transaction":%s,"claim_script":"%s"}' % (key,value,tmpl,claim_script)
         response = connSide.request("/sign-with-key",json.loads(body_json))
         resp_json = json.loads(response.text.encode('utf-8'))
         if resp_json['status'] == 'success':
+            print resp_json
             tmpl = json.dumps(resp_json['data']['transaction'])
             raw_transaction = resp_json['data']['transaction']['raw_transaction'].encode('utf-8')
-        elif resp_json['status'] == 'fail':
+        elif resp_json['status'] == 'fail': 
+            print "sign-with-key"
+            print  resp_json
             return json_contents(jsonify(code=-1, msg="sign-with-key: " + resp_json['msg']))
         else:
+            print resp_json
             return json_contents(jsonify(code=-1, msg="sign-with-key fail"))
     
     # 提交到主链
index 498d301..192fcf9 100644 (file)
@@ -7,9 +7,9 @@ import (
        "fmt"
        "strconv"
 
+       jww "github.com/spf13/jwalterweatherman"
        "github.com/vapor/blockchain/rpc"
        "github.com/vapor/config"
-       jww "github.com/spf13/jwalterweatherman"
 )
 
 var MainchainConfig *config.MainChainRpcConfig