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)
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)
}
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)
}
import (
"context"
"encoding/hex"
+ "encoding/json"
"fmt"
"github.com/vapor/blockchain/txbuilder"
"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
}
type utxoResp struct {
- Utxo account.UTXO `json:"utxo"`
+ Utxo []byte `json:"utxo"`
}
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)
}
}
}
- return NewSuccessResponse(&utxoResp{Utxo: utxo})
+ resp, err := json.Marshal(&utxo)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+
+ return NewSuccessResponse(&utxoResp{Utxo: resp})
}
"context"
"github.com/vapor/blockchain/txbuilder"
+ "github.com/vapor/claim/rpc"
chainjson "github.com/vapor/encoding/json"
)
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)
}
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 {
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()
}
}
+++ /dev/null
-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"`
-}
"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
}
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
+}
--- /dev/null
+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"`
+}
-package bytom
+package protocolbc
import "github.com/vapor/protocol/bc"
-package bytom
+package protocolbc
import (
"encoding/binary"
-package bytom
+package protocolbc
import (
"github.com/vapor/crypto/sha3pool"
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"
)
"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.
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()))
--- /dev/null
+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
+}
--- /dev/null
+package claim
+
+type Claim interface {
+}
--- /dev/null
+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
+}
--- /dev/null
+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
+}
-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"
--- /dev/null
+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)
+}
--- /dev/null
+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"`
+}
--- /dev/null
+package rpc
+
+type PeginRpc interface {
+ GetPeginAddress() (interface{}, error)
+ GetPeginContractAddress() (interface{}, error)
+}
--- /dev/null
+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
+}
Issuance
Spend
Claim
- Dpos
*/
package bc
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")
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,
}
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;
-}
+++ /dev/null
-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,
- }
-}
+++ /dev/null
-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 }
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
}
var (
spends []*bc.Spend
- dposs []*bc.Dpos
issuances []*bc.Issuance
coinbase *bc.Coinbase
claim *bc.Claim
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)
}
}
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)
}
SpendInputType
CoinbaseInputType
ClainPeginInputType
- DposInputType
)
type (
return inp.AssetAmount
case *ClaimInput:
return inp.AssetAmount
- case *DposTx:
- return inp.AssetAmount
}
return bc.AssetAmount{}
}
return *inp.AssetId
case *ClaimInput:
return *inp.AssetId
- case *DposTx:
- return *inp.AssetId
}
return bc.AssetID{}
return inp.Amount
case *ClaimInput:
return inp.Amount
- case *DposTx:
- return inp.Amount
}
return 0
}
return inp.Arguments
case *ClaimInput:
return inp.Arguments
- case *DposTx:
- return inp.Arguments
}
return nil
}
inp.Arguments = args
case *ClaimInput:
inp.Arguments = args
- case *DposTx:
- inp.Arguments = args
}
}
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])
}
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
})
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
}
_, 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
}
import (
"encoding/json"
- "github.com/vapor/protocol/vm"
-
log "github.com/sirupsen/logrus"
"github.com/vapor/common"
"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 (
}
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 {
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
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)
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
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)
}
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")
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)
}
"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"
)
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')
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"))
# 提交到主链
"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