From f58a184bb6507d0d2bc4962b977de698abace5d6 Mon Sep 17 00:00:00 2001 From: mars Date: Thu, 28 Mar 2019 22:30:44 +0800 Subject: [PATCH 1/1] module claim --- account/dpos_builder.go | 40 -- api/cliam_transact.go | 376 +--------------- api/main_transact.go | 319 +------------ api/query.go | 15 +- api/receivers.go | 45 +- blockchain/txbuilder/finalize.go | 4 +- blockchain/txbuilder/mainchain/types.go | 57 --- .../txbuilder => claim/bytom}/mainchain/builder.go | 25 +- .../bytom}/mainchain/constraint.go | 0 .../bytom}/mainchain/data_witness.go | 0 .../bytom}/mainchain/rawtxsig_witness.go | 0 .../bytom}/mainchain/signature_program.go | 0 .../bytom}/mainchain/signature_witness.go | 0 .../bytom}/mainchain/signing_instruction.go | 0 claim/bytom/mainchain/types.go | 170 +++++++ .../txbuilder => claim/bytom}/mainchain/witness.go | 0 .../bytom => claim/bytom/protocolbc}/block.go | 2 +- .../bytom => claim/bytom/protocolbc}/general.go | 2 +- .../types/bytom => claim/bytom/protocolbc}/tx.go | 2 +- .../bytom/protocolbc}/types/block.go | 0 .../bytom/protocolbc}/types/block_commitment.go | 0 .../bytom/protocolbc}/types/block_header.go | 0 .../bytom/protocolbc}/types/block_test.go | 0 .../bytom/protocolbc}/types/coinbase.go | 0 .../bytom => claim/bytom/protocolbc}/types/map.go | 2 +- .../bytom/protocolbc}/types/output_commitment.go | 0 .../bytom/protocolbc}/types/spend.go | 0 .../bytom/protocolbc}/types/spend_commitment.go | 0 .../bytom/protocolbc}/types/transaction.go | 4 +- .../bytom/protocolbc}/types/txinput.go | 0 .../bytom/protocolbc}/types/txoutput.go | 0 claim/bytom_validation.go | 131 ++++++ claim/claim.go | 4 + claim/rpc/bytom/bytom_claim_tx.go | 496 +++++++++++++++++++++ claim/rpc/bytom/bytom_main_tx.go | 366 +++++++++++++++ {api => claim/rpc/bytom}/estimate.go | 4 +- claim/rpc/claim_tx.go | 23 + claim/rpc/main_tx.go | 20 + claim/rpc/pegin.go | 6 + claim/rpc/pegin_address.go | 188 ++++++++ protocol/bc/bc.pb.go | 215 +++------ protocol/bc/bc.proto | 11 - protocol/bc/dpos.go | 36 -- protocol/bc/types/dpos.go | 49 -- protocol/bc/types/map.go | 36 -- protocol/bc/types/txinput.go | 75 ---- protocol/block.go | 7 +- protocol/validation/tx.go | 141 +----- tools/monitor_tx/main.go | 2 +- tools/side_chain_tool/app/api/transaction.py | 15 +- util/call_rpc.go | 2 +- 51 files changed, 1581 insertions(+), 1309 deletions(-) delete mode 100644 blockchain/txbuilder/mainchain/types.go rename {blockchain/txbuilder => claim/bytom}/mainchain/builder.go (84%) rename {blockchain/txbuilder => claim/bytom}/mainchain/constraint.go (100%) rename {blockchain/txbuilder => claim/bytom}/mainchain/data_witness.go (100%) rename {blockchain/txbuilder => claim/bytom}/mainchain/rawtxsig_witness.go (100%) rename {blockchain/txbuilder => claim/bytom}/mainchain/signature_program.go (100%) rename {blockchain/txbuilder => claim/bytom}/mainchain/signature_witness.go (100%) rename {blockchain/txbuilder => claim/bytom}/mainchain/signing_instruction.go (100%) create mode 100644 claim/bytom/mainchain/types.go rename {blockchain/txbuilder => claim/bytom}/mainchain/witness.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/block.go (89%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/general.go (99%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/tx.go (99%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/block.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/block_commitment.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/block_header.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/block_test.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/coinbase.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/map.go (99%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/output_commitment.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/spend.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/spend_commitment.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/transaction.go (98%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/txinput.go (100%) rename {protocol/bc/types/bytom => claim/bytom/protocolbc}/types/txoutput.go (100%) create mode 100644 claim/bytom_validation.go create mode 100644 claim/claim.go create mode 100644 claim/rpc/bytom/bytom_claim_tx.go create mode 100644 claim/rpc/bytom/bytom_main_tx.go rename {api => claim/rpc/bytom}/estimate.go (98%) create mode 100644 claim/rpc/claim_tx.go create mode 100644 claim/rpc/main_tx.go create mode 100644 claim/rpc/pegin.go create mode 100644 claim/rpc/pegin_address.go delete mode 100644 protocol/bc/dpos.go delete mode 100644 protocol/bc/types/dpos.go diff --git a/account/dpos_builder.go b/account/dpos_builder.go index 64f50613..6652a916 100644 --- a/account/dpos_builder.go +++ b/account/dpos_builder.go @@ -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) diff --git a/api/cliam_transact.go b/api/cliam_transact.go index b6dc4494..33af4287 100644 --- a/api/cliam_transact.go +++ b/api/cliam_transact.go @@ -1,383 +1,39 @@ 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) } diff --git a/api/main_transact.go b/api/main_transact.go index 4bb63c82..fdce0b0c 100644 --- a/api/main_transact.go +++ b/api/main_transact.go @@ -1,328 +1,49 @@ 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) } diff --git a/api/query.go b/api/query.go index 79ab3a9d..b59af89c 100644 --- a/api/query.go +++ b/api/query.go @@ -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}) } diff --git a/api/receivers.go b/api/receivers.go index 7ccffc02..87cab430 100644 --- a/api/receivers.go +++ b/api/receivers.go @@ -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) } diff --git a/blockchain/txbuilder/finalize.go b/blockchain/txbuilder/finalize.go index 1cafe4f0..daa6308b 100644 --- a/blockchain/txbuilder/finalize.go +++ b/blockchain/txbuilder/finalize.go @@ -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 index d0497a1a..00000000 --- a/blockchain/txbuilder/mainchain/types.go +++ /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"` -} diff --git a/blockchain/txbuilder/mainchain/builder.go b/claim/bytom/mainchain/builder.go similarity index 84% rename from blockchain/txbuilder/mainchain/builder.go rename to claim/bytom/mainchain/builder.go index ad124838..e11003db 100644 --- a/blockchain/txbuilder/mainchain/builder.go +++ b/claim/bytom/mainchain/builder.go @@ -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/blockchain/txbuilder/mainchain/constraint.go b/claim/bytom/mainchain/constraint.go similarity index 100% rename from blockchain/txbuilder/mainchain/constraint.go rename to claim/bytom/mainchain/constraint.go diff --git a/blockchain/txbuilder/mainchain/data_witness.go b/claim/bytom/mainchain/data_witness.go similarity index 100% rename from blockchain/txbuilder/mainchain/data_witness.go rename to claim/bytom/mainchain/data_witness.go diff --git a/blockchain/txbuilder/mainchain/rawtxsig_witness.go b/claim/bytom/mainchain/rawtxsig_witness.go similarity index 100% rename from blockchain/txbuilder/mainchain/rawtxsig_witness.go rename to claim/bytom/mainchain/rawtxsig_witness.go diff --git a/blockchain/txbuilder/mainchain/signature_program.go b/claim/bytom/mainchain/signature_program.go similarity index 100% rename from blockchain/txbuilder/mainchain/signature_program.go rename to claim/bytom/mainchain/signature_program.go diff --git a/blockchain/txbuilder/mainchain/signature_witness.go b/claim/bytom/mainchain/signature_witness.go similarity index 100% rename from blockchain/txbuilder/mainchain/signature_witness.go rename to claim/bytom/mainchain/signature_witness.go diff --git a/blockchain/txbuilder/mainchain/signing_instruction.go b/claim/bytom/mainchain/signing_instruction.go similarity index 100% rename from blockchain/txbuilder/mainchain/signing_instruction.go rename to claim/bytom/mainchain/signing_instruction.go diff --git a/claim/bytom/mainchain/types.go b/claim/bytom/mainchain/types.go new file mode 100644 index 00000000..ddb0f948 --- /dev/null +++ b/claim/bytom/mainchain/types.go @@ -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"` +} diff --git a/blockchain/txbuilder/mainchain/witness.go b/claim/bytom/mainchain/witness.go similarity index 100% rename from blockchain/txbuilder/mainchain/witness.go rename to claim/bytom/mainchain/witness.go diff --git a/protocol/bc/types/bytom/block.go b/claim/bytom/protocolbc/block.go similarity index 89% rename from protocol/bc/types/bytom/block.go rename to claim/bytom/protocolbc/block.go index 38611a09..2d0fcebc 100644 --- a/protocol/bc/types/bytom/block.go +++ b/claim/bytom/protocolbc/block.go @@ -1,4 +1,4 @@ -package bytom +package protocolbc import "github.com/vapor/protocol/bc" diff --git a/protocol/bc/types/bytom/general.go b/claim/bytom/protocolbc/general.go similarity index 99% rename from protocol/bc/types/bytom/general.go rename to claim/bytom/protocolbc/general.go index 9fa860ff..513fb127 100644 --- a/protocol/bc/types/bytom/general.go +++ b/claim/bytom/protocolbc/general.go @@ -1,4 +1,4 @@ -package bytom +package protocolbc import ( "encoding/binary" diff --git a/protocol/bc/types/bytom/tx.go b/claim/bytom/protocolbc/tx.go similarity index 99% rename from protocol/bc/types/bytom/tx.go rename to claim/bytom/protocolbc/tx.go index a5fa8967..3af65188 100644 --- a/protocol/bc/types/bytom/tx.go +++ b/claim/bytom/protocolbc/tx.go @@ -1,4 +1,4 @@ -package bytom +package protocolbc import ( "github.com/vapor/crypto/sha3pool" diff --git a/protocol/bc/types/bytom/types/block.go b/claim/bytom/protocolbc/types/block.go similarity index 100% rename from protocol/bc/types/bytom/types/block.go rename to claim/bytom/protocolbc/types/block.go diff --git a/protocol/bc/types/bytom/types/block_commitment.go b/claim/bytom/protocolbc/types/block_commitment.go similarity index 100% rename from protocol/bc/types/bytom/types/block_commitment.go rename to claim/bytom/protocolbc/types/block_commitment.go diff --git a/protocol/bc/types/bytom/types/block_header.go b/claim/bytom/protocolbc/types/block_header.go similarity index 100% rename from protocol/bc/types/bytom/types/block_header.go rename to claim/bytom/protocolbc/types/block_header.go diff --git a/protocol/bc/types/bytom/types/block_test.go b/claim/bytom/protocolbc/types/block_test.go similarity index 100% rename from protocol/bc/types/bytom/types/block_test.go rename to claim/bytom/protocolbc/types/block_test.go diff --git a/protocol/bc/types/bytom/types/coinbase.go b/claim/bytom/protocolbc/types/coinbase.go similarity index 100% rename from protocol/bc/types/bytom/types/coinbase.go rename to claim/bytom/protocolbc/types/coinbase.go diff --git a/protocol/bc/types/bytom/types/map.go b/claim/bytom/protocolbc/types/map.go similarity index 99% rename from protocol/bc/types/bytom/types/map.go rename to claim/bytom/protocolbc/types/map.go index 4892c195..92beecb0 100644 --- a/protocol/bc/types/bytom/types/map.go +++ b/claim/bytom/protocolbc/types/map.go @@ -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" ) diff --git a/protocol/bc/types/bytom/types/output_commitment.go b/claim/bytom/protocolbc/types/output_commitment.go similarity index 100% rename from protocol/bc/types/bytom/types/output_commitment.go rename to claim/bytom/protocolbc/types/output_commitment.go diff --git a/protocol/bc/types/bytom/types/spend.go b/claim/bytom/protocolbc/types/spend.go similarity index 100% rename from protocol/bc/types/bytom/types/spend.go rename to claim/bytom/protocolbc/types/spend.go diff --git a/protocol/bc/types/bytom/types/spend_commitment.go b/claim/bytom/protocolbc/types/spend_commitment.go similarity index 100% rename from protocol/bc/types/bytom/types/spend_commitment.go rename to claim/bytom/protocolbc/types/spend_commitment.go diff --git a/protocol/bc/types/bytom/types/transaction.go b/claim/bytom/protocolbc/types/transaction.go similarity index 98% rename from protocol/bc/types/bytom/types/transaction.go rename to claim/bytom/protocolbc/types/transaction.go index c1aa00b4..235154b3 100644 --- a/protocol/bc/types/bytom/types/transaction.go +++ b/claim/bytom/protocolbc/types/transaction.go @@ -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/protocol/bc/types/bytom/types/txinput.go b/claim/bytom/protocolbc/types/txinput.go similarity index 100% rename from protocol/bc/types/bytom/types/txinput.go rename to claim/bytom/protocolbc/types/txinput.go diff --git a/protocol/bc/types/bytom/types/txoutput.go b/claim/bytom/protocolbc/types/txoutput.go similarity index 100% rename from protocol/bc/types/bytom/types/txoutput.go rename to claim/bytom/protocolbc/types/txoutput.go diff --git a/claim/bytom_validation.go b/claim/bytom_validation.go new file mode 100644 index 00000000..252e3dd3 --- /dev/null +++ b/claim/bytom_validation.go @@ -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 index 00000000..fd9273d7 --- /dev/null +++ b/claim/claim.go @@ -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 index 00000000..f7a13f26 --- /dev/null +++ b/claim/rpc/bytom/bytom_claim_tx.go @@ -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 index 00000000..344d111b --- /dev/null +++ b/claim/rpc/bytom/bytom_main_tx.go @@ -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 +} diff --git a/api/estimate.go b/claim/rpc/bytom/estimate.go similarity index 98% rename from api/estimate.go rename to claim/rpc/bytom/estimate.go index 406f9ddf..4b88d2d0 100644 --- a/api/estimate.go +++ b/claim/rpc/bytom/estimate.go @@ -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 index 00000000..e89113c2 --- /dev/null +++ b/claim/rpc/claim_tx.go @@ -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 index 00000000..245ed4d3 --- /dev/null +++ b/claim/rpc/main_tx.go @@ -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 index 00000000..529001fe --- /dev/null +++ b/claim/rpc/pegin.go @@ -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 index 00000000..910696cd --- /dev/null +++ b/claim/rpc/pegin_address.go @@ -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 +} diff --git a/protocol/bc/bc.pb.go b/protocol/bc/bc.pb.go index 984df23b..7d1eb818 100644 --- a/protocol/bc/bc.pb.go +++ b/protocol/bc/bc.pb.go @@ -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, } diff --git a/protocol/bc/bc.proto b/protocol/bc/bc.proto index 0ee23f8d..5a38c4c7 100644 --- a/protocol/bc/bc.proto +++ b/protocol/bc/bc.proto @@ -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 index 39106378..00000000 --- a/protocol/bc/dpos.go +++ /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 index 73a600df..00000000 --- a/protocol/bc/types/dpos.go +++ /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 } diff --git a/protocol/bc/types/map.go b/protocol/bc/types/map.go index 9ad4037b..99be1533 100644 --- a/protocol/bc/types/map.go +++ b/protocol/bc/types/map.go @@ -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) } diff --git a/protocol/bc/types/txinput.go b/protocol/bc/types/txinput.go index 58d01d63..8eaafaf1 100644 --- a/protocol/bc/types/txinput.go +++ b/protocol/bc/types/txinput.go @@ -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 } diff --git a/protocol/block.go b/protocol/block.go index 3a8dceed..2f241a96 100644 --- a/protocol/block.go +++ b/protocol/block.go @@ -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 { diff --git a/protocol/validation/tx.go b/protocol/validation/tx.go index fdb19ad9..e81fe11e 100644 --- a/protocol/validation/tx.go +++ b/protocol/validation/tx.go @@ -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) } diff --git a/tools/monitor_tx/main.go b/tools/monitor_tx/main.go index 15e8b61b..dfc7c462 100644 --- a/tools/monitor_tx/main.go +++ b/tools/monitor_tx/main.go @@ -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" ) diff --git a/tools/side_chain_tool/app/api/transaction.py b/tools/side_chain_tool/app/api/transaction.py index 7de312d3..c7c83f1e 100644 --- a/tools/side_chain_tool/app/api/transaction.py +++ b/tools/side_chain_tool/app/api/transaction.py @@ -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")) # 提交到主链 diff --git a/util/call_rpc.go b/util/call_rpc.go index 498d301e..192fcf9e 100644 --- a/util/call_rpc.go +++ b/util/call_rpc.go @@ -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 -- 2.11.0