package account
import (
+ "encoding/hex"
"encoding/json"
"reflect"
"sort"
"github.com/vapor/crypto"
"github.com/vapor/crypto/ed25519/chainkd"
"github.com/vapor/crypto/sha3pool"
+ "github.com/vapor/equity/pegin_contract"
"github.com/vapor/errors"
"github.com/vapor/protocol"
"github.com/vapor/protocol/bc"
func (m *Manager) CreatePeginAddress(accountID string, change bool) (string, []byte, error) {
// 通过配置获取
- claimCtrlProg, _ := m.CreateAddress(accountID, change)
+ claimCtrlProg, err := m.CreateAddress(accountID, change)
+ if err != nil {
+ return "", nil, err
+ }
claimScript := claimCtrlProg.ControlProgram
federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
scriptHash := crypto.Sha256(federationRedeemScript)
- address, err := common.NewAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
+ 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 (m *Manager) CreatePeginContractPrograms(accountID string, change bool) (string, []byte, error) {
+ // 通过配置获取
+ claimCtrlProg, err := m.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 (m *Manager) CreatePeginContractAddress(accountID string, change bool) (string, []byte, []byte, error) {
+ // 通过配置获取
+ claimCtrlProg, err := m.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 (m *Manager) 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
}
m.Handle("/recovery-wallet", jsonHandler(a.recoveryFromRootXPubs))
m.Handle("/get-pegin-address", jsonHandler(a.getPeginAddress))
- m.Handle("/claim-pegin-transaction", jsonHandler(a.claimPeginTx))
+ m.Handle("/get-pegin-contract-address", jsonHandler(a.getPeginContractAddress))
+ m.Handle("/claim-pegin-transaction", jsonHandler(a.claimContractPeginTx))
m.Handle("/create-key-pair", jsonHandler(a.createXKeys))
m.Handle("/get-utxo-from-transaction", jsonHandler(a.getUnspentOutputs))
m.Handle("/get-side-raw-transaction", jsonHandler(a.getSideRawTransaction))
- m.Handle("/build-mainchain-tx", jsonHandler(a.buildMainChainTx))
+ m.Handle("/build-mainchain-tx", jsonHandler(a.buildMainChainTxForContract))
m.Handle("/sign-with-key", jsonHandler(a.signWithKey))
} else {
log.Warn("Please enable wallet")
--- /dev/null
+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"
+)
+
+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
+}
+
+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})
+}
+
+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
+ //txInput := types.NewClaimInputInput(nil, *ins.RawTx.Outputs[nOut].AssetId, ins.RawTx.Outputs[nOut].Amount, cp.ControlProgram)
+ sourceID := *ins.RawTx.OutputID(nOut)
+ outputAccount := ins.RawTx.Outputs[nOut].Amount
+ assetID := *ins.RawTx.Outputs[nOut].AssetId
+
+ txInput := types.NewClaimInputInput(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, _ := 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
+ //txInput := types.NewClaimInputInput(nil, *ins.RawTx.Outputs[nOut].AssetId, ins.RawTx.Outputs[nOut].Amount, cp.ControlProgram)
+
+ sourceID := *ins.RawTx.OutputID(nOut)
+ outputAccount := ins.RawTx.Outputs[nOut].Amount
+ assetID := *ins.RawTx.Outputs[nOut].AssetId
+
+ txInput := types.NewClaimInputInput(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
+}
--- /dev/null
+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"
+ 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)
+}
+
+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)
+ }
+
+ 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)
+ 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
+}
+
+// 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(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)
+ }
+
+ // 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
+}
+
+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
+}
"github.com/vapor/blockchain/txbuilder"
"github.com/vapor/crypto/ed25519"
- "github.com/vapor/protocol/bc/types/bytom"
log "github.com/sirupsen/logrus"
type GetRawTransationResp struct {
Tx *bytomtypes.Tx `json:"raw_transaction"`
- BlockHash bytom.Hash `json:"block_hash"`
+ BlockHash bc.Hash `json:"block_hash"`
}
func (a *API) getRawTransaction(ins struct {
txID := bc.Hash{}
txID.UnmarshalText([]byte(ins.TxID))
-
for _, tx := range block.Transactions {
if tx.ID.String() == txID.String() {
rawTransaction = tx
type fundingResp struct {
MainchainAddress string `json:"mainchain_address"`
+ ControlProgram chainjson.HexBytes `json:"control_program,omitempty"`
ClaimScript chainjson.HexBytes `json:"claim_script"`
}
ClaimScript: claimScript,
})
}
+
+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
+ }
+
+ mainchainAddress, controlProgram, claimScript, err := a.wallet.AccountMgr.CreatePeginContractAddress(accountID, false)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+
+ return NewSuccessResponse(fundingResp{
+ MainchainAddress: mainchainAddress,
+ ControlProgram: controlProgram,
+ ClaimScript: claimScript,
+ })
+}
package api
import (
- "bytes"
"context"
- "crypto/hmac"
- "crypto/sha256"
"encoding/json"
"math"
- "strconv"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/vapor/account"
- "github.com/vapor/blockchain/signers"
"github.com/vapor/blockchain/txbuilder"
- "github.com/vapor/blockchain/txbuilder/mainchain"
- "github.com/vapor/common"
"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/net/http/reqid"
"github.com/vapor/protocol/bc"
"github.com/vapor/protocol/bc/types"
- "github.com/vapor/protocol/bc/types/bytom"
- bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
- "github.com/vapor/protocol/vm/vmutil"
- "github.com/vapor/util"
)
var (
}
return NewSuccessResponse(txGasResp)
}
-
-func getPeginTxnOutputIndex(rawTx bytomtypes.Tx, controlProg []byte) int {
- for index, output := range rawTx.Outputs {
- if bytes.Equal(output.ControlProgram, controlProg) {
- return index
- }
- }
- return 0
-}
-
-func toHash(hexBytes []chainjson.HexBytes) (hashs []*bytom.Hash) {
- for _, data := range hexBytes {
- b32 := [32]byte{}
- copy(b32[:], data)
- res := bytom.NewHash(b32)
- hashs = append(hashs, &res)
- }
- return
-}
-
-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})
-}
-
-// GetMerkleBlockResp is resp struct for GetTxOutProof API
-type GetMerkleBlock struct {
- 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"`
-}
-
-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)
- if !bytomtypes.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) {
- 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
- //txInput := types.NewClaimInputInput(nil, *ins.RawTx.Outputs[nOut].AssetId, ins.RawTx.Outputs[nOut].Amount, cp.ControlProgram)
- assetId := bc.AssetID{}
- assetId.V0 = ins.RawTx.Outputs[nOut].AssetId.GetV0()
- assetId.V1 = ins.RawTx.Outputs[nOut].AssetId.GetV1()
- assetId.V2 = ins.RawTx.Outputs[nOut].AssetId.GetV2()
- assetId.V3 = ins.RawTx.Outputs[nOut].AssetId.GetV3()
-
- sourceID := bc.Hash{}
- sourceID.V0 = ins.RawTx.OutputID(nOut).GetV0()
- sourceID.V1 = ins.RawTx.OutputID(nOut).GetV1()
- sourceID.V2 = ins.RawTx.OutputID(nOut).GetV2()
- sourceID.V3 = ins.RawTx.OutputID(nOut).GetV3()
- outputAccount := ins.RawTx.Outputs[nOut].Amount
-
- txInput := types.NewClaimInputInput(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, _ := json.Marshal(ins.RawTx)
- stack = append(stack, tx)
- // proof
- MerkleBLock := GetMerkleBlock{
- BlockHeader: ins.BlockHeader,
- TxHashes: ins.TxHashes,
- StatusHashes: ins.StatusHashes,
- Flags: ins.Flags,
- MatchedTxIDs: ins.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) buildMainChainTx(ins struct {
- Utxo account.UTXO `json:"utxo"`
- Tx types.Tx `json:"raw_transaction"`
- RootXPubs []chainkd.XPub `json:"root_xpubs"`
- Alias string `json:"alias"`
- 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)
- }
- acc := &account.Account{}
- var err error
- if acc, err = a.wallet.AccountMgr.FindByAlias(ins.Alias); err != nil {
- acc, err = a.wallet.AccountMgr.Create(xpubs, len(xpubs), ins.Alias, signers.BIP0044)
- if err != nil {
- return NewErrorResponse(err)
- }
- }
- ins.Utxo.ControlProgramIndex = acc.Signer.KeyIndex
-
- txInput, sigInst, err := utxoToInputs(acc.Signer, &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 := bytom.AssetID{
- V0: output.Source.Value.AssetId.GetV0(),
- V1: output.Source.Value.AssetId.GetV1(),
- V2: output.Source.Value.AssetId.GetV2(),
- V3: output.Source.Value.AssetId.GetV3(),
- }
- 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
- assetID := bytom.AssetID{
- V0: u.AssetID.GetV0(),
- V1: u.AssetID.GetV1(),
- V2: u.AssetID.GetV2(),
- V3: u.AssetID.GetV3(),
- }
- out := bytomtypes.NewTxOutput(assetID, changeAmount, ins.Utxo.ControlProgram)
- builder.AddOutput(out)
- }
-
- tmpl, tx, err := builder.Build()
- if err != nil {
- return NewErrorResponse(err)
- }
- //交易费估算
- txGasResp, err := EstimateTxGasForMainchain(*tmpl)
- 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
-}
-
-// UtxoToInputs convert an utxo to the txinput
-func utxoToInputs(signer *signers.Signer, u *account.UTXO) (*bytomtypes.TxInput, *mainchain.SigningInstruction, error) {
- sourceID := bytom.Hash{
- V0: u.SourceID.GetV0(),
- V1: u.SourceID.GetV1(),
- V2: u.SourceID.GetV2(),
- V3: u.SourceID.GetV3(),
- }
-
- assetID := bytom.AssetID{
- V0: u.AssetID.GetV0(),
- V1: u.AssetID.GetV1(),
- V2: u.AssetID.GetV2(),
- V3: u.AssetID.GetV3(),
- }
-
- txInput := bytomtypes.NewSpendInput(nil, sourceID, assetID, u.Amount, u.SourcePos, u.ControlProgram)
- sigInst := &mainchain.SigningInstruction{}
- if signer == nil {
- return txInput, sigInst, nil
- }
-
- // TODO u.Change看怎么填写
- path, _ := signers.Path(signer, signers.AccountKeySpace, u.Change, u.ControlProgramIndex)
- if u.Address == "" {
- sigInst.AddWitnessKeys(signer.XPubs, path, signer.Quorum)
- return txInput, sigInst, nil
- }
-
- address, err := common.DecodeBytomAddress(u.Address, &consensus.ActiveNetParams)
- if err != nil {
- return nil, nil, err
- }
-
- switch address.(type) {
- case *common.AddressWitnessPubKeyHash:
- sigInst.AddRawWitnessKeys(signer.XPubs, path, signer.Quorum)
- derivedXPubs := chainkd.DeriveXPubs(signer.XPubs, path)
- derivedPK := derivedXPubs[0].PublicKey()
- sigInst.WitnessComponents = append(sigInst.WitnessComponents, mainchain.DataWitness([]byte(derivedPK)))
-
- case *common.AddressWitnessScriptHash:
- sigInst.AddRawWitnessKeys(signer.XPubs, path, signer.Quorum)
- //path := signers.Path(signer, signers.AccountKeySpace, u.ControlProgramIndex)
- //derivedXPubs := chainkd.DeriveXPubs(signer.XPubs, path)
- derivedXPubs := signer.XPubs
- derivedPKs := chainkd.XPubKeys(derivedXPubs)
- script, err := vmutil.P2SPMultiSigProgram(derivedPKs, signer.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
-}
-
-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
-}
import (
"github.com/vapor/protocol/bc"
- "github.com/vapor/protocol/bc/types/bytom"
"github.com/vapor/protocol/vm"
"github.com/vapor/protocol/vm/vmutil"
)
// at the given index, optionally with the given refdatahash.
type payConstraint struct {
Index int
- bytom.AssetAmount
+ bc.AssetAmount
Program []byte
}
// Already have a signature for this key
continue
}
- path := make([][]byte, len(keyID.DerivationPath))
- for i, p := range keyID.DerivationPath {
- path[i] = p
- }
if keyID.XPub.String() != xprv.XPub().String() {
continue
}
// AddWitnessKeys adds a SignatureWitness with the given quorum and
// list of keys derived by applying the derivation path to each of the
// xpubs.
-func (si *SigningInstruction) AddWitnessKeys(xpubs []chainkd.XPub, path [][]byte, quorum int) {
- hexPath := make([]chainjson.HexBytes, 0, len(path))
- for _, p := range path {
- hexPath = append(hexPath, p)
- }
+func (si *SigningInstruction) AddWitnessKeys(xpubs []chainkd.XPub, quorum int) {
keyIDs := make([]keyID, 0, len(xpubs))
for _, xpub := range xpubs {
- keyIDs = append(keyIDs, keyID{xpub, hexPath})
+ keyIDs = append(keyIDs, keyID{XPub: xpub})
}
sw := &SignatureWitness{
si.WitnessComponents = append(si.WitnessComponents, sw)
}
+func (si *SigningInstruction) AddRawWitnessKeysWithoutPath(xpubs []chainkd.XPub, quorum int) {
+
+ keyIDs := make([]keyID, 0, len(xpubs))
+ for _, xpub := range xpubs {
+ keyIDs = append(keyIDs, keyID{XPub: xpub})
+ }
+
+ sw := &RawTxSigWitness{
+ Quorum: quorum,
+ Keys: keyIDs,
+ }
+ si.WitnessComponents = append(si.WitnessComponents, sw)
+}
+
// SigningInstruction gives directions for signing inputs in a TxTemplate.
type SigningInstruction struct {
Position uint32 `json:"position"`
"github.com/vapor/crypto/ed25519/chainkd"
chainjson "github.com/vapor/encoding/json"
- "github.com/vapor/protocol/bc/types/bytom"
+ "github.com/vapor/protocol/bc"
bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
)
}
// Hash return sign hash
-func (t *Template) Hash(idx uint32) bytom.Hash {
+func (t *Template) Hash(idx uint32) bc.Hash {
return t.Transaction.SigHash(idx)
}
![pegin-address](pegin-address.png)
-- 在主链的dashboard,发送btm到mainchain_address
+- 在主链的dashboard,发送btm到mainchain_address 或者启动monitor_tx自动处理claim tx
- 工具页面赎回交易填入参数,发送交易
--- /dev/null
+contract LockWith3Keys(pubkey1, pubkey2, pubkey3: PublicKey) locks amount of asset {
+ clause unlockWith2Sigs(sig1, sig2: Signature) {
+ verify checkTxMultiSig([pubkey1, pubkey2, pubkey3], [sig1, sig2])
+ unlock amount of asset
+ }
+}
+
--- /dev/null
+package pegin_contract
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "errors"
+ "fmt"
+ "strings"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/vapor/consensus"
+ "github.com/vapor/crypto/ed25519"
+ "github.com/vapor/crypto/ed25519/chainkd"
+ chainjson "github.com/vapor/encoding/json"
+ "github.com/vapor/equity/compiler"
+)
+
+const module = "pegin_contract"
+
+var lockWith2of3KeysFmt = `
+contract LockWith2of3Keys(%s) locks amount of asset {
+ clause unlockWith2Sigs(%s) {
+ verify checkTxMultiSig(%s)
+ unlock amount of asset
+ }
+}
+`
+
+func GetPeginContractPrograms(claimScript []byte) ([]byte, error) {
+
+ pubkeys := getNewXpub(consensus.ActiveNetParams.FedpegXPubs, claimScript)
+ num := len(pubkeys)
+ if num == 0 {
+ return nil, errors.New("Fedpeg's XPubs is empty")
+ }
+ params := ""
+ unlockParams := ""
+ checkParams := "["
+
+ for index := 0; index < num; index++ {
+ param := fmt.Sprintf("pubkey%d", index+1)
+ params += param
+ checkParams += param
+ if (index + 1) < num {
+ params += ","
+ checkParams += ","
+ }
+ }
+ params += ": PublicKey"
+ checkParams += "],["
+
+ signNum := getNumberOfSignaturesRequired(pubkeys)
+ for index := 0; index < signNum; index++ {
+ param := fmt.Sprintf("sig%d", index+1)
+ unlockParams += param
+ checkParams += param
+ if index+1 < signNum {
+ unlockParams += ","
+ checkParams += ","
+ }
+ }
+
+ unlockParams += ": Signature"
+ checkParams += "]"
+
+ lockWith2of3Keys := fmt.Sprintf(lockWith2of3KeysFmt, params, unlockParams, checkParams)
+ r := strings.NewReader(lockWith2of3Keys)
+ compiled, err := compiler.Compile(r)
+ if err != nil {
+ return nil, errors.New("Compile contract failed")
+ }
+
+ contract := compiled[len(compiled)-1]
+
+ if num < len(contract.Params) {
+ return nil, errors.New("Compile contract failed")
+ }
+
+ contractArgs, err := convertArguments(contract, pubkeys)
+ if err != nil {
+ log.WithFields(log.Fields{"module": module, "error": err}).Error("Convert arguments into contract parameters error")
+ return nil, errors.New("Convert arguments into contract parameters error")
+ }
+
+ instantProg, err := instantiateContract(contract, contractArgs)
+ if err != nil {
+ log.WithFields(log.Fields{"module": module, "error": err}).Error("Instantiate contract error")
+ return nil, errors.New("Instantiate contract error")
+ }
+
+ return instantProg, nil
+}
+
+func getNewXpub(federationRedeemXPub []chainkd.XPub, claimScript []byte) []ed25519.PublicKey {
+
+ var pubkeys []ed25519.PublicKey
+ for _, xpub := range federationRedeemXPub {
+ // pub + scriptPubKey 生成一个随机数A
+ var tmp [32]byte
+ h := hmac.New(sha256.New, xpub[:])
+ h.Write(claimScript)
+ tweak := h.Sum(tmp[:])
+ // pub + A 生成一个新的公钥pub_new
+ chaildXPub := xpub.Child(tweak)
+ pubkeys = append(pubkeys, chaildXPub.PublicKey())
+ }
+ return pubkeys
+}
+
+func getNumberOfSignaturesRequired(pubkeys []ed25519.PublicKey) int {
+ return len(pubkeys)/2 + 1
+}
+
+// InstantiateContract instantiate contract parameters
+func instantiateContract(contract *compiler.Contract, args []compiler.ContractArg) ([]byte, error) {
+ program, err := compiler.Instantiate(contract.Body, contract.Params, contract.Recursive, args)
+ if err != nil {
+ return nil, err
+ }
+
+ return program, nil
+}
+
+func convertArguments(contract *compiler.Contract, args []ed25519.PublicKey) ([]compiler.ContractArg, error) {
+ var contractArgs []compiler.ContractArg
+ for i, p := range contract.Params {
+ var argument compiler.ContractArg
+ switch p.Type {
+ case "PublicKey":
+ argument.S = (*chainjson.HexBytes)(&args[i])
+ default:
+ return nil, errors.New("Contract parameter type error")
+ }
+ contractArgs = append(contractArgs, argument)
+ }
+
+ return contractArgs, nil
+}
if !exist {
cmn.Exit(cmn.Fmt("chain_id[%v] don't exist", config.ChainID))
}
- var federationRedeemXPubs []chainkd.XPub
- if fedpegXPubs := strings.Split(config.Side.FedpegXPubs, ","); len(fedpegXPubs) > 0 {
+ if config.Side.FedpegXPubs != "" {
+ var federationRedeemXPubs []chainkd.XPub
+ fedpegXPubs := strings.Split(config.Side.FedpegXPubs, ",")
for _, xpubStr := range fedpegXPubs {
var xpub chainkd.XPub
xpub.UnmarshalText([]byte(xpubStr))
federationRedeemXPubs = append(federationRedeemXPubs, xpub)
}
+ consensus.ActiveNetParams.FedpegXPubs = federationRedeemXPubs
}
- var signBlockXPubs []chainkd.XPub
- if xPubs := strings.Split(config.Side.SignBlockXPubs, ","); len(xPubs) > 0 {
+ if config.Side.SignBlockXPubs != "" {
+ var signBlockXPubs []chainkd.XPub
+ xPubs := strings.Split(config.Side.SignBlockXPubs, ",")
for _, xpubStr := range xPubs {
var xpub chainkd.XPub
xpub.UnmarshalText([]byte(xpubStr))
signBlockXPubs = append(signBlockXPubs, xpub)
}
+ consensus.ActiveNetParams.SignBlockXPubs = signBlockXPubs
}
consensus.ActiveNetParams.Signer = config.Signer
- consensus.ActiveNetParams.FedpegXPubs = federationRedeemXPubs
- consensus.ActiveNetParams.SignBlockXPubs = signBlockXPubs
consensus.ActiveNetParams.PeginMinDepth = config.Side.PeginMinDepth
consensus.ActiveNetParams.ParentGenesisBlockHash = config.Side.ParentGenesisBlockHash
}
}
if util.ValidatePegin {
for {
- resp, err := util.CallRPC("/get-block-header", &Req{BlockHeight: 0})
+ resp, err := util.CallRPC("/get-merkle-proof", &Req{BlockHeight: 0})
if err != nil {
log.Error("Call mainchain interface get-block-header failed")
time.Sleep(time.Millisecond * 1000)
ValueSource
ValueDestination
Proof
+ BytomBlockHeader
BlockHeader
TxHeader
TxVerifyResult
return nil
}
+type BytomBlockHeader struct {
+ Version uint64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
+ Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"`
+ PreviousBlockId *Hash `protobuf:"bytes,3,opt,name=previous_block_id,json=previousBlockId" json:"previous_block_id,omitempty"`
+ Timestamp uint64 `protobuf:"varint,4,opt,name=timestamp" json:"timestamp,omitempty"`
+ TransactionsRoot *Hash `protobuf:"bytes,5,opt,name=transactions_root,json=transactionsRoot" json:"transactions_root,omitempty"`
+ TransactionStatusHash *Hash `protobuf:"bytes,6,opt,name=transaction_status_hash,json=transactionStatusHash" json:"transaction_status_hash,omitempty"`
+ Nonce uint64 `protobuf:"varint,7,opt,name=nonce" json:"nonce,omitempty"`
+ Bits uint64 `protobuf:"varint,8,opt,name=bits" json:"bits,omitempty"`
+ TransactionStatus *TransactionStatus `protobuf:"bytes,9,opt,name=transaction_status,json=transactionStatus" json:"transaction_status,omitempty"`
+}
+
+func (m *BytomBlockHeader) Reset() { *m = BytomBlockHeader{} }
+func (m *BytomBlockHeader) String() string { return proto.CompactTextString(m) }
+func (*BytomBlockHeader) ProtoMessage() {}
+func (*BytomBlockHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
+
+func (m *BytomBlockHeader) GetVersion() uint64 {
+ if m != nil {
+ return m.Version
+ }
+ return 0
+}
+
+func (m *BytomBlockHeader) GetHeight() uint64 {
+ if m != nil {
+ return m.Height
+ }
+ return 0
+}
+
+func (m *BytomBlockHeader) GetPreviousBlockId() *Hash {
+ if m != nil {
+ return m.PreviousBlockId
+ }
+ return nil
+}
+
+func (m *BytomBlockHeader) GetTimestamp() uint64 {
+ if m != nil {
+ return m.Timestamp
+ }
+ return 0
+}
+
+func (m *BytomBlockHeader) GetTransactionsRoot() *Hash {
+ if m != nil {
+ return m.TransactionsRoot
+ }
+ return nil
+}
+
+func (m *BytomBlockHeader) GetTransactionStatusHash() *Hash {
+ if m != nil {
+ return m.TransactionStatusHash
+ }
+ return nil
+}
+
+func (m *BytomBlockHeader) GetNonce() uint64 {
+ if m != nil {
+ return m.Nonce
+ }
+ return 0
+}
+
+func (m *BytomBlockHeader) GetBits() uint64 {
+ if m != nil {
+ return m.Bits
+ }
+ return 0
+}
+
+func (m *BytomBlockHeader) GetTransactionStatus() *TransactionStatus {
+ if m != nil {
+ return m.TransactionStatus
+ }
+ return nil
+}
+
type BlockHeader struct {
Version uint64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"`
func (m *BlockHeader) Reset() { *m = BlockHeader{} }
func (m *BlockHeader) String() string { return proto.CompactTextString(m) }
func (*BlockHeader) ProtoMessage() {}
-func (*BlockHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
+func (*BlockHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (m *BlockHeader) GetVersion() uint64 {
if m != nil {
func (m *TxHeader) Reset() { *m = TxHeader{} }
func (m *TxHeader) String() string { return proto.CompactTextString(m) }
func (*TxHeader) ProtoMessage() {}
-func (*TxHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
+func (*TxHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
func (m *TxHeader) GetVersion() uint64 {
if m != nil {
func (m *TxVerifyResult) Reset() { *m = TxVerifyResult{} }
func (m *TxVerifyResult) String() string { return proto.CompactTextString(m) }
func (*TxVerifyResult) ProtoMessage() {}
-func (*TxVerifyResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
+func (*TxVerifyResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
func (m *TxVerifyResult) GetStatusFail() bool {
if m != nil {
func (m *TransactionStatus) Reset() { *m = TransactionStatus{} }
func (m *TransactionStatus) String() string { return proto.CompactTextString(m) }
func (*TransactionStatus) ProtoMessage() {}
-func (*TransactionStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
+func (*TransactionStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
func (m *TransactionStatus) GetVersion() uint64 {
if m != nil {
func (m *Mux) Reset() { *m = Mux{} }
func (m *Mux) String() string { return proto.CompactTextString(m) }
func (*Mux) ProtoMessage() {}
-func (*Mux) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
+func (*Mux) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
func (m *Mux) GetSources() []*ValueSource {
if m != nil {
func (m *Coinbase) Reset() { *m = Coinbase{} }
func (m *Coinbase) String() string { return proto.CompactTextString(m) }
func (*Coinbase) ProtoMessage() {}
-func (*Coinbase) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
+func (*Coinbase) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
func (m *Coinbase) GetWitnessDestination() *ValueDestination {
if m != nil {
func (m *Output) Reset() { *m = Output{} }
func (m *Output) String() string { return proto.CompactTextString(m) }
func (*Output) ProtoMessage() {}
-func (*Output) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
+func (*Output) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
func (m *Output) GetSource() *ValueSource {
if m != nil {
func (m *Retirement) Reset() { *m = Retirement{} }
func (m *Retirement) String() string { return proto.CompactTextString(m) }
func (*Retirement) ProtoMessage() {}
-func (*Retirement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
+func (*Retirement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
func (m *Retirement) GetSource() *ValueSource {
if m != nil {
func (m *Issuance) Reset() { *m = Issuance{} }
func (m *Issuance) String() string { return proto.CompactTextString(m) }
func (*Issuance) ProtoMessage() {}
-func (*Issuance) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
+func (*Issuance) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
func (m *Issuance) GetNonceHash() *Hash {
if m != nil {
func (m *Spend) Reset() { *m = Spend{} }
func (m *Spend) String() string { return proto.CompactTextString(m) }
func (*Spend) ProtoMessage() {}
-func (*Spend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
+func (*Spend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
func (m *Spend) GetSpentOutputId() *Hash {
if m != nil {
func (m *Claim) Reset() { *m = Claim{} }
func (m *Claim) String() string { return proto.CompactTextString(m) }
func (*Claim) ProtoMessage() {}
-func (*Claim) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
+func (*Claim) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
func (m *Claim) GetSpentOutputId() *Hash {
if m != nil {
proto.RegisterType((*ValueSource)(nil), "bc.ValueSource")
proto.RegisterType((*ValueDestination)(nil), "bc.ValueDestination")
proto.RegisterType((*Proof)(nil), "bc.Proof")
+ proto.RegisterType((*BytomBlockHeader)(nil), "bc.BytomBlockHeader")
proto.RegisterType((*BlockHeader)(nil), "bc.BlockHeader")
proto.RegisterType((*TxHeader)(nil), "bc.TxHeader")
proto.RegisterType((*TxVerifyResult)(nil), "bc.TxVerifyResult")
func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
- // 982 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcd, 0x6e, 0xdb, 0xc6,
- 0x13, 0x87, 0x24, 0xea, 0x6b, 0xe4, 0x58, 0xd6, 0xda, 0xc9, 0x9f, 0x08, 0xf2, 0x47, 0x02, 0x02,
- 0x89, 0x5b, 0x14, 0x30, 0x6c, 0x39, 0x6d, 0x2f, 0x3d, 0xd4, 0xb5, 0x9b, 0x46, 0x07, 0x23, 0xc6,
- 0xda, 0xf0, 0x95, 0x58, 0x91, 0x2b, 0x69, 0x51, 0x8a, 0xab, 0xee, 0x2e, 0x55, 0xc7, 0xb7, 0x3e,
- 0x44, 0x8f, 0x7d, 0x8e, 0x3e, 0x42, 0x4f, 0x7d, 0x92, 0xbe, 0x44, 0xb1, 0xc3, 0xa5, 0x44, 0x7d,
- 0xe4, 0x0b, 0x45, 0x0f, 0xbd, 0x71, 0x66, 0x67, 0xe7, 0xe3, 0x37, 0xbf, 0x99, 0x25, 0xb4, 0x86,
- 0xd1, 0xd1, 0x4c, 0x49, 0x23, 0x49, 0x75, 0x18, 0x05, 0xaf, 0xc0, 0x7b, 0xcd, 0xf4, 0x84, 0xec,
- 0x42, 0x75, 0x7e, 0xec, 0x57, 0x9e, 0x55, 0x3e, 0x6b, 0xd0, 0xea, 0xfc, 0x18, 0xe5, 0x13, 0xbf,
- 0xea, 0xe4, 0x13, 0x94, 0xfb, 0x7e, 0xcd, 0xc9, 0x7d, 0x94, 0x4f, 0x7d, 0xcf, 0xc9, 0xa7, 0xc1,
- 0x37, 0xd0, 0xbc, 0x52, 0x72, 0xac, 0xd8, 0x94, 0xfc, 0x1f, 0x60, 0x3e, 0x0d, 0xe7, 0x5c, 0x69,
- 0x21, 0x53, 0x74, 0xe9, 0xd1, 0xf6, 0x7c, 0x7a, 0x9b, 0x2b, 0x08, 0x01, 0x2f, 0x92, 0x31, 0x47,
- 0xdf, 0x3b, 0x14, 0xbf, 0x83, 0x01, 0x34, 0xcf, 0xb4, 0xe6, 0x66, 0x70, 0xf1, 0x8f, 0x13, 0xb9,
- 0x84, 0x0e, 0xba, 0x3a, 0x9b, 0xca, 0x2c, 0x35, 0xe4, 0x05, 0xb4, 0x98, 0x15, 0x43, 0x11, 0xa3,
- 0xd3, 0x4e, 0xbf, 0x73, 0x34, 0x8c, 0x8e, 0x5c, 0x34, 0xda, 0xc4, 0xc3, 0x41, 0x4c, 0x1e, 0x41,
- 0x83, 0xe1, 0x0d, 0x0c, 0xe5, 0x51, 0x27, 0x05, 0x63, 0xe8, 0xa2, 0xed, 0x05, 0x1f, 0x89, 0x54,
- 0x18, 0x5b, 0xc0, 0x57, 0xb0, 0x27, 0xb4, 0xce, 0x58, 0x1a, 0xf1, 0x70, 0x96, 0xd7, 0x5c, 0x76,
- 0xed, 0x60, 0xa0, 0xdd, 0xc2, 0xa8, 0xc0, 0xe5, 0x09, 0x78, 0x31, 0x33, 0x0c, 0x03, 0x74, 0xfa,
- 0x2d, 0x6b, 0x6b, 0xa1, 0xa7, 0xa8, 0x0d, 0x12, 0xe8, 0xdc, 0xb2, 0x24, 0xe3, 0xd7, 0x32, 0x53,
- 0x11, 0x27, 0x8f, 0xa1, 0xa6, 0xf8, 0xc8, 0xf9, 0x5d, 0xda, 0x5a, 0x25, 0x79, 0x0e, 0xf5, 0xb9,
- 0x35, 0x75, 0x9e, 0xba, 0x8b, 0x82, 0xf2, 0x9a, 0x69, 0x7e, 0x4a, 0x1e, 0x43, 0x6b, 0x26, 0x35,
- 0xe6, 0x8c, 0x78, 0x79, 0x74, 0x21, 0x07, 0x3f, 0xc1, 0x1e, 0x46, 0xbb, 0xe0, 0xda, 0x88, 0x94,
- 0x61, 0x5d, 0xff, 0x72, 0xc8, 0x73, 0xa8, 0x5f, 0x29, 0x29, 0x47, 0x96, 0x00, 0x5a, 0x8c, 0x73,
- 0x66, 0xec, 0x50, 0xfc, 0x26, 0x2f, 0x60, 0x37, 0x92, 0xa9, 0x51, 0x32, 0x71, 0x68, 0x39, 0x7a,
- 0xac, 0x69, 0x83, 0xdf, 0x6a, 0xd0, 0xf9, 0x2e, 0x91, 0xd1, 0x8f, 0xaf, 0x39, 0x8b, 0xb9, 0x22,
- 0x3e, 0x34, 0x57, 0x89, 0x56, 0x88, 0xb6, 0xa1, 0x13, 0x2e, 0xc6, 0x93, 0x45, 0x43, 0x73, 0x89,
- 0xbc, 0x84, 0xde, 0x4c, 0xf1, 0xb9, 0x90, 0x99, 0x0e, 0x87, 0xd6, 0x93, 0x65, 0x46, 0x6d, 0xad,
- 0xe6, 0x6e, 0x61, 0x82, 0xb1, 0x06, 0x31, 0x79, 0x02, 0x6d, 0x23, 0xa6, 0x5c, 0x1b, 0x36, 0x9d,
- 0x21, 0xd9, 0x3c, 0xba, 0x54, 0x90, 0x2f, 0xa1, 0x67, 0x14, 0x4b, 0x35, 0x8b, 0x6c, 0xa5, 0x3a,
- 0x54, 0x52, 0x1a, 0xbf, 0xbe, 0xe6, 0x73, 0xaf, 0x6c, 0x42, 0xa5, 0x34, 0xe4, 0x5b, 0xf8, 0x5f,
- 0x49, 0x17, 0x6a, 0xc3, 0x4c, 0xa6, 0xc3, 0x09, 0xd3, 0x13, 0xbf, 0xb1, 0x76, 0xf9, 0x61, 0xc9,
- 0xf0, 0x1a, 0xed, 0x70, 0x6a, 0x0f, 0xa0, 0x9e, 0xca, 0x34, 0xe2, 0x7e, 0x13, 0x53, 0xca, 0x05,
- 0x0b, 0xf0, 0x50, 0x18, 0xed, 0xb7, 0x50, 0x89, 0xdf, 0xe4, 0x02, 0xc8, 0x66, 0x2c, 0xbf, 0x8d,
- 0x61, 0x1e, 0xda, 0x30, 0x37, 0xeb, 0x01, 0x68, 0x6f, 0x23, 0x26, 0x79, 0xea, 0x7a, 0xe8, 0x03,
- 0x5e, 0x6c, 0x3b, 0xbe, 0xcb, 0x11, 0xcd, 0xf5, 0xc1, 0xaf, 0x15, 0x68, 0xdd, 0xdc, 0x7d, 0xb0,
- 0x39, 0x87, 0xd0, 0xd5, 0x5c, 0x09, 0x96, 0x88, 0x7b, 0x1e, 0x87, 0x5a, 0xdc, 0x73, 0xd7, 0xa5,
- 0xdd, 0xa5, 0xfa, 0x5a, 0xdc, 0x73, 0xbb, 0x4b, 0x2c, 0xcc, 0xa1, 0x62, 0xe9, 0x98, 0x3b, 0x4a,
- 0x21, 0xf0, 0xd4, 0x2a, 0xc8, 0x21, 0x80, 0xe2, 0x3a, 0x4b, 0xec, 0x78, 0x6b, 0xdf, 0x7b, 0x56,
- 0x5b, 0x01, 0xad, 0x9d, 0x9f, 0x0d, 0x62, 0x1d, 0x9c, 0xc0, 0xee, 0xcd, 0xdd, 0x2d, 0x57, 0x62,
- 0xf4, 0x96, 0xa2, 0x92, 0x3c, 0x85, 0x8e, 0x03, 0x7c, 0xc4, 0x44, 0x82, 0x09, 0xb6, 0x28, 0xe4,
- 0xaa, 0x57, 0x4c, 0x24, 0xc1, 0x08, 0x7a, 0x1b, 0x98, 0xbc, 0xa7, 0xa4, 0xaf, 0xe1, 0xc1, 0x1c,
- 0xfd, 0x17, 0xd8, 0x56, 0x31, 0x1b, 0x82, 0xd8, 0xae, 0x84, 0xa6, 0x3b, 0xb9, 0x61, 0xee, 0x32,
- 0xf8, 0xb3, 0x02, 0xb5, 0xcb, 0xec, 0x8e, 0x7c, 0x0e, 0x4d, 0x8d, 0xb3, 0xaf, 0xfd, 0x0a, 0x5e,
- 0xc5, 0x21, 0x2b, 0xed, 0x04, 0x5a, 0x9c, 0x93, 0xe7, 0xd0, 0x9c, 0x95, 0xc6, 0x64, 0x6d, 0xf1,
- 0x14, 0x67, 0xe4, 0x07, 0x38, 0xf8, 0x59, 0x98, 0x94, 0x6b, 0x1d, 0xc6, 0xcb, 0x39, 0xd7, 0x7e,
- 0x0d, 0xdd, 0x1f, 0x2c, 0xdc, 0x97, 0x96, 0x00, 0xdd, 0x77, 0x37, 0x4a, 0x3a, 0x4d, 0xbe, 0x80,
- 0x5e, 0xe1, 0x88, 0xa9, 0x71, 0x36, 0xe5, 0xa9, 0xc9, 0xd1, 0xde, 0xa1, 0x7b, 0xee, 0xe0, 0xac,
- 0xd0, 0x07, 0x12, 0x5a, 0xe7, 0x52, 0xa4, 0x43, 0xa6, 0x39, 0xf9, 0x1e, 0xf6, 0xb7, 0x64, 0xe0,
- 0x56, 0xcc, 0xf6, 0x04, 0xc8, 0x66, 0x02, 0x76, 0xfa, 0x98, 0x1a, 0x0a, 0xa3, 0x98, 0x7a, 0xeb,
- 0x16, 0xc3, 0x52, 0x11, 0xfc, 0x52, 0x81, 0xc6, 0x9b, 0xcc, 0xcc, 0x32, 0x43, 0x0e, 0xa1, 0x91,
- 0x63, 0xe4, 0x42, 0x6c, 0x40, 0xe8, 0x8e, 0xc9, 0x4b, 0xe8, 0xba, 0xcd, 0x12, 0xbe, 0x07, 0xc9,
- 0xb5, 0xed, 0x63, 0xbb, 0x2f, 0x55, 0x2c, 0x52, 0x96, 0x38, 0x2a, 0x16, 0x62, 0xf0, 0x06, 0x80,
- 0x72, 0x23, 0x14, 0xb7, 0x18, 0x7c, 0x7c, 0x1a, 0x25, 0x87, 0xd5, 0x55, 0x87, 0xbf, 0x57, 0xa1,
- 0x35, 0x70, 0x0f, 0x88, 0xa5, 0x39, 0x4e, 0x76, 0xbe, 0x1b, 0xd6, 0x17, 0x74, 0x1b, 0xcf, 0x70,
- 0x1f, 0x7c, 0xe4, 0x9a, 0x7e, 0x47, 0x5b, 0x6a, 0x9f, 0xd8, 0x96, 0x4b, 0xf0, 0x17, 0xb4, 0xc0,
- 0x37, 0x36, 0x5e, 0x3c, 0x92, 0xb8, 0x23, 0x3b, 0xfd, 0xfd, 0x45, 0x02, 0xcb, 0xf7, 0x93, 0x3e,
- 0x2a, 0x28, 0xb3, 0xf6, 0xae, 0x6e, 0x65, 0x59, 0x7d, 0x3b, 0xcb, 0xca, 0xc8, 0x35, 0x56, 0x91,
- 0xfb, 0xa3, 0x02, 0xf5, 0xeb, 0x19, 0x4f, 0x63, 0x72, 0x0c, 0x5d, 0x3d, 0xe3, 0xa9, 0x09, 0x25,
- 0xb2, 0x63, 0xf9, 0x0b, 0xb0, 0xc4, 0xee, 0x01, 0x1a, 0xe4, 0xec, 0x19, 0xc4, 0xef, 0x02, 0xa6,
- 0xfa, 0x89, 0xc0, 0x6c, 0xad, 0xa4, 0xf6, 0xe1, 0x4a, 0xbc, 0xd5, 0x4a, 0xfe, 0xaa, 0x40, 0xfd,
- 0x3c, 0x61, 0x62, 0xfa, 0x5f, 0xaf, 0x84, 0x04, 0xb0, 0x73, 0xc5, 0xc7, 0x22, 0x75, 0x57, 0x5c,
- 0x57, 0x57, 0x74, 0xc3, 0x06, 0xfe, 0x94, 0x9e, 0xfe, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x29,
- 0x9e, 0x4e, 0xa0, 0x0a, 0x00, 0x00,
+ // 999 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x57, 0xcb, 0x6e, 0x1b, 0x37,
+ 0x14, 0x85, 0x34, 0xa3, 0xd7, 0x95, 0x63, 0xd9, 0xb4, 0x93, 0x0e, 0x82, 0x14, 0x09, 0x06, 0x48,
+ 0xdc, 0xa2, 0x80, 0xe1, 0x47, 0xda, 0x6e, 0xba, 0xa8, 0x63, 0x37, 0x8d, 0x16, 0x46, 0x0c, 0xda,
+ 0xf0, 0x76, 0x40, 0xcd, 0x50, 0x32, 0xd1, 0xd1, 0x50, 0x25, 0x39, 0xaa, 0xed, 0x5d, 0x3e, 0xa2,
+ 0xcb, 0x7e, 0x47, 0x3f, 0xa1, 0xab, 0x7e, 0x49, 0x7f, 0xa2, 0xe0, 0x1d, 0x8e, 0x34, 0x92, 0x95,
+ 0x17, 0x8a, 0xa2, 0x28, 0x90, 0x9d, 0xee, 0xe1, 0xe5, 0x7d, 0x1c, 0x5e, 0x9e, 0xa1, 0xa0, 0x3d,
+ 0x88, 0x77, 0x27, 0x4a, 0x1a, 0x49, 0xea, 0x83, 0x38, 0x7c, 0x09, 0xfe, 0x2b, 0xa6, 0xaf, 0xc8,
+ 0x3a, 0xd4, 0xa7, 0x7b, 0x41, 0xed, 0x49, 0xed, 0x8b, 0x26, 0xad, 0x4f, 0xf7, 0xd0, 0xde, 0x0f,
+ 0xea, 0xce, 0xde, 0x47, 0xfb, 0x20, 0xf0, 0x9c, 0x7d, 0x80, 0xf6, 0x61, 0xe0, 0x3b, 0xfb, 0x30,
+ 0xfc, 0x0e, 0x5a, 0x67, 0x4a, 0x8e, 0x14, 0x1b, 0x93, 0xcf, 0x01, 0xa6, 0xe3, 0x68, 0xca, 0x95,
+ 0x16, 0x32, 0xc3, 0x90, 0x3e, 0xed, 0x4c, 0xc7, 0x97, 0x05, 0x40, 0x08, 0xf8, 0xb1, 0x4c, 0x38,
+ 0xc6, 0x5e, 0xa3, 0xf8, 0x3b, 0xec, 0x43, 0xeb, 0x48, 0x6b, 0x6e, 0xfa, 0x27, 0xff, 0xb8, 0x90,
+ 0x53, 0xe8, 0x62, 0xa8, 0xa3, 0xb1, 0xcc, 0x33, 0x43, 0x9e, 0x41, 0x9b, 0x59, 0x33, 0x12, 0x09,
+ 0x06, 0xed, 0x1e, 0x74, 0x77, 0x07, 0xf1, 0xae, 0xcb, 0x46, 0x5b, 0xb8, 0xd8, 0x4f, 0xc8, 0x03,
+ 0x68, 0x32, 0xdc, 0x81, 0xa9, 0x7c, 0xea, 0xac, 0x70, 0x04, 0x3d, 0xf4, 0x3d, 0xe1, 0x43, 0x91,
+ 0x09, 0x63, 0x1b, 0xf8, 0x06, 0x36, 0x84, 0xd6, 0x39, 0xcb, 0x62, 0x1e, 0x4d, 0x8a, 0x9e, 0xab,
+ 0xa1, 0x1d, 0x0d, 0xb4, 0x57, 0x3a, 0x95, 0xbc, 0x3c, 0x02, 0x3f, 0x61, 0x86, 0x61, 0x82, 0xee,
+ 0x41, 0xdb, 0xfa, 0x5a, 0xea, 0x29, 0xa2, 0x61, 0x0a, 0xdd, 0x4b, 0x96, 0xe6, 0xfc, 0x5c, 0xe6,
+ 0x2a, 0xe6, 0xe4, 0x21, 0x78, 0x8a, 0x0f, 0x5d, 0xdc, 0xb9, 0xaf, 0x05, 0xc9, 0x53, 0x68, 0x4c,
+ 0xad, 0xab, 0x8b, 0xd4, 0x9b, 0x35, 0x54, 0xf4, 0x4c, 0x8b, 0x55, 0xf2, 0x10, 0xda, 0x13, 0xa9,
+ 0xb1, 0x66, 0xe4, 0xcb, 0xa7, 0x33, 0x3b, 0xfc, 0x19, 0x36, 0x30, 0xdb, 0x09, 0xd7, 0x46, 0x64,
+ 0x0c, 0xfb, 0xfa, 0x97, 0x53, 0x1e, 0x43, 0xe3, 0x4c, 0x49, 0x39, 0xb4, 0x03, 0xa0, 0xc5, 0xa8,
+ 0x98, 0x8c, 0x35, 0x8a, 0xbf, 0xc9, 0x33, 0x58, 0x8f, 0x65, 0x66, 0x94, 0x4c, 0x1d, 0x5b, 0x6e,
+ 0x3c, 0x96, 0xd0, 0xf0, 0x8d, 0x07, 0x1b, 0x2f, 0x6e, 0x8c, 0x1c, 0xbf, 0x48, 0x65, 0xfc, 0xd3,
+ 0x2b, 0xce, 0x12, 0xae, 0x48, 0x00, 0xad, 0xc5, 0x69, 0x2b, 0x4d, 0x7b, 0xaa, 0x57, 0x5c, 0x8c,
+ 0xae, 0x66, 0xa7, 0x5a, 0x58, 0xe4, 0x39, 0x6c, 0x4e, 0x14, 0x9f, 0x0a, 0x99, 0xeb, 0x68, 0x60,
+ 0x23, 0xd9, 0xf1, 0xf0, 0x96, 0x1a, 0xef, 0x95, 0x2e, 0x98, 0xab, 0x9f, 0x90, 0x47, 0xd0, 0x31,
+ 0x62, 0xcc, 0xb5, 0x61, 0xe3, 0x09, 0x4e, 0x9c, 0x4f, 0xe7, 0x00, 0xf9, 0x1a, 0x36, 0x8d, 0x62,
+ 0x99, 0x66, 0xb1, 0x6d, 0x57, 0x47, 0x4a, 0x4a, 0x13, 0x34, 0x96, 0x62, 0x6e, 0x54, 0x5d, 0xa8,
+ 0x94, 0x86, 0x7c, 0x0f, 0x9f, 0x55, 0xb0, 0x48, 0x1b, 0x66, 0x72, 0x1d, 0x5d, 0x31, 0x7d, 0x15,
+ 0x34, 0x97, 0x36, 0xdf, 0xaf, 0x38, 0x9e, 0xa3, 0x1f, 0x5e, 0xdd, 0x6d, 0x68, 0x64, 0x32, 0x8b,
+ 0x79, 0xd0, 0xc2, 0x92, 0x0a, 0xc3, 0xb2, 0x3c, 0x10, 0x46, 0x07, 0x6d, 0x04, 0xf1, 0x37, 0x39,
+ 0x01, 0x72, 0x37, 0x57, 0xd0, 0xc1, 0x34, 0xf7, 0x6d, 0x9a, 0x8b, 0xe5, 0x04, 0x74, 0xf3, 0x4e,
+ 0xce, 0xf0, 0x37, 0x0f, 0xba, 0x9f, 0xe8, 0xff, 0xaf, 0xe8, 0x27, 0x8f, 0xdd, 0x3d, 0x0a, 0x00,
+ 0x37, 0x76, 0x9c, 0xe6, 0xc8, 0x21, 0x2d, 0xf0, 0xf0, 0xd7, 0x1a, 0xb4, 0x2f, 0xae, 0xdf, 0x7b,
+ 0x38, 0x3b, 0xd0, 0xd3, 0x5c, 0x09, 0x96, 0x8a, 0x5b, 0x9e, 0x44, 0x5a, 0xdc, 0x72, 0x77, 0x4a,
+ 0xeb, 0x73, 0xf8, 0x5c, 0xdc, 0x72, 0xab, 0xe7, 0x96, 0xe6, 0x48, 0xb1, 0x6c, 0xc4, 0xdd, 0xb5,
+ 0x46, 0xe2, 0xa9, 0x05, 0xc8, 0x0e, 0x80, 0xe2, 0x3a, 0x4f, 0xad, 0xc4, 0xea, 0xc0, 0x7f, 0xe2,
+ 0x2d, 0x90, 0xd6, 0x29, 0xd6, 0xfa, 0x89, 0x0e, 0xf7, 0x61, 0xfd, 0xe2, 0xfa, 0x92, 0x2b, 0x31,
+ 0xbc, 0xa1, 0x08, 0x92, 0xc7, 0xd0, 0x75, 0x84, 0x0f, 0x99, 0x48, 0xb1, 0xc0, 0x36, 0x85, 0x02,
+ 0x7a, 0xc9, 0x44, 0x1a, 0x0e, 0x61, 0xf3, 0x0e, 0x27, 0xef, 0x68, 0xe9, 0x5b, 0xb8, 0x37, 0xc5,
+ 0xf8, 0x25, 0xb7, 0x75, 0xac, 0x86, 0x20, 0xb7, 0x0b, 0xa9, 0xe9, 0x5a, 0xe1, 0xe8, 0x46, 0xfa,
+ 0xcf, 0x1a, 0x78, 0xa7, 0xf9, 0x35, 0xf9, 0x12, 0x5a, 0x1a, 0xf5, 0x57, 0x07, 0x35, 0xdc, 0x8a,
+ 0x42, 0x57, 0xd1, 0x65, 0x5a, 0xae, 0x93, 0xa7, 0xd0, 0x9a, 0x54, 0xa4, 0x6a, 0x49, 0xfc, 0xcb,
+ 0x35, 0xf2, 0x23, 0x6c, 0xff, 0x22, 0x4c, 0xc6, 0xb5, 0x8e, 0x92, 0xb9, 0xd6, 0xea, 0xc0, 0xc3,
+ 0xf0, 0xdb, 0xb3, 0xf0, 0x15, 0x21, 0xa6, 0x5b, 0x6e, 0x47, 0x05, 0xd3, 0xe4, 0x2b, 0xd8, 0x2c,
+ 0x03, 0x31, 0x35, 0xca, 0xc7, 0x3c, 0x33, 0x05, 0xdb, 0x6b, 0x74, 0xc3, 0x2d, 0x1c, 0x95, 0x78,
+ 0x28, 0xa1, 0x7d, 0x2c, 0x45, 0x36, 0x60, 0x9a, 0x93, 0x1f, 0x60, 0x6b, 0x45, 0x05, 0x4e, 0xe6,
+ 0x57, 0x17, 0x40, 0xee, 0x16, 0x60, 0x6f, 0x1f, 0x53, 0x03, 0x61, 0x14, 0x53, 0x37, 0x4e, 0x9c,
+ 0xe7, 0x40, 0xf8, 0xa6, 0x06, 0xcd, 0xd7, 0xb9, 0x99, 0xe4, 0x86, 0xec, 0x40, 0xb3, 0xe0, 0xc8,
+ 0xa5, 0xb8, 0x43, 0xa1, 0x5b, 0x26, 0xcf, 0xa1, 0xe7, 0xd4, 0x3d, 0x7a, 0x07, 0x93, 0x4b, 0x5f,
+ 0x00, 0x7b, 0xfa, 0x52, 0x25, 0x22, 0x63, 0xa9, 0x1b, 0xc5, 0xd2, 0x0c, 0x5f, 0x03, 0x50, 0x6e,
+ 0x84, 0xe2, 0x96, 0x83, 0x0f, 0x2f, 0xa3, 0x12, 0xb0, 0xbe, 0x18, 0xf0, 0xf7, 0x3a, 0xb4, 0xfb,
+ 0xee, 0x23, 0x6e, 0xc7, 0x1c, 0x6f, 0x76, 0xa1, 0x0d, 0xcb, 0x1f, 0xc9, 0x0e, 0xae, 0xa1, 0x1e,
+ 0x7c, 0xe0, 0xa7, 0xf2, 0x2d, 0xc7, 0xe2, 0x7d, 0xe4, 0xb1, 0x9c, 0x42, 0x30, 0x1b, 0x0b, 0x7c,
+ 0xe7, 0x24, 0xb3, 0x87, 0x0a, 0x6a, 0x64, 0xf7, 0x60, 0x6b, 0x56, 0xc0, 0xfc, 0x0d, 0x43, 0x1f,
+ 0x94, 0x23, 0xb3, 0xf4, 0xb6, 0x59, 0x39, 0x65, 0x8d, 0xd5, 0x53, 0x56, 0x65, 0xae, 0xb9, 0xc8,
+ 0xdc, 0x1f, 0x35, 0x68, 0x9c, 0x4f, 0x78, 0x96, 0x90, 0x3d, 0xe8, 0xe9, 0x09, 0xcf, 0x4c, 0x24,
+ 0x71, 0x3a, 0xe6, 0xcf, 0xb0, 0x39, 0x77, 0xf7, 0xd0, 0xa1, 0x98, 0x9e, 0x7e, 0xf2, 0x36, 0x62,
+ 0xea, 0x1f, 0x49, 0xcc, 0xca, 0x4e, 0xbc, 0xf7, 0x77, 0xe2, 0x2f, 0x76, 0xf2, 0x57, 0x0d, 0x1a,
+ 0xc7, 0x29, 0x13, 0xe3, 0xff, 0x7b, 0x27, 0x24, 0x84, 0xb5, 0x33, 0x3e, 0x12, 0x99, 0xdb, 0xe2,
+ 0x4e, 0x75, 0x01, 0x1b, 0x34, 0xf1, 0x8f, 0xc1, 0xe1, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x9d,
+ 0xe4, 0x01, 0xce, 0x24, 0x0c, 0x00, 0x00,
}
bytes controlProgram = 2;
}
+message BytomBlockHeader {
+ uint64 version = 1;
+ uint64 height = 2;
+ Hash previous_block_id = 3;
+ uint64 timestamp = 4;
+ Hash transactions_root = 5;
+ Hash transaction_status_hash = 6;
+ uint64 nonce = 7;
+ uint64 bits = 8;
+ TransactionStatus transaction_status = 9;
+}
+
message BlockHeader {
uint64 version = 1;
uint64 height = 2;
-package bytom
+package bc
import "io"
-// BlockHeader contains the header information for a blockchain
-// block. It satisfies the Entry interface.
-
-func (BlockHeader) typ() string { return "blockheader" }
-func (bh *BlockHeader) writeForHash(w io.Writer) {
+func (BytomBlockHeader) typ() string { return "blockheader" }
+func (bh *BytomBlockHeader) writeForHash(w io.Writer) {
mustWriteForHash(w, bh.Version)
mustWriteForHash(w, bh.Height)
mustWriteForHash(w, bh.PreviousBlockId)
mustWriteForHash(w, bh.Nonce)
}
-// NewBlockHeader creates a new BlockHeader and populates
+// NewBytomBlockHeader creates a new BlockHeader and populates
// its body.
-func NewBlockHeader(version, height uint64, previousBlockID *Hash, timestamp uint64, transactionsRoot, transactionStatusHash *Hash, nonce, bits uint64) *BlockHeader {
- return &BlockHeader{
+func NewBytomBlockHeader(version, height uint64, previousBlockID *Hash, timestamp uint64, transactionsRoot, transactionStatusHash *Hash, nonce, bits uint64) *BytomBlockHeader {
+ return &BytomBlockHeader{
Version: version,
Height: height,
PreviousBlockId: previousBlockID,
+++ /dev/null
-package bytom
-
-import (
- "encoding/binary"
- "errors"
- "io"
-
- "github.com/vapor/crypto/sha3pool"
- "github.com/vapor/encoding/blockchain"
-)
-
-// NewAssetID convert byte array to aseet id
-func NewAssetID(b [32]byte) (a AssetID) {
- return AssetID{
- V0: binary.BigEndian.Uint64(b[0:8]),
- V1: binary.BigEndian.Uint64(b[8:16]),
- V2: binary.BigEndian.Uint64(b[16:24]),
- V3: binary.BigEndian.Uint64(b[24:32]),
- }
-}
-
-// Byte32 return the byte array representation
-func (a AssetID) Byte32() (b32 [32]byte) { return Hash(a).Byte32() }
-
-// MarshalText satisfies the TextMarshaler interface.
-func (a AssetID) MarshalText() ([]byte, error) { return Hash(a).MarshalText() }
-
-// UnmarshalText satisfies the TextUnmarshaler interface.
-func (a *AssetID) UnmarshalText(b []byte) error { return (*Hash)(a).UnmarshalText(b) }
-
-// UnmarshalJSON satisfies the json.Unmarshaler interface.
-func (a *AssetID) UnmarshalJSON(b []byte) error { return (*Hash)(a).UnmarshalJSON(b) }
-
-// Bytes returns the byte representation.
-func (a AssetID) Bytes() []byte { return Hash(a).Bytes() }
-
-// WriteTo satisfies the io.WriterTo interface.
-func (a AssetID) WriteTo(w io.Writer) (int64, error) { return Hash(a).WriteTo(w) }
-
-// ReadFrom satisfies the io.ReaderFrom interface.
-func (a *AssetID) ReadFrom(r io.Reader) (int64, error) { return (*Hash)(a).ReadFrom(r) }
-
-// IsZero tells whether a Asset pointer is nil or points to an all-zero hash.
-func (a *AssetID) IsZero() bool { return (*Hash)(a).IsZero() }
-
-// ComputeAssetID calculate the asset id from AssetDefinition
-func (ad *AssetDefinition) ComputeAssetID() (assetID AssetID) {
- h := sha3pool.Get256()
- defer sha3pool.Put256(h)
- writeForHash(h, *ad) // error is impossible
- var b [32]byte
- h.Read(b[:]) // error is impossible
- return NewAssetID(b)
-}
-
-// ComputeAssetID implement the assetID calculate logic
-func ComputeAssetID(prog []byte, vmVersion uint64, data *Hash) AssetID {
- def := &AssetDefinition{
- IssuanceProgram: &Program{
- VmVersion: vmVersion,
- Code: prog,
- },
- Data: data,
- }
- return def.ComputeAssetID()
-}
-
-// ReadFrom read the AssetAmount from the bytes
-func (a *AssetAmount) ReadFrom(r *blockchain.Reader) (err error) {
- var assetID AssetID
- if _, err = assetID.ReadFrom(r); err != nil {
- return err
- }
- a.AssetId = &assetID
- a.Amount, err = blockchain.ReadVarint63(r)
- return err
-}
-
-// WriteTo convert struct to byte and write to io
-func (a AssetAmount) WriteTo(w io.Writer) (int64, error) {
- n, err := a.AssetId.WriteTo(w)
- if err != nil {
- return n, err
- }
- n2, err := blockchain.WriteVarint63(w, a.Amount)
- return n + int64(n2), err
-}
-
-// Equal check does two AssetAmount have same assetID and amount
-func (a *AssetAmount) Equal(other *AssetAmount) (eq bool, err error) {
- if a == nil || other == nil {
- return false, errors.New("empty asset amount")
- }
- if a.AssetId == nil || other.AssetId == nil {
- return false, errors.New("empty asset id")
- }
- return a.Amount == other.Amount && *a.AssetId == *other.AssetId, nil
-}
+++ /dev/null
-package bytom
-
-import (
- "testing"
-
- "golang.org/x/crypto/sha3"
-)
-
-func TestComputeAssetID(t *testing.T) {
- issuanceScript := []byte{1}
- assetID := ComputeAssetID(issuanceScript, 1, &EmptyStringHash)
-
- unhashed := append([]byte{})
- unhashed = append(unhashed, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}...) // vmVersion
- unhashed = append(unhashed, 0x01) // length of issuanceScript
- unhashed = append(unhashed, issuanceScript...)
- unhashed = append(unhashed, EmptyStringHash.Bytes()...)
-
- if want := NewAssetID(sha3.Sum256(unhashed)); assetID != want {
- t.Errorf("asset id = %x want %x", assetID.Bytes(), want.Bytes())
- }
-}
-
-var assetIDSink AssetID
-
-func BenchmarkComputeAssetID(b *testing.B) {
- var (
- issuanceScript = []byte{5}
- )
-
- for i := 0; i < b.N; i++ {
- assetIDSink = ComputeAssetID(issuanceScript, 1, &EmptyStringHash)
- }
-}
+++ /dev/null
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// source: bc.proto
-
-/*
-Package bytom is a generated protocol buffer package.
-
-It is generated from these files:
- bc.proto
-
-It has these top-level messages:
- Hash
- Program
- AssetID
- AssetAmount
- AssetDefinition
- ValueSource
- ValueDestination
- BlockHeader
- TxHeader
- TxVerifyResult
- TransactionStatus
- Mux
- Coinbase
- Output
- Retirement
- Issuance
- Spend
-*/
-package bytom
-
-import proto "github.com/golang/protobuf/proto"
-import fmt "fmt"
-import math "math"
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-type Hash struct {
- V0 uint64 `protobuf:"fixed64,1,opt,name=v0" json:"v0,omitempty"`
- V1 uint64 `protobuf:"fixed64,2,opt,name=v1" json:"v1,omitempty"`
- V2 uint64 `protobuf:"fixed64,3,opt,name=v2" json:"v2,omitempty"`
- V3 uint64 `protobuf:"fixed64,4,opt,name=v3" json:"v3,omitempty"`
-}
-
-func (m *Hash) Reset() { *m = Hash{} }
-func (m *Hash) String() string { return proto.CompactTextString(m) }
-func (*Hash) ProtoMessage() {}
-func (*Hash) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
-
-func (m *Hash) GetV0() uint64 {
- if m != nil {
- return m.V0
- }
- return 0
-}
-
-func (m *Hash) GetV1() uint64 {
- if m != nil {
- return m.V1
- }
- return 0
-}
-
-func (m *Hash) GetV2() uint64 {
- if m != nil {
- return m.V2
- }
- return 0
-}
-
-func (m *Hash) GetV3() uint64 {
- if m != nil {
- return m.V3
- }
- return 0
-}
-
-type Program struct {
- VmVersion uint64 `protobuf:"varint,1,opt,name=vm_version,json=vmVersion" json:"vm_version,omitempty"`
- Code []byte `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
-}
-
-func (m *Program) Reset() { *m = Program{} }
-func (m *Program) String() string { return proto.CompactTextString(m) }
-func (*Program) ProtoMessage() {}
-func (*Program) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
-
-func (m *Program) GetVmVersion() uint64 {
- if m != nil {
- return m.VmVersion
- }
- return 0
-}
-
-func (m *Program) GetCode() []byte {
- if m != nil {
- return m.Code
- }
- return nil
-}
-
-// This message type duplicates Hash, above. One alternative is to
-// embed a Hash inside an AssetID. But it's useful for AssetID to be
-// plain old data (without pointers). Another alternative is use Hash
-// in any protobuf types where an AssetID is called for, but it's
-// preferable to have type safety.
-type AssetID struct {
- V0 uint64 `protobuf:"fixed64,1,opt,name=v0" json:"v0,omitempty"`
- V1 uint64 `protobuf:"fixed64,2,opt,name=v1" json:"v1,omitempty"`
- V2 uint64 `protobuf:"fixed64,3,opt,name=v2" json:"v2,omitempty"`
- V3 uint64 `protobuf:"fixed64,4,opt,name=v3" json:"v3,omitempty"`
-}
-
-func (m *AssetID) Reset() { *m = AssetID{} }
-func (m *AssetID) String() string { return proto.CompactTextString(m) }
-func (*AssetID) ProtoMessage() {}
-func (*AssetID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
-
-func (m *AssetID) GetV0() uint64 {
- if m != nil {
- return m.V0
- }
- return 0
-}
-
-func (m *AssetID) GetV1() uint64 {
- if m != nil {
- return m.V1
- }
- return 0
-}
-
-func (m *AssetID) GetV2() uint64 {
- if m != nil {
- return m.V2
- }
- return 0
-}
-
-func (m *AssetID) GetV3() uint64 {
- if m != nil {
- return m.V3
- }
- return 0
-}
-
-type AssetAmount struct {
- AssetId *AssetID `protobuf:"bytes,1,opt,name=asset_id,json=assetId" json:"asset_id,omitempty"`
- Amount uint64 `protobuf:"varint,2,opt,name=amount" json:"amount,omitempty"`
-}
-
-func (m *AssetAmount) Reset() { *m = AssetAmount{} }
-func (m *AssetAmount) String() string { return proto.CompactTextString(m) }
-func (*AssetAmount) ProtoMessage() {}
-func (*AssetAmount) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
-
-func (m *AssetAmount) GetAssetId() *AssetID {
- if m != nil {
- return m.AssetId
- }
- return nil
-}
-
-func (m *AssetAmount) GetAmount() uint64 {
- if m != nil {
- return m.Amount
- }
- return 0
-}
-
-type AssetDefinition struct {
- IssuanceProgram *Program `protobuf:"bytes,1,opt,name=issuance_program,json=issuanceProgram" json:"issuance_program,omitempty"`
- Data *Hash `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
-}
-
-func (m *AssetDefinition) Reset() { *m = AssetDefinition{} }
-func (m *AssetDefinition) String() string { return proto.CompactTextString(m) }
-func (*AssetDefinition) ProtoMessage() {}
-func (*AssetDefinition) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
-
-func (m *AssetDefinition) GetIssuanceProgram() *Program {
- if m != nil {
- return m.IssuanceProgram
- }
- return nil
-}
-
-func (m *AssetDefinition) GetData() *Hash {
- if m != nil {
- return m.Data
- }
- return nil
-}
-
-type ValueSource struct {
- Ref *Hash `protobuf:"bytes,1,opt,name=ref" json:"ref,omitempty"`
- Value *AssetAmount `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
- Position uint64 `protobuf:"varint,3,opt,name=position" json:"position,omitempty"`
-}
-
-func (m *ValueSource) Reset() { *m = ValueSource{} }
-func (m *ValueSource) String() string { return proto.CompactTextString(m) }
-func (*ValueSource) ProtoMessage() {}
-func (*ValueSource) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
-
-func (m *ValueSource) GetRef() *Hash {
- if m != nil {
- return m.Ref
- }
- return nil
-}
-
-func (m *ValueSource) GetValue() *AssetAmount {
- if m != nil {
- return m.Value
- }
- return nil
-}
-
-func (m *ValueSource) GetPosition() uint64 {
- if m != nil {
- return m.Position
- }
- return 0
-}
-
-type ValueDestination struct {
- Ref *Hash `protobuf:"bytes,1,opt,name=ref" json:"ref,omitempty"`
- Value *AssetAmount `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
- Position uint64 `protobuf:"varint,3,opt,name=position" json:"position,omitempty"`
-}
-
-func (m *ValueDestination) Reset() { *m = ValueDestination{} }
-func (m *ValueDestination) String() string { return proto.CompactTextString(m) }
-func (*ValueDestination) ProtoMessage() {}
-func (*ValueDestination) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
-
-func (m *ValueDestination) GetRef() *Hash {
- if m != nil {
- return m.Ref
- }
- return nil
-}
-
-func (m *ValueDestination) GetValue() *AssetAmount {
- if m != nil {
- return m.Value
- }
- return nil
-}
-
-func (m *ValueDestination) GetPosition() uint64 {
- if m != nil {
- return m.Position
- }
- return 0
-}
-
-type BlockHeader struct {
- Version uint64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
- Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"`
- PreviousBlockId *Hash `protobuf:"bytes,3,opt,name=previous_block_id,json=previousBlockId" json:"previous_block_id,omitempty"`
- Timestamp uint64 `protobuf:"varint,4,opt,name=timestamp" json:"timestamp,omitempty"`
- TransactionsRoot *Hash `protobuf:"bytes,5,opt,name=transactions_root,json=transactionsRoot" json:"transactions_root,omitempty"`
- TransactionStatusHash *Hash `protobuf:"bytes,6,opt,name=transaction_status_hash,json=transactionStatusHash" json:"transaction_status_hash,omitempty"`
- Nonce uint64 `protobuf:"varint,7,opt,name=nonce" json:"nonce,omitempty"`
- Bits uint64 `protobuf:"varint,8,opt,name=bits" json:"bits,omitempty"`
- TransactionStatus *TransactionStatus `protobuf:"bytes,9,opt,name=transaction_status,json=transactionStatus" json:"transaction_status,omitempty"`
-}
-
-func (m *BlockHeader) Reset() { *m = BlockHeader{} }
-func (m *BlockHeader) String() string { return proto.CompactTextString(m) }
-func (*BlockHeader) ProtoMessage() {}
-func (*BlockHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
-
-func (m *BlockHeader) GetVersion() uint64 {
- if m != nil {
- return m.Version
- }
- return 0
-}
-
-func (m *BlockHeader) GetHeight() uint64 {
- if m != nil {
- return m.Height
- }
- return 0
-}
-
-func (m *BlockHeader) GetPreviousBlockId() *Hash {
- if m != nil {
- return m.PreviousBlockId
- }
- return nil
-}
-
-func (m *BlockHeader) GetTimestamp() uint64 {
- if m != nil {
- return m.Timestamp
- }
- return 0
-}
-
-func (m *BlockHeader) GetTransactionsRoot() *Hash {
- if m != nil {
- return m.TransactionsRoot
- }
- return nil
-}
-
-func (m *BlockHeader) GetTransactionStatusHash() *Hash {
- if m != nil {
- return m.TransactionStatusHash
- }
- return nil
-}
-
-func (m *BlockHeader) GetNonce() uint64 {
- if m != nil {
- return m.Nonce
- }
- return 0
-}
-
-func (m *BlockHeader) GetBits() uint64 {
- if m != nil {
- return m.Bits
- }
- return 0
-}
-
-func (m *BlockHeader) GetTransactionStatus() *TransactionStatus {
- if m != nil {
- return m.TransactionStatus
- }
- return nil
-}
-
-type TxHeader struct {
- Version uint64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
- SerializedSize uint64 `protobuf:"varint,2,opt,name=serialized_size,json=serializedSize" json:"serialized_size,omitempty"`
- TimeRange uint64 `protobuf:"varint,3,opt,name=time_range,json=timeRange" json:"time_range,omitempty"`
- ResultIds []*Hash `protobuf:"bytes,4,rep,name=result_ids,json=resultIds" json:"result_ids,omitempty"`
-}
-
-func (m *TxHeader) Reset() { *m = TxHeader{} }
-func (m *TxHeader) String() string { return proto.CompactTextString(m) }
-func (*TxHeader) ProtoMessage() {}
-func (*TxHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
-
-func (m *TxHeader) GetVersion() uint64 {
- if m != nil {
- return m.Version
- }
- return 0
-}
-
-func (m *TxHeader) GetSerializedSize() uint64 {
- if m != nil {
- return m.SerializedSize
- }
- return 0
-}
-
-func (m *TxHeader) GetTimeRange() uint64 {
- if m != nil {
- return m.TimeRange
- }
- return 0
-}
-
-func (m *TxHeader) GetResultIds() []*Hash {
- if m != nil {
- return m.ResultIds
- }
- return nil
-}
-
-type TxVerifyResult struct {
- StatusFail bool `protobuf:"varint,1,opt,name=status_fail,json=statusFail" json:"status_fail,omitempty"`
-}
-
-func (m *TxVerifyResult) Reset() { *m = TxVerifyResult{} }
-func (m *TxVerifyResult) String() string { return proto.CompactTextString(m) }
-func (*TxVerifyResult) ProtoMessage() {}
-func (*TxVerifyResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
-
-func (m *TxVerifyResult) GetStatusFail() bool {
- if m != nil {
- return m.StatusFail
- }
- return false
-}
-
-type TransactionStatus struct {
- Version uint64 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
- VerifyStatus []*TxVerifyResult `protobuf:"bytes,2,rep,name=verify_status,json=verifyStatus" json:"verify_status,omitempty"`
-}
-
-func (m *TransactionStatus) Reset() { *m = TransactionStatus{} }
-func (m *TransactionStatus) String() string { return proto.CompactTextString(m) }
-func (*TransactionStatus) ProtoMessage() {}
-func (*TransactionStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
-
-func (m *TransactionStatus) GetVersion() uint64 {
- if m != nil {
- return m.Version
- }
- return 0
-}
-
-func (m *TransactionStatus) GetVerifyStatus() []*TxVerifyResult {
- if m != nil {
- return m.VerifyStatus
- }
- return nil
-}
-
-type Mux struct {
- Sources []*ValueSource `protobuf:"bytes,1,rep,name=sources" json:"sources,omitempty"`
- Program *Program `protobuf:"bytes,2,opt,name=program" json:"program,omitempty"`
- WitnessDestinations []*ValueDestination `protobuf:"bytes,3,rep,name=witness_destinations,json=witnessDestinations" json:"witness_destinations,omitempty"`
- WitnessArguments [][]byte `protobuf:"bytes,4,rep,name=witness_arguments,json=witnessArguments,proto3" json:"witness_arguments,omitempty"`
-}
-
-func (m *Mux) Reset() { *m = Mux{} }
-func (m *Mux) String() string { return proto.CompactTextString(m) }
-func (*Mux) ProtoMessage() {}
-func (*Mux) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
-
-func (m *Mux) GetSources() []*ValueSource {
- if m != nil {
- return m.Sources
- }
- return nil
-}
-
-func (m *Mux) GetProgram() *Program {
- if m != nil {
- return m.Program
- }
- return nil
-}
-
-func (m *Mux) GetWitnessDestinations() []*ValueDestination {
- if m != nil {
- return m.WitnessDestinations
- }
- return nil
-}
-
-func (m *Mux) GetWitnessArguments() [][]byte {
- if m != nil {
- return m.WitnessArguments
- }
- return nil
-}
-
-type Coinbase struct {
- WitnessDestination *ValueDestination `protobuf:"bytes,1,opt,name=witness_destination,json=witnessDestination" json:"witness_destination,omitempty"`
- Arbitrary []byte `protobuf:"bytes,2,opt,name=arbitrary,proto3" json:"arbitrary,omitempty"`
-}
-
-func (m *Coinbase) Reset() { *m = Coinbase{} }
-func (m *Coinbase) String() string { return proto.CompactTextString(m) }
-func (*Coinbase) ProtoMessage() {}
-func (*Coinbase) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
-
-func (m *Coinbase) GetWitnessDestination() *ValueDestination {
- if m != nil {
- return m.WitnessDestination
- }
- return nil
-}
-
-func (m *Coinbase) GetArbitrary() []byte {
- if m != nil {
- return m.Arbitrary
- }
- return nil
-}
-
-type Output struct {
- Source *ValueSource `protobuf:"bytes,1,opt,name=source" json:"source,omitempty"`
- ControlProgram *Program `protobuf:"bytes,2,opt,name=control_program,json=controlProgram" json:"control_program,omitempty"`
- Ordinal uint64 `protobuf:"varint,3,opt,name=ordinal" json:"ordinal,omitempty"`
-}
-
-func (m *Output) Reset() { *m = Output{} }
-func (m *Output) String() string { return proto.CompactTextString(m) }
-func (*Output) ProtoMessage() {}
-func (*Output) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
-
-func (m *Output) GetSource() *ValueSource {
- if m != nil {
- return m.Source
- }
- return nil
-}
-
-func (m *Output) GetControlProgram() *Program {
- if m != nil {
- return m.ControlProgram
- }
- return nil
-}
-
-func (m *Output) GetOrdinal() uint64 {
- if m != nil {
- return m.Ordinal
- }
- return 0
-}
-
-type Retirement struct {
- Source *ValueSource `protobuf:"bytes,1,opt,name=source" json:"source,omitempty"`
- Ordinal uint64 `protobuf:"varint,2,opt,name=ordinal" json:"ordinal,omitempty"`
-}
-
-func (m *Retirement) Reset() { *m = Retirement{} }
-func (m *Retirement) String() string { return proto.CompactTextString(m) }
-func (*Retirement) ProtoMessage() {}
-func (*Retirement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
-
-func (m *Retirement) GetSource() *ValueSource {
- if m != nil {
- return m.Source
- }
- return nil
-}
-
-func (m *Retirement) GetOrdinal() uint64 {
- if m != nil {
- return m.Ordinal
- }
- return 0
-}
-
-type Issuance struct {
- NonceHash *Hash `protobuf:"bytes,1,opt,name=nonce_hash,json=nonceHash" json:"nonce_hash,omitempty"`
- Value *AssetAmount `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
- WitnessDestination *ValueDestination `protobuf:"bytes,3,opt,name=witness_destination,json=witnessDestination" json:"witness_destination,omitempty"`
- WitnessAssetDefinition *AssetDefinition `protobuf:"bytes,4,opt,name=witness_asset_definition,json=witnessAssetDefinition" json:"witness_asset_definition,omitempty"`
- WitnessArguments [][]byte `protobuf:"bytes,5,rep,name=witness_arguments,json=witnessArguments,proto3" json:"witness_arguments,omitempty"`
- Ordinal uint64 `protobuf:"varint,6,opt,name=ordinal" json:"ordinal,omitempty"`
-}
-
-func (m *Issuance) Reset() { *m = Issuance{} }
-func (m *Issuance) String() string { return proto.CompactTextString(m) }
-func (*Issuance) ProtoMessage() {}
-func (*Issuance) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
-
-func (m *Issuance) GetNonceHash() *Hash {
- if m != nil {
- return m.NonceHash
- }
- return nil
-}
-
-func (m *Issuance) GetValue() *AssetAmount {
- if m != nil {
- return m.Value
- }
- return nil
-}
-
-func (m *Issuance) GetWitnessDestination() *ValueDestination {
- if m != nil {
- return m.WitnessDestination
- }
- return nil
-}
-
-func (m *Issuance) GetWitnessAssetDefinition() *AssetDefinition {
- if m != nil {
- return m.WitnessAssetDefinition
- }
- return nil
-}
-
-func (m *Issuance) GetWitnessArguments() [][]byte {
- if m != nil {
- return m.WitnessArguments
- }
- return nil
-}
-
-func (m *Issuance) GetOrdinal() uint64 {
- if m != nil {
- return m.Ordinal
- }
- return 0
-}
-
-type Spend 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"`
-}
-
-func (m *Spend) Reset() { *m = Spend{} }
-func (m *Spend) String() string { return proto.CompactTextString(m) }
-func (*Spend) ProtoMessage() {}
-func (*Spend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
-
-func (m *Spend) GetSpentOutputId() *Hash {
- if m != nil {
- return m.SpentOutputId
- }
- return nil
-}
-
-func (m *Spend) GetWitnessDestination() *ValueDestination {
- if m != nil {
- return m.WitnessDestination
- }
- return nil
-}
-
-func (m *Spend) GetWitnessArguments() [][]byte {
- if m != nil {
- return m.WitnessArguments
- }
- return nil
-}
-
-func (m *Spend) GetOrdinal() uint64 {
- if m != nil {
- return m.Ordinal
- }
- return 0
-}
-
-func init() {
- proto.RegisterType((*Hash)(nil), "bytom.Hash")
- proto.RegisterType((*Program)(nil), "bytom.Program")
- proto.RegisterType((*AssetID)(nil), "bytom.AssetID")
- proto.RegisterType((*AssetAmount)(nil), "bytom.AssetAmount")
- proto.RegisterType((*AssetDefinition)(nil), "bytom.AssetDefinition")
- proto.RegisterType((*ValueSource)(nil), "bytom.ValueSource")
- proto.RegisterType((*ValueDestination)(nil), "bytom.ValueDestination")
- proto.RegisterType((*BlockHeader)(nil), "bytom.BlockHeader")
- proto.RegisterType((*TxHeader)(nil), "bytom.TxHeader")
- proto.RegisterType((*TxVerifyResult)(nil), "bytom.TxVerifyResult")
- proto.RegisterType((*TransactionStatus)(nil), "bytom.TransactionStatus")
- proto.RegisterType((*Mux)(nil), "bytom.Mux")
- proto.RegisterType((*Coinbase)(nil), "bytom.Coinbase")
- proto.RegisterType((*Output)(nil), "bytom.Output")
- proto.RegisterType((*Retirement)(nil), "bytom.Retirement")
- proto.RegisterType((*Issuance)(nil), "bytom.Issuance")
- proto.RegisterType((*Spend)(nil), "bytom.Spend")
-}
-
-func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
-
-var fileDescriptor0 = []byte{
- // 916 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6e, 0x1b, 0x37,
- 0x10, 0x86, 0xb4, 0xab, 0xbf, 0x91, 0x23, 0x59, 0x4c, 0xe2, 0x2c, 0x8a, 0x06, 0x09, 0xf6, 0x52,
- 0x37, 0x2d, 0x8c, 0x58, 0x3e, 0xa4, 0x2d, 0x7a, 0x71, 0x63, 0xa4, 0x56, 0x81, 0xa2, 0x06, 0x6d,
- 0xf8, 0xba, 0xa0, 0xb4, 0xb4, 0x45, 0x54, 0x4b, 0x0a, 0x24, 0x57, 0xb1, 0xfd, 0x02, 0xed, 0x23,
- 0xf4, 0x7d, 0x7a, 0xee, 0xb5, 0xcf, 0x53, 0x70, 0x96, 0x6b, 0xad, 0x2c, 0x39, 0xae, 0x51, 0xa0,
- 0x37, 0xcd, 0x70, 0x76, 0xbe, 0x99, 0x6f, 0xfe, 0x04, 0xed, 0xf1, 0x64, 0x6f, 0xae, 0x95, 0x55,
- 0xa4, 0x31, 0xbe, 0xb6, 0x2a, 0x8b, 0x3f, 0x40, 0x78, 0xcc, 0xcc, 0x94, 0xf4, 0xa0, 0xbe, 0x78,
- 0x1b, 0xd5, 0x5e, 0xd7, 0x76, 0x9b, 0xb4, 0xbe, 0x78, 0x8b, 0xf2, 0x7e, 0x54, 0xf7, 0xf2, 0x3e,
- 0xca, 0xc3, 0x28, 0xf0, 0xf2, 0x10, 0xe5, 0x83, 0x28, 0xf4, 0xf2, 0x41, 0xfc, 0x3d, 0xb4, 0x4e,
- 0xb4, 0xba, 0xd4, 0x2c, 0x23, 0x2f, 0x01, 0x16, 0x59, 0xb2, 0xe0, 0xda, 0x08, 0x25, 0xd1, 0x65,
- 0x48, 0x3b, 0x8b, 0xec, 0xbc, 0x50, 0x10, 0x02, 0xe1, 0x44, 0xa5, 0x1c, 0x7d, 0x6f, 0x51, 0xfc,
- 0x1d, 0x8f, 0xa0, 0x75, 0x68, 0x0c, 0xb7, 0xa3, 0xa3, 0xff, 0x1c, 0xc8, 0x09, 0x74, 0xd1, 0xd5,
- 0x61, 0xa6, 0x72, 0x69, 0xc9, 0x97, 0xd0, 0x66, 0x4e, 0x4c, 0x44, 0x8a, 0x4e, 0xbb, 0xc3, 0xde,
- 0x1e, 0x66, 0xbe, 0xe7, 0x01, 0x69, 0x0b, 0xdf, 0x47, 0x29, 0xd9, 0x81, 0x26, 0xc3, 0x8f, 0x10,
- 0x2d, 0xa4, 0x5e, 0x8a, 0x33, 0xe8, 0xa3, 0xed, 0x11, 0xbf, 0x10, 0x52, 0x58, 0x97, 0xc3, 0xb7,
- 0xb0, 0x2d, 0x8c, 0xc9, 0x99, 0x9c, 0xf0, 0x64, 0x5e, 0xa4, 0x7d, 0xc7, 0xbb, 0x27, 0x83, 0xf6,
- 0x4b, 0xbb, 0x92, 0x9d, 0x57, 0x10, 0xa6, 0xcc, 0x32, 0xc4, 0xe8, 0x0e, 0xbb, 0xde, 0xdc, 0xd5,
- 0x80, 0xe2, 0x43, 0xac, 0xa1, 0x7b, 0xce, 0x66, 0x39, 0x3f, 0x55, 0xb9, 0x9e, 0x70, 0xf2, 0x12,
- 0x02, 0xcd, 0x2f, 0xbc, 0xf7, 0x15, 0x73, 0xa7, 0x27, 0xbb, 0xd0, 0x58, 0x38, 0x6b, 0xef, 0x8f,
- 0x54, 0x93, 0x2b, 0x28, 0xa0, 0x85, 0x01, 0xf9, 0x0c, 0xda, 0x73, 0x65, 0x30, 0x7e, 0xa4, 0x2f,
- 0xa4, 0xb7, 0x72, 0xfc, 0x11, 0xb6, 0x11, 0xf3, 0x88, 0x1b, 0x2b, 0x24, 0xc3, 0x1c, 0xff, 0x17,
- 0xe0, 0xdf, 0x03, 0xe8, 0xfe, 0x30, 0x53, 0x93, 0x5f, 0x8f, 0x39, 0x4b, 0xb9, 0x26, 0x11, 0xb4,
- 0x56, 0x1b, 0xa7, 0x14, 0x5d, 0x75, 0xa6, 0x5c, 0x5c, 0x4e, 0x6f, 0xab, 0x53, 0x48, 0xe4, 0x1d,
- 0x0c, 0xe6, 0x9a, 0x2f, 0x84, 0xca, 0x4d, 0x32, 0x76, 0x9e, 0x5c, 0xa5, 0x83, 0xf5, 0xa0, 0xfb,
- 0xa5, 0x15, 0xc2, 0x8d, 0x52, 0xf2, 0x39, 0x74, 0xac, 0xc8, 0xb8, 0xb1, 0x2c, 0x9b, 0x63, 0xff,
- 0x84, 0x74, 0xa9, 0x20, 0xdf, 0xc0, 0xc0, 0x6a, 0x26, 0x0d, 0x9b, 0xb8, 0x38, 0x4d, 0xa2, 0x95,
- 0xb2, 0x51, 0x63, 0xdd, 0xed, 0x76, 0xd5, 0x8a, 0x2a, 0x65, 0xc9, 0x7b, 0x78, 0x51, 0xd1, 0x25,
- 0xc6, 0x32, 0x9b, 0x9b, 0x64, 0xca, 0xcc, 0x34, 0x6a, 0xae, 0x7f, 0xff, 0xbc, 0x62, 0x7b, 0x8a,
- 0xa6, 0x38, 0x8e, 0xcf, 0xa0, 0x21, 0x95, 0x9c, 0xf0, 0xa8, 0x85, 0x81, 0x15, 0x82, 0x1b, 0x9d,
- 0xb1, 0xb0, 0x26, 0x6a, 0xa3, 0x12, 0x7f, 0x93, 0x1f, 0x81, 0xac, 0xc3, 0x45, 0x1d, 0x44, 0x8a,
- 0x3c, 0xd2, 0xd9, 0x5d, 0x0c, 0x3a, 0x58, 0x83, 0x8d, 0xff, 0xa8, 0x41, 0xfb, 0xec, 0xea, 0xc1,
- 0x3a, 0x7c, 0x01, 0x7d, 0xc3, 0xb5, 0x60, 0x33, 0x71, 0xc3, 0xd3, 0xc4, 0x88, 0x1b, 0xee, 0x0b,
- 0xd2, 0x5b, 0xaa, 0x4f, 0xc5, 0x8d, 0x6b, 0x5c, 0x70, 0x74, 0x26, 0x9a, 0xc9, 0x4b, 0xee, 0x0b,
- 0x8f, 0x04, 0x53, 0xa7, 0x20, 0x6f, 0x00, 0x34, 0x37, 0xf9, 0xcc, 0x4d, 0xa6, 0x89, 0xc2, 0xd7,
- 0xc1, 0x5d, 0x66, 0x3a, 0xc5, 0xf3, 0x28, 0x35, 0xf1, 0x3e, 0xf4, 0xce, 0xae, 0xce, 0xb9, 0x16,
- 0x17, 0xd7, 0x14, 0x95, 0xe4, 0x15, 0x74, 0x3d, 0xb1, 0x17, 0x4c, 0xcc, 0x30, 0xc6, 0x36, 0x85,
- 0x42, 0xf5, 0x81, 0x89, 0x59, 0x2c, 0x60, 0xb0, 0x96, 0xf5, 0x27, 0xb2, 0xfa, 0x0e, 0x9e, 0x2c,
- 0xd0, 0x7f, 0x49, 0x60, 0x1d, 0x03, 0x7a, 0x5e, 0x12, 0xb8, 0x82, 0x4e, 0xb7, 0x0a, 0x5b, 0x4f,
- 0xdc, 0xdf, 0x35, 0x08, 0x7e, 0xce, 0xaf, 0xc8, 0xd7, 0xd0, 0x32, 0x38, 0xb3, 0x26, 0xaa, 0xe1,
- 0xd7, 0xe5, 0x4c, 0x54, 0xc6, 0x99, 0x96, 0x26, 0x64, 0x17, 0x5a, 0xe5, 0xe6, 0xa8, 0x6f, 0xdc,
- 0x1c, 0xe5, 0x33, 0xf9, 0x09, 0x9e, 0x7d, 0x14, 0x56, 0x72, 0x63, 0x92, 0x74, 0x39, 0x9f, 0x26,
- 0x0a, 0x10, 0xe4, 0x45, 0x15, 0xa4, 0x32, 0xbf, 0xf4, 0xa9, 0xff, 0xa8, 0xa2, 0x33, 0xe4, 0x2b,
- 0x18, 0x94, 0xbe, 0x98, 0xbe, 0xcc, 0x33, 0x2e, 0x6d, 0x41, 0xfe, 0x16, 0xdd, 0xf6, 0x0f, 0x87,
- 0xa5, 0x3e, 0xd6, 0xd0, 0x7e, 0xaf, 0x84, 0x1c, 0x33, 0xc3, 0xc9, 0x31, 0x3c, 0xdd, 0x10, 0x84,
- 0xdf, 0x0e, 0xf7, 0xc6, 0x40, 0xd6, 0x63, 0x70, 0x73, 0xc7, 0xf4, 0x58, 0x58, 0xcd, 0xf4, 0xb5,
- 0x3f, 0x02, 0x4b, 0x45, 0xfc, 0x5b, 0x0d, 0x9a, 0xbf, 0xe4, 0x76, 0x9e, 0x5b, 0xf2, 0x06, 0x9a,
- 0x05, 0x59, 0x1e, 0x65, 0x13, 0x9d, 0xde, 0x82, 0xbc, 0x83, 0xfe, 0x44, 0x49, 0xab, 0xd5, 0x2c,
- 0xf9, 0x34, 0xab, 0x3d, 0x6f, 0x56, 0xae, 0xe3, 0x08, 0x5a, 0x4a, 0xa7, 0x42, 0xb2, 0x99, 0x6f,
- 0xd1, 0x52, 0x8c, 0x29, 0x00, 0xe5, 0x56, 0x68, 0xee, 0xc8, 0x78, 0x54, 0x30, 0x15, 0x9f, 0xf5,
- 0x55, 0x9f, 0x7f, 0xd6, 0xa1, 0x3d, 0xf2, 0x07, 0xc1, 0x4d, 0x00, 0x8e, 0x75, 0xb1, 0x1b, 0x36,
- 0xec, 0xd9, 0x0e, 0x3e, 0xe3, 0x3e, 0xf8, 0xf7, 0xdb, 0xf6, 0x9e, 0x42, 0x05, 0x8f, 0x2f, 0xd4,
- 0x09, 0x44, 0xb7, 0xbd, 0x82, 0x27, 0x34, 0xbd, 0x3d, 0x80, 0xb8, 0x2f, 0xbb, 0xc3, 0x9d, 0x6a,
- 0x18, 0xcb, 0xf3, 0x48, 0x77, 0xca, 0x56, 0xba, 0x73, 0x36, 0x37, 0x76, 0x5f, 0x63, 0x73, 0xf7,
- 0x55, 0x59, 0x6c, 0xae, 0xb2, 0xf8, 0x57, 0x0d, 0x1a, 0xa7, 0x73, 0x2e, 0x53, 0x72, 0x00, 0x7d,
- 0x33, 0xe7, 0xd2, 0x26, 0x0a, 0x5b, 0x66, 0x79, 0xe4, 0x57, 0x78, 0x7c, 0x82, 0x36, 0x45, 0x57,
- 0x8d, 0xd2, 0xfb, 0x18, 0xaa, 0x3f, 0x9e, 0xa1, 0x8d, 0xf9, 0x04, 0x0f, 0xe7, 0x13, 0xae, 0xe4,
- 0x33, 0x6e, 0xe2, 0x3f, 0xb2, 0x83, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x91, 0x64, 0x55, 0x53,
- 0x9d, 0x09, 0x00, 0x00,
-}
+++ /dev/null
-syntax = "proto3";
-
-package bytom;
-
-message Hash {
- fixed64 v0 = 1;
- fixed64 v1 = 2;
- fixed64 v2 = 3;
- fixed64 v3 = 4;
-}
-
-message Program {
- uint64 vm_version = 1;
- bytes code = 2;
-}
-
-// This message type duplicates Hash, above. One alternative is to
-// embed a Hash inside an AssetID. But it's useful for AssetID to be
-// plain old data (without pointers). Another alternative is use Hash
-// in any protobuf types where an AssetID is called for, but it's
-// preferable to have type safety.
-message AssetID {
- fixed64 v0 = 1;
- fixed64 v1 = 2;
- fixed64 v2 = 3;
- fixed64 v3 = 4;
-}
-
-message AssetAmount {
- AssetID asset_id = 1;
- uint64 amount = 2;
-}
-
-message AssetDefinition {
- Program issuance_program = 1;
- Hash data = 2;
-}
-
-message ValueSource {
- Hash ref = 1;
- AssetAmount value = 2;
- uint64 position = 3;
-}
-
-message ValueDestination {
- Hash ref = 1;
- AssetAmount value = 2;
- uint64 position = 3;
-}
-
-message BlockHeader {
- uint64 version = 1;
- uint64 height = 2;
- Hash previous_block_id = 3;
- uint64 timestamp = 4;
- Hash transactions_root = 5;
- Hash transaction_status_hash = 6;
- uint64 nonce = 7;
- uint64 bits = 8;
- TransactionStatus transaction_status = 9;
-}
-
-message TxHeader {
- uint64 version = 1;
- uint64 serialized_size = 2;
- uint64 time_range = 3;
- repeated Hash result_ids = 4;
-}
-
-message TxVerifyResult {
- bool status_fail = 1;
-}
-
-message TransactionStatus {
- uint64 version = 1;
- repeated TxVerifyResult verify_status = 2;
-}
-
-message Mux {
- repeated ValueSource sources = 1; // issuances, spends, and muxes
- Program program = 2;
- repeated ValueDestination witness_destinations = 3; // outputs, retirements, and muxes
- repeated bytes witness_arguments = 4;
-}
-
-message Coinbase {
- ValueDestination witness_destination = 1;
- bytes arbitrary = 2;
-}
-
-message Output {
- ValueSource source = 1;
- Program control_program = 2;
- uint64 ordinal = 3;
-}
-
-message Retirement {
- ValueSource source = 1;
- uint64 ordinal = 2;
-}
-
-message Issuance {
- Hash nonce_hash = 1;
- AssetAmount value = 2;
- ValueDestination witness_destination = 3;
- AssetDefinition witness_asset_definition = 4;
- repeated bytes witness_arguments = 5;
- uint64 ordinal = 6;
-}
-
-message Spend {
- Hash spent_output_id = 1;
- ValueDestination witness_destination = 2;
- repeated bytes witness_arguments = 3;
- uint64 ordinal = 4;
-}
\ No newline at end of file
package bytom
+import "github.com/vapor/protocol/bc"
+
// Block is block struct in bc level
type Block struct {
- *BlockHeader
- ID Hash
+ *bc.BytomBlockHeader
+ ID bc.Hash
Transactions []*Tx
}
+++ /dev/null
-package bytom
-
-import "io"
-
-func (Coinbase) typ() string { return "coinbase1" }
-func (c *Coinbase) writeForHash(w io.Writer) {
- mustWriteForHash(w, c.Arbitrary)
-}
-
-// SetDestination is support function for map tx
-func (c *Coinbase) SetDestination(id *Hash, val *AssetAmount, pos uint64) {
- c.WitnessDestination = &ValueDestination{
- Ref: id,
- Value: val,
- Position: pos,
- }
-}
-
-// NewCoinbase creates a new Coinbase.
-func NewCoinbase(arbitrary []byte) *Coinbase {
- return &Coinbase{Arbitrary: arbitrary}
-}
+++ /dev/null
-package bytom
-
-import (
- "encoding/binary"
- "fmt"
- "io"
- "reflect"
-
- "github.com/golang/protobuf/proto"
-
- "github.com/vapor/crypto/sha3pool"
- "github.com/vapor/encoding/blockchain"
- "github.com/vapor/errors"
-)
-
-// Entry is the interface implemented by each addressable unit in a
-// blockchain: transaction components such as spends, issuances,
-// outputs, and retirements (among others), plus blockheaders.
-type Entry interface {
- proto.Message
-
- // type produces a short human-readable string uniquely identifying
- // the type of this entry.
- typ() string
-
- // writeForHash writes the entry's body for hashing.
- writeForHash(w io.Writer)
-}
-
-var errInvalidValue = errors.New("invalid value")
-
-// EntryID computes the identifier of an entry, as the hash of its
-// body plus some metadata.
-func EntryID(e Entry) (hash Hash) {
- if e == nil {
- return hash
- }
-
- // Nil pointer; not the same as nil interface above. (See
- // https://golang.org/doc/faq#nil_error.)
- if v := reflect.ValueOf(e); v.Kind() == reflect.Ptr && v.IsNil() {
- return hash
- }
-
- hasher := sha3pool.Get256()
- defer sha3pool.Put256(hasher)
-
- hasher.Write([]byte("entryid:"))
- hasher.Write([]byte(e.typ()))
- hasher.Write([]byte{':'})
-
- bh := sha3pool.Get256()
- defer sha3pool.Put256(bh)
-
- e.writeForHash(bh)
-
- var innerHash [32]byte
- bh.Read(innerHash[:])
-
- hasher.Write(innerHash[:])
-
- hash.ReadFrom(hasher)
- return hash
-}
-
-var byte32zero [32]byte
-
-// mustWriteForHash serializes the object c to the writer w, from which
-// presumably a hash can be extracted.
-//
-// This function may panic with an error from the underlying writer,
-// and may produce errors of its own if passed objects whose
-// hash-serialization formats are not specified. It MUST NOT produce
-// errors in other cases.
-func mustWriteForHash(w io.Writer, c interface{}) {
- if err := writeForHash(w, c); err != nil {
- panic(err)
- }
-}
-
-func writeForHash(w io.Writer, c interface{}) error {
- switch v := c.(type) {
- case byte:
- _, err := w.Write([]byte{v})
- return errors.Wrap(err, "writing byte for hash")
- case uint64:
- buf := [8]byte{}
- binary.LittleEndian.PutUint64(buf[:], v)
- _, err := w.Write(buf[:])
- return errors.Wrapf(err, "writing uint64 (%d) for hash", v)
- case []byte:
- _, err := blockchain.WriteVarstr31(w, v)
- return errors.Wrapf(err, "writing []byte (len %d) for hash", len(v))
- case [][]byte:
- _, err := blockchain.WriteVarstrList(w, v)
- return errors.Wrapf(err, "writing [][]byte (len %d) for hash", len(v))
- case string:
- _, err := blockchain.WriteVarstr31(w, []byte(v))
- return errors.Wrapf(err, "writing string (len %d) for hash", len(v))
- case *Hash:
- if v == nil {
- _, err := w.Write(byte32zero[:])
- return errors.Wrap(err, "writing nil *Hash for hash")
- }
- _, err := w.Write(v.Bytes())
- return errors.Wrap(err, "writing *Hash for hash")
- case *AssetID:
- if v == nil {
- _, err := w.Write(byte32zero[:])
- return errors.Wrap(err, "writing nil *AssetID for hash")
- }
- _, err := w.Write(v.Bytes())
- return errors.Wrap(err, "writing *AssetID for hash")
- case Hash:
- _, err := v.WriteTo(w)
- return errors.Wrap(err, "writing Hash for hash")
- case AssetID:
- _, err := v.WriteTo(w)
- return errors.Wrap(err, "writing AssetID for hash")
- }
-
- // The two container types in the spec (List and Struct)
- // correspond to slices and structs in Go. They can't be
- // handled with type assertions, so we must use reflect.
- switch v := reflect.ValueOf(c); v.Kind() {
- case reflect.Ptr:
- if v.IsNil() {
- return nil
- }
- elem := v.Elem()
- return writeForHash(w, elem.Interface())
- case reflect.Slice:
- l := v.Len()
- if _, err := blockchain.WriteVarint31(w, uint64(l)); err != nil {
- return errors.Wrapf(err, "writing slice (len %d) for hash", l)
- }
- for i := 0; i < l; i++ {
- c := v.Index(i)
- if !c.CanInterface() {
- return errInvalidValue
- }
- if err := writeForHash(w, c.Interface()); err != nil {
- return errors.Wrapf(err, "writing slice element %d for hash", i)
- }
- }
- return nil
-
- case reflect.Struct:
- typ := v.Type()
- for i := 0; i < typ.NumField(); i++ {
- c := v.Field(i)
- if !c.CanInterface() {
- return errInvalidValue
- }
- if err := writeForHash(w, c.Interface()); err != nil {
- t := v.Type()
- f := t.Field(i)
- return errors.Wrapf(err, "writing struct field %d (%s.%s) for hash", i, t.Name(), f.Name)
- }
- }
- return nil
- }
-
- return errors.Wrap(fmt.Errorf("bad type %T", c))
-}
+++ /dev/null
-package bytom
-
-import (
- "reflect"
- "testing"
-)
-
-func BenchmarkEntryID(b *testing.B) {
- m := NewMux([]*ValueSource{{Position: 1}}, &Program{Code: []byte{1}, VmVersion: 1})
-
- entries := []Entry{
- NewIssuance(nil, &AssetAmount{}, 0),
- m,
- NewTxHeader(1, 1, 0, nil),
- NewOutput(&ValueSource{}, &Program{Code: []byte{1}, VmVersion: 1}, 0),
- NewRetirement(&ValueSource{}, 1),
- NewSpend(&Hash{}, 0),
- }
-
- for _, e := range entries {
- name := reflect.TypeOf(e).Elem().Name()
- b.Run(name, func(b *testing.B) {
- for i := 0; i < b.N; i++ {
- EntryID(e)
- }
- })
- }
-}
import (
"encoding/binary"
"strings"
+
+ "github.com/vapor/protocol/bc"
)
//consensus variables
)
// BTMAssetID is BTM's asset id, the soul asset of Bytom
-var BTMAssetID = &AssetID{
+var BTMAssetID = &bc.AssetID{
V0: binary.BigEndian.Uint64([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}),
V1: binary.BigEndian.Uint64([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}),
V2: binary.BigEndian.Uint64([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}),
}
// InitialSeed is SHA3-256 of Byte[0^32]
-var InitialSeed = &Hash{
+var InitialSeed = &bc.Hash{
V0: uint64(11412844483649490393),
V1: uint64(4614157290180302959),
V2: uint64(1780246333311066183),
// and also prevents forks from old blocks.
type Checkpoint struct {
Height uint64
- Hash Hash
+ Hash bc.Hash
}
// Params store the config for different network
Name: "main",
Bech32HRPSegwit: "bm",
Checkpoints: []Checkpoint{
- {10000, NewHash([32]byte{0x93, 0xe1, 0xeb, 0x78, 0x21, 0xd2, 0xb4, 0xad, 0x0f, 0x5b, 0x1c, 0xea, 0x82, 0xe8, 0x43, 0xad, 0x8c, 0x09, 0x9a, 0xb6, 0x5d, 0x8f, 0x70, 0xc5, 0x84, 0xca, 0xa2, 0xdd, 0xf1, 0x74, 0x65, 0x2c})},
- {20000, NewHash([32]byte{0x7d, 0x38, 0x61, 0xf3, 0x2c, 0xc0, 0x03, 0x81, 0xbb, 0xcd, 0x9a, 0x37, 0x6f, 0x10, 0x5d, 0xfe, 0x6f, 0xfe, 0x2d, 0xa5, 0xea, 0x88, 0xa5, 0xe3, 0x42, 0xed, 0xa1, 0x17, 0x9b, 0xa8, 0x0b, 0x7c})},
- {30000, NewHash([32]byte{0x32, 0x36, 0x06, 0xd4, 0x27, 0x2e, 0x35, 0x24, 0x46, 0x26, 0x7b, 0xe0, 0xfa, 0x48, 0x10, 0xa4, 0x3b, 0xb2, 0x40, 0xf1, 0x09, 0x51, 0x5b, 0x22, 0x9f, 0xf3, 0xc3, 0x83, 0x28, 0xaa, 0x4a, 0x00})},
- {40000, NewHash([32]byte{0x7f, 0xe2, 0xde, 0x11, 0x21, 0xf3, 0xa9, 0xa0, 0xee, 0x60, 0x8d, 0x7d, 0x4b, 0xea, 0xcc, 0x33, 0xfe, 0x41, 0x25, 0xdc, 0x2f, 0x26, 0xc2, 0xf2, 0x9c, 0x07, 0x17, 0xf9, 0xe4, 0x4f, 0x9d, 0x46})},
- {50000, NewHash([32]byte{0x5e, 0xfb, 0xdf, 0xf5, 0x35, 0x38, 0xa6, 0x0b, 0x75, 0x32, 0x02, 0x61, 0x83, 0x54, 0x34, 0xff, 0x3e, 0x82, 0x2e, 0xf8, 0x64, 0xae, 0x2d, 0xc7, 0x6c, 0x9d, 0x5e, 0xbd, 0xa3, 0xd4, 0x50, 0xcf})},
- {62000, NewHash([32]byte{0xd7, 0x39, 0x8f, 0x23, 0x57, 0xf9, 0x4c, 0xa0, 0x28, 0xa7, 0x00, 0x2b, 0x53, 0x9e, 0x51, 0x2d, 0x3e, 0xca, 0xc9, 0x22, 0x59, 0xfc, 0xd0, 0x3f, 0x67, 0x1a, 0x0a, 0xb1, 0x02, 0xbf, 0x2b, 0x03})},
- {72000, NewHash([32]byte{0x66, 0x02, 0x31, 0x19, 0xf1, 0x60, 0x35, 0x61, 0xa4, 0xf1, 0x38, 0x04, 0xcc, 0xe4, 0x59, 0x8f, 0x55, 0x39, 0xba, 0x22, 0xf2, 0x6d, 0x90, 0xbf, 0xc1, 0x87, 0xef, 0x98, 0xcc, 0x70, 0x4d, 0x94})},
- {83700, NewHash([32]byte{0x7f, 0x26, 0xc9, 0x11, 0xe8, 0x46, 0xd0, 0x6e, 0x36, 0xbb, 0xac, 0xce, 0x99, 0xa2, 0x19, 0x89, 0x3f, 0xf7, 0x84, 0x2a, 0xcb, 0x44, 0x7f, 0xbb, 0x0e, 0x3b, 0xa3, 0x68, 0xd6, 0x2b, 0xe8, 0x0d})},
+ {10000, bc.NewHash([32]byte{0x93, 0xe1, 0xeb, 0x78, 0x21, 0xd2, 0xb4, 0xad, 0x0f, 0x5b, 0x1c, 0xea, 0x82, 0xe8, 0x43, 0xad, 0x8c, 0x09, 0x9a, 0xb6, 0x5d, 0x8f, 0x70, 0xc5, 0x84, 0xca, 0xa2, 0xdd, 0xf1, 0x74, 0x65, 0x2c})},
+ {20000, bc.NewHash([32]byte{0x7d, 0x38, 0x61, 0xf3, 0x2c, 0xc0, 0x03, 0x81, 0xbb, 0xcd, 0x9a, 0x37, 0x6f, 0x10, 0x5d, 0xfe, 0x6f, 0xfe, 0x2d, 0xa5, 0xea, 0x88, 0xa5, 0xe3, 0x42, 0xed, 0xa1, 0x17, 0x9b, 0xa8, 0x0b, 0x7c})},
+ {30000, bc.NewHash([32]byte{0x32, 0x36, 0x06, 0xd4, 0x27, 0x2e, 0x35, 0x24, 0x46, 0x26, 0x7b, 0xe0, 0xfa, 0x48, 0x10, 0xa4, 0x3b, 0xb2, 0x40, 0xf1, 0x09, 0x51, 0x5b, 0x22, 0x9f, 0xf3, 0xc3, 0x83, 0x28, 0xaa, 0x4a, 0x00})},
+ {40000, bc.NewHash([32]byte{0x7f, 0xe2, 0xde, 0x11, 0x21, 0xf3, 0xa9, 0xa0, 0xee, 0x60, 0x8d, 0x7d, 0x4b, 0xea, 0xcc, 0x33, 0xfe, 0x41, 0x25, 0xdc, 0x2f, 0x26, 0xc2, 0xf2, 0x9c, 0x07, 0x17, 0xf9, 0xe4, 0x4f, 0x9d, 0x46})},
+ {50000, bc.NewHash([32]byte{0x5e, 0xfb, 0xdf, 0xf5, 0x35, 0x38, 0xa6, 0x0b, 0x75, 0x32, 0x02, 0x61, 0x83, 0x54, 0x34, 0xff, 0x3e, 0x82, 0x2e, 0xf8, 0x64, 0xae, 0x2d, 0xc7, 0x6c, 0x9d, 0x5e, 0xbd, 0xa3, 0xd4, 0x50, 0xcf})},
+ {62000, bc.NewHash([32]byte{0xd7, 0x39, 0x8f, 0x23, 0x57, 0xf9, 0x4c, 0xa0, 0x28, 0xa7, 0x00, 0x2b, 0x53, 0x9e, 0x51, 0x2d, 0x3e, 0xca, 0xc9, 0x22, 0x59, 0xfc, 0xd0, 0x3f, 0x67, 0x1a, 0x0a, 0xb1, 0x02, 0xbf, 0x2b, 0x03})},
+ {72000, bc.NewHash([32]byte{0x66, 0x02, 0x31, 0x19, 0xf1, 0x60, 0x35, 0x61, 0xa4, 0xf1, 0x38, 0x04, 0xcc, 0xe4, 0x59, 0x8f, 0x55, 0x39, 0xba, 0x22, 0xf2, 0x6d, 0x90, 0xbf, 0xc1, 0x87, 0xef, 0x98, 0xcc, 0x70, 0x4d, 0x94})},
+ {83700, bc.NewHash([32]byte{0x7f, 0x26, 0xc9, 0x11, 0xe8, 0x46, 0xd0, 0x6e, 0x36, 0xbb, 0xac, 0xce, 0x99, 0xa2, 0x19, 0x89, 0x3f, 0xf7, 0x84, 0x2a, 0xcb, 0x44, 0x7f, 0xbb, 0x0e, 0x3b, 0xa3, 0x68, 0xd6, 0x2b, 0xe8, 0x0d})},
},
}
Name: "test",
Bech32HRPSegwit: "tm",
Checkpoints: []Checkpoint{
- {10303, NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c})},
- {40000, NewHash([32]byte{0x6b, 0x13, 0x9a, 0x5b, 0x76, 0x77, 0x9b, 0xd4, 0x1c, 0xec, 0x53, 0x68, 0x44, 0xbf, 0xf4, 0x48, 0x94, 0x3d, 0x16, 0xe3, 0x9b, 0x2e, 0xe8, 0xa1, 0x0f, 0xa0, 0xbc, 0x7d, 0x2b, 0x17, 0x55, 0xfc})},
+ {10303, bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c})},
+ {40000, bc.NewHash([32]byte{0x6b, 0x13, 0x9a, 0x5b, 0x76, 0x77, 0x9b, 0xd4, 0x1c, 0xec, 0x53, 0x68, 0x44, 0xbf, 0xf4, 0x48, 0x94, 0x3d, 0x16, 0xe3, 0x9b, 0x2e, 0xe8, 0xa1, 0x0f, 0xa0, 0xbc, 0x7d, 0x2b, 0x17, 0x55, 0xfc})},
},
}
+++ /dev/null
-package bytom
-
-import (
- "bytes"
- "encoding/binary"
- "encoding/hex"
- "encoding/json"
- "fmt"
- "io"
-
- "golang.org/x/crypto/sha3"
-)
-
-// EmptyStringHash represents a 256-bit hash.
-var EmptyStringHash = NewHash(sha3.Sum256(nil))
-
-// NewHash convert the input byte array to hash
-func NewHash(b32 [32]byte) (h Hash) {
- h.V0 = binary.BigEndian.Uint64(b32[0:8])
- h.V1 = binary.BigEndian.Uint64(b32[8:16])
- h.V2 = binary.BigEndian.Uint64(b32[16:24])
- h.V3 = binary.BigEndian.Uint64(b32[24:32])
- return h
-}
-
-// Byte32 return the byte array representation
-func (h Hash) Byte32() (b32 [32]byte) {
- binary.BigEndian.PutUint64(b32[0:8], h.V0)
- binary.BigEndian.PutUint64(b32[8:16], h.V1)
- binary.BigEndian.PutUint64(b32[16:24], h.V2)
- binary.BigEndian.PutUint64(b32[24:32], h.V3)
- return b32
-}
-
-// MarshalText satisfies the TextMarshaler interface.
-// It returns the bytes of h encoded in hex,
-// for formats that can't hold arbitrary binary data.
-// It never returns an error.
-func (h Hash) MarshalText() ([]byte, error) {
- b := h.Byte32()
- v := make([]byte, 64)
- hex.Encode(v, b[:])
- return v, nil
-}
-
-// UnmarshalText satisfies the TextUnmarshaler interface.
-// It decodes hex data from b into h.
-func (h *Hash) UnmarshalText(v []byte) error {
- var b [32]byte
- if len(v) != 64 {
- return fmt.Errorf("bad length hash string %d", len(v))
- }
- _, err := hex.Decode(b[:], v)
- *h = NewHash(b)
- return err
-}
-
-// UnmarshalJSON satisfies the json.Unmarshaler interface.
-// If b is a JSON-encoded null, it copies the zero-value into h. Othwerwise, it
-// decodes hex data from b into h.
-func (h *Hash) UnmarshalJSON(b []byte) error {
- if bytes.Equal(b, []byte("null")) {
- *h = Hash{}
- return nil
- }
- var s string
- if err := json.Unmarshal(b, &s); err != nil {
- return err
- }
- return h.UnmarshalText([]byte(s))
-}
-
-// Bytes returns the byte representation
-func (h Hash) Bytes() []byte {
- b32 := h.Byte32()
- return b32[:]
-}
-
-// WriteTo satisfies the io.WriterTo interface.
-func (h Hash) WriteTo(w io.Writer) (int64, error) {
- n, err := w.Write(h.Bytes())
- return int64(n), err
-}
-
-// ReadFrom satisfies the io.ReaderFrom interface.
-func (h *Hash) ReadFrom(r io.Reader) (int64, error) {
- var b32 [32]byte
- n, err := io.ReadFull(r, b32[:])
- if err != nil {
- return int64(n), err
- }
- *h = NewHash(b32)
- return int64(n), nil
-}
-
-// IsZero tells whether a Hash pointer is nil or points to an all-zero
-// hash.
-func (h *Hash) IsZero() bool {
- if h == nil {
- return true
- }
- return *h == Hash{}
-}
+++ /dev/null
-package bytom
-
-import "io"
-
-// Issuance is a source of new value on a blockchain. It satisfies the
-// Entry interface.
-
-func (Issuance) typ() string { return "issuance1" }
-func (iss *Issuance) writeForHash(w io.Writer) {
- mustWriteForHash(w, iss.NonceHash)
- mustWriteForHash(w, iss.Value)
-}
-
-// SetDestination will link the issuance to the output
-func (iss *Issuance) SetDestination(id *Hash, val *AssetAmount, pos uint64) {
- iss.WitnessDestination = &ValueDestination{
- Ref: id,
- Value: val,
- Position: pos,
- }
-}
-
-// NewIssuance creates a new Issuance.
-func NewIssuance(nonceHash *Hash, value *AssetAmount, ordinal uint64) *Issuance {
- return &Issuance{
- NonceHash: nonceHash,
- Value: value,
- Ordinal: ordinal,
- }
-}
+++ /dev/null
-package bytom
-
-import "io"
-
-// Mux splits and combines value from one or more source entries,
-// making it available to one or more destination entries. It
-// satisfies the Entry interface.
-
-func (Mux) typ() string { return "mux1" }
-func (m *Mux) writeForHash(w io.Writer) {
- mustWriteForHash(w, m.Sources)
- mustWriteForHash(w, m.Program)
-}
-
-// NewMux creates a new Mux.
-func NewMux(sources []*ValueSource, program *Program) *Mux {
- return &Mux{
- Sources: sources,
- Program: program,
- }
-}
+++ /dev/null
-package bytom
-
-import "io"
-
-// Output is the result of a transfer of value. The value it contains
-// may be accessed by a later Spend entry (if that entry can satisfy
-// the Output's ControlProgram). Output satisfies the Entry interface.
-//
-// (Not to be confused with the deprecated type TxOutput.)
-
-func (Output) typ() string { return "output1" }
-func (o *Output) writeForHash(w io.Writer) {
- mustWriteForHash(w, o.Source)
- mustWriteForHash(w, o.ControlProgram)
-}
-
-// NewOutput creates a new Output.
-func NewOutput(source *ValueSource, controlProgram *Program, ordinal uint64) *Output {
- return &Output{
- Source: source,
- ControlProgram: controlProgram,
- Ordinal: ordinal,
- }
-}
+++ /dev/null
-package bytom
-
-import "io"
-
-// Retirement is for the permanent removal of some value from a
-// blockchain. The value it contains can never be obtained by later
-// entries. Retirement satisfies the Entry interface.
-
-func (Retirement) typ() string { return "retirement1" }
-func (r *Retirement) writeForHash(w io.Writer) {
- mustWriteForHash(w, r.Source)
-}
-
-// NewRetirement creates a new Retirement.
-func NewRetirement(source *ValueSource, ordinal uint64) *Retirement {
- return &Retirement{
- Source: source,
- Ordinal: ordinal,
- }
-}
+++ /dev/null
-package bytom
-
-import "io"
-
-// Spend accesses the value in a prior Output for transfer
-// elsewhere. It satisfies the Entry interface.
-//
-// (Not to be confused with the deprecated type SpendInput.)
-
-func (Spend) typ() string { return "spend1" }
-func (s *Spend) writeForHash(w io.Writer) {
- mustWriteForHash(w, s.SpentOutputId)
-}
-
-// SetDestination will link the spend to the output
-func (s *Spend) SetDestination(id *Hash, val *AssetAmount, pos uint64) {
- s.WitnessDestination = &ValueDestination{
- Ref: id,
- Value: val,
- Position: pos,
- }
-}
-
-// NewSpend creates a new Spend.
-func NewSpend(spentOutputID *Hash, ordinal uint64) *Spend {
- return &Spend{
- SpentOutputId: spentOutputID,
- Ordinal: ordinal,
- }
-}
import (
"github.com/vapor/crypto/sha3pool"
"github.com/vapor/errors"
+ "github.com/vapor/protocol/bc"
)
// Tx is a wrapper for the entries-based representation of a transaction.
type Tx struct {
- *TxHeader
- ID Hash
- Entries map[Hash]Entry
- InputIDs []Hash // 1:1 correspondence with TxData.Inputs
+ *bc.TxHeader
+ ID bc.Hash
+ Entries map[bc.Hash]bc.Entry
+ InputIDs []bc.Hash // 1:1 correspondence with TxData.Inputs
- SpentOutputIDs []Hash
- GasInputIDs []Hash
+ SpentOutputIDs []bc.Hash
+ GasInputIDs []bc.Hash
}
// SigHash ...
-func (tx *Tx) SigHash(n uint32) (hash Hash) {
+func (tx *Tx) SigHash(n uint32) (hash bc.Hash) {
hasher := sha3pool.Get256()
defer sha3pool.Put256(hasher)
)
// Output try to get the output entry by given hash
-func (tx *Tx) Output(id Hash) (*Output, error) {
+func (tx *Tx) Output(id bc.Hash) (*bc.Output, error) {
e, ok := tx.Entries[id]
if !ok || e == nil {
return nil, errors.Wrapf(ErrMissingEntry, "id %x", id.Bytes())
}
- o, ok := e.(*Output)
+ o, ok := e.(*bc.Output)
if !ok {
return nil, errors.Wrapf(ErrEntryType, "entry %x has unexpected type %T", id.Bytes(), e)
}
}
// Spend try to get the spend entry by given hash
-func (tx *Tx) Spend(id Hash) (*Spend, error) {
+func (tx *Tx) Spend(id bc.Hash) (*bc.Spend, error) {
e, ok := tx.Entries[id]
if !ok || e == nil {
return nil, errors.Wrapf(ErrMissingEntry, "id %x", id.Bytes())
}
- sp, ok := e.(*Spend)
+ sp, ok := e.(*bc.Spend)
if !ok {
return nil, errors.Wrapf(ErrEntryType, "entry %x has unexpected type %T", id.Bytes(), e)
}
}
// Issuance try to get the issuance entry by given hash
-func (tx *Tx) Issuance(id Hash) (*Issuance, error) {
+func (tx *Tx) Issuance(id bc.Hash) (*bc.Issuance, error) {
e, ok := tx.Entries[id]
if !ok || e == nil {
return nil, errors.Wrapf(ErrMissingEntry, "id %x", id.Bytes())
}
- iss, ok := e.(*Issuance)
+ iss, ok := e.(*bc.Issuance)
if !ok {
return nil, errors.Wrapf(ErrEntryType, "entry %x has unexpected type %T", id.Bytes(), e)
}
+++ /dev/null
-package bytom
-
-import (
- "encoding/json"
- "errors"
- "io"
-)
-
-const transactionStatusVersion = 1
-
-// NewTransactionStatus create a empty TransactionStatus struct
-func NewTransactionStatus() *TransactionStatus {
- return &TransactionStatus{
- Version: transactionStatusVersion,
- VerifyStatus: []*TxVerifyResult{},
- }
-}
-
-// SetStatus set the tx status of given index
-func (ts *TransactionStatus) SetStatus(i int, gasOnly bool) error {
- if i > len(ts.VerifyStatus) {
- return errors.New("setStatus should be set one by one")
- }
-
- if i == len(ts.VerifyStatus) {
- ts.VerifyStatus = append(ts.VerifyStatus, &TxVerifyResult{StatusFail: gasOnly})
- } else {
- ts.VerifyStatus[i].StatusFail = gasOnly
- }
- return nil
-}
-
-// GetStatus get the tx status of given index
-func (ts *TransactionStatus) GetStatus(i int) (bool, error) {
- if i >= len(ts.VerifyStatus) {
- return false, errors.New("GetStatus is out of range")
- }
-
- return ts.VerifyStatus[i].StatusFail, nil
-}
-
-// WriteTo will write TxVerifyResult struct to io.Writer
-func (tvr *TxVerifyResult) WriteTo(w io.Writer) (int64, error) {
- bytes, err := json.Marshal(tvr)
- if err != nil {
- return 0, err
- }
-
- n, err := w.Write(bytes)
- return int64(n), err
-}
+++ /dev/null
-package bytom
-
-import (
- "testing"
-)
-
-func TestSetBits(t *testing.T) {
- cases := []struct {
- op map[int]bool
- result []bool
- }{
- {
- op: map[int]bool{
- 0: true,
- },
- result: []bool{true},
- },
- {
- op: map[int]bool{
- 0: false,
- },
- result: []bool{false},
- },
- {
- op: map[int]bool{
- 0: false,
- 1: true,
- },
- result: []bool{false, true},
- },
- {
- op: map[int]bool{
- 0: true,
- 1: false,
- },
- result: []bool{true, false},
- },
- {
- op: map[int]bool{
- 0: true,
- 1: false,
- 2: false,
- 3: true,
- 4: true,
- 5: true,
- 6: false,
- 7: true,
- 8: false,
- 9: true,
- },
- result: []bool{true, false, false, true, true, true, false, true, false, true},
- },
- }
-
- for ci, c := range cases {
- ts := NewTransactionStatus()
- for i := 0; i < len(c.op); i++ {
- if err := ts.SetStatus(i, c.op[i]); err != nil {
- t.Errorf("test case #%d, %t", ci, err)
- }
- }
-
- for i, v := range c.result {
- result, err := ts.GetStatus(i)
- if err != nil {
- t.Errorf("test case #%d, %t", ci, err)
- }
- if result != v {
- t.Errorf("bad result, %d want %t get %t", i, v, result)
- }
- }
- }
-}
+++ /dev/null
-package bytom
-
-import "io"
-
-// TxHeader contains header information for a transaction. Every
-// transaction on a blockchain contains exactly one TxHeader. The ID
-// of the TxHeader is the ID of the transaction. TxHeader satisfies
-// the Entry interface.
-
-func (TxHeader) typ() string { return "txheader" }
-func (h *TxHeader) writeForHash(w io.Writer) {
- mustWriteForHash(w, h.Version)
- mustWriteForHash(w, h.TimeRange)
- mustWriteForHash(w, h.ResultIds)
-}
-
-// NewTxHeader creates an new TxHeader.
-func NewTxHeader(version, serializedSize, timeRange uint64, resultIDs []*Hash) *TxHeader {
- return &TxHeader{
- Version: version,
- SerializedSize: serializedSize,
- TimeRange: timeRange,
- ResultIds: resultIDs,
- }
-}
"io"
"github.com/vapor/encoding/blockchain"
- "github.com/vapor/protocol/bc/types/bytom"
+ "github.com/vapor/protocol/bc"
)
// BlockCommitment store the TransactionsMerkleRoot && TransactionStatusHash
type BlockCommitment struct {
// TransactionsMerkleRoot is the root hash of the Merkle binary hash tree
// formed by the hashes of all transactions included in the block.
- TransactionsMerkleRoot bytom.Hash `json:"transaction_merkle_root"`
+ TransactionsMerkleRoot bc.Hash `json:"transaction_merkle_root"`
// TransactionStatusHash is the root hash of the Merkle binary hash tree
// formed by the hashes of all transaction verify results
- TransactionStatusHash bytom.Hash `json:"transaction_status_hash"`
+ TransactionStatusHash bc.Hash `json:"transaction_status_hash"`
}
func (bc *BlockCommitment) readFrom(r *blockchain.Reader) error {
"github.com/vapor/encoding/blockchain"
"github.com/vapor/encoding/bufpool"
"github.com/vapor/errors"
- "github.com/vapor/protocol/bc/types/bytom"
+ "github.com/vapor/protocol/bc"
)
// BlockHeader defines information about a block and is used in the Bytom
type BlockHeader struct {
- Version uint64 // The version of the block.
- Height uint64 // The height of the block.
- PreviousBlockHash bytom.Hash // The hash of the previous block.
- Timestamp uint64 // The time of the block in seconds.
- Nonce uint64 // Nonce used to generate the block.
- Bits uint64 // Difficulty target for the block.
+ Version uint64 // The version of the block.
+ Height uint64 // The height of the block.
+ PreviousBlockHash bc.Hash // The hash of the previous block.
+ Timestamp uint64 // The time of the block in seconds.
+ Nonce uint64 // Nonce used to generate the block.
+ Bits uint64 // Difficulty target for the block.
BlockCommitment
}
}
// Hash returns complete hash of the block header.
-func (bh *BlockHeader) Hash() bytom.Hash {
+func (bh *BlockHeader) Hash() bc.Hash {
h, _ := mapBlockHeader(bh)
return h
}
+++ /dev/null
-package types
-
-import (
- "github.com/vapor/crypto/sha3pool"
- "github.com/vapor/protocol/bc/types/bytom"
-)
-
-// IssuanceInput satisfies the TypedInput interface and represents a issuance.
-type IssuanceInput struct {
- Nonce []byte
- Amount uint64
-
- AssetDefinition []byte
- VMVersion uint64
- IssuanceProgram []byte
- Arguments [][]byte
-}
-
-// NewIssuanceInput create a new IssuanceInput struct.
-func NewIssuanceInput(nonce []byte, amount uint64, issuanceProgram []byte, arguments [][]byte, assetDefinition []byte) *TxInput {
- return &TxInput{
- AssetVersion: 1,
- TypedInput: &IssuanceInput{
- Nonce: nonce,
- Amount: amount,
- AssetDefinition: assetDefinition,
- VMVersion: 1,
- IssuanceProgram: issuanceProgram,
- Arguments: arguments,
- },
- }
-}
-
-// InputType is the interface function for return the input type.
-func (ii *IssuanceInput) InputType() uint8 { return IssuanceInputType }
-
-// AssetID calculate the assetID of the issuance input.
-func (ii *IssuanceInput) AssetID() bytom.AssetID {
- defhash := ii.AssetDefinitionHash()
- return bytom.ComputeAssetID(ii.IssuanceProgram, ii.VMVersion, &defhash)
-}
-
-// AssetDefinitionHash return the hash of the issuance asset definition.
-func (ii *IssuanceInput) AssetDefinitionHash() (defhash bytom.Hash) {
- sha := sha3pool.Get256()
- defer sha3pool.Put256(sha)
- sha.Write(ii.AssetDefinition)
- defhash.ReadFrom(sha)
- return defhash
-}
-
-// NonceHash return the hash of the issuance asset definition.
-func (ii *IssuanceInput) NonceHash() (hash bytom.Hash) {
- sha := sha3pool.Get256()
- defer sha3pool.Put256(sha)
- sha.Write(ii.Nonce)
- hash.ReadFrom(sha)
- return hash
-}
package types
import (
+ "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"
TxHeader: txHeader,
ID: txID,
Entries: entries,
- InputIDs: make([]bytom.Hash, len(oldTx.Inputs)),
+ InputIDs: make([]bc.Hash, len(oldTx.Inputs)),
}
- spentOutputIDs := make(map[bytom.Hash]bool)
+ spentOutputIDs := make(map[bc.Hash]bool)
for id, e := range entries {
var ord uint64
switch e := e.(type) {
- case *bytom.Issuance:
+ case *bc.Issuance:
ord = e.Ordinal
- case *bytom.Spend:
+ case *bc.Spend:
ord = e.Ordinal
spentOutputIDs[*e.SpentOutputId] = true
- if *e.WitnessDestination.Value.AssetId == *bytom.BTMAssetID {
+ if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
tx.GasInputIDs = append(tx.GasInputIDs, id)
}
- case *bytom.Coinbase:
+ case *bc.Coinbase:
ord = 0
default:
return tx
}
-func mapTx(tx *TxData) (headerID bytom.Hash, hdr *bytom.TxHeader, entryMap map[bytom.Hash]bytom.Entry) {
- entryMap = make(map[bytom.Hash]bytom.Entry)
- addEntry := func(e bytom.Entry) bytom.Hash {
- id := bytom.EntryID(e)
+func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash]bc.Entry) {
+ entryMap = make(map[bc.Hash]bc.Entry)
+ addEntry := func(e bc.Entry) bc.Hash {
+ id := bc.EntryID(e)
entryMap[id] = e
return id
}
var (
- spends []*bytom.Spend
- issuances []*bytom.Issuance
- coinbase *bytom.Coinbase
+ spends []*bc.Spend
+ issuances []*bc.Issuance
+ coinbase *bc.Coinbase
)
- muxSources := make([]*bytom.ValueSource, len(tx.Inputs))
+ muxSources := make([]*bc.ValueSource, len(tx.Inputs))
for i, input := range tx.Inputs {
switch inp := input.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
nonceHash := inp.NonceHash()
assetDefHash := inp.AssetDefinitionHash()
value := input.AssetAmount()
- issuance := bytom.NewIssuance(&nonceHash, &value, uint64(i))
- issuance.WitnessAssetDefinition = &bytom.AssetDefinition{
+ issuance := bc.NewIssuance(&nonceHash, &value, uint64(i))
+ issuance.WitnessAssetDefinition = &bc.AssetDefinition{
Data: &assetDefHash,
- IssuanceProgram: &bytom.Program{
+ IssuanceProgram: &bc.Program{
VmVersion: inp.VMVersion,
Code: inp.IssuanceProgram,
},
issuance.WitnessArguments = inp.Arguments
issuanceID := addEntry(issuance)
- muxSources[i] = &bytom.ValueSource{
+ muxSources[i] = &bc.ValueSource{
Ref: &issuanceID,
Value: &value,
}
case *SpendInput:
// create entry for prevout
- prog := &bytom.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
- src := &bytom.ValueSource{
+ prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
+ src := &bc.ValueSource{
Ref: &inp.SourceID,
Value: &inp.AssetAmount,
Position: inp.SourcePosition,
}
- prevout := bytom.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
+ prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
prevoutID := addEntry(prevout)
// create entry for spend
- spend := bytom.NewSpend(&prevoutID, uint64(i))
+ spend := bc.NewSpend(&prevoutID, uint64(i))
spend.WitnessArguments = inp.Arguments
spendID := addEntry(spend)
// setup mux
- muxSources[i] = &bytom.ValueSource{
+ muxSources[i] = &bc.ValueSource{
Ref: &spendID,
Value: &inp.AssetAmount,
}
spends = append(spends, spend)
case *CoinbaseInput:
- coinbase = bytom.NewCoinbase(inp.Arbitrary)
+ coinbase = bc.NewCoinbase(inp.Arbitrary)
coinbaseID := addEntry(coinbase)
out := tx.Outputs[0]
- muxSources[i] = &bytom.ValueSource{
+ muxSources[i] = &bc.ValueSource{
Ref: &coinbaseID,
Value: &out.AssetAmount,
}
}
}
- mux := bytom.NewMux(muxSources, &bytom.Program{VmVersion: 1, Code: []byte{byte(vm.OP_TRUE)}})
+ mux := bc.NewMux(muxSources, &bc.Program{VmVersion: 1, Code: []byte{byte(vm.OP_TRUE)}})
muxID := addEntry(mux)
// connect the inputs to the mux
for _, spend := range spends {
- spentOutput := entryMap[*spend.SpentOutputId].(*bytom.Output)
+ spentOutput := entryMap[*spend.SpentOutputId].(*bc.Output)
spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
}
for _, issuance := range issuances {
}
// convert types.outputs to the bytom.output
- var resultIDs []*bytom.Hash
+ var resultIDs []*bc.Hash
for i, out := range tx.Outputs {
- src := &bytom.ValueSource{
+ src := &bc.ValueSource{
Ref: &muxID,
Value: &out.AssetAmount,
Position: uint64(i),
}
- var resultID bytom.Hash
+ var resultID bc.Hash
if vmutil.IsUnspendable(out.ControlProgram) {
// retirement
- r := bytom.NewRetirement(src, uint64(i))
+ r := bc.NewRetirement(src, uint64(i))
resultID = addEntry(r)
} else {
// non-retirement
- prog := &bytom.Program{out.VMVersion, out.ControlProgram}
- o := bytom.NewOutput(src, prog, uint64(i))
+ prog := &bc.Program{out.VMVersion, out.ControlProgram}
+ o := bc.NewOutput(src, prog, uint64(i))
resultID = addEntry(o)
}
- dest := &bytom.ValueDestination{
+ dest := &bc.ValueDestination{
Value: src.Value,
Ref: &resultID,
Position: 0,
mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
}
- h := bytom.NewTxHeader(tx.Version, tx.SerializedSize, tx.TimeRange, resultIDs)
+ h := bc.NewTxHeader(tx.Version, tx.SerializedSize, tx.TimeRange, resultIDs)
return addEntry(h), h, entryMap
}
-func mapBlockHeader(old *BlockHeader) (bytom.Hash, *bytom.BlockHeader) {
- bh := bytom.NewBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash, old.Nonce, old.Bits)
- return bytom.EntryID(bh), bh
+func mapBlockHeader(old *BlockHeader) (bc.Hash, *bc.BytomBlockHeader) {
+ bh := bc.NewBytomBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash, old.Nonce, old.Bits)
+ return bc.EntryID(bh), bh
}
// MapBlock converts a types block to bc block
}
b := new(bytom.Block)
- b.ID, b.BlockHeader = mapBlockHeader(&old.BlockHeader)
+ b.ID, b.BytomBlockHeader = mapBlockHeader(&old.BlockHeader)
for _, oldTx := range old.Transactions {
b.Transactions = append(b.Transactions, oldTx.Tx)
}
+++ /dev/null
-package types
-
-import (
- "container/list"
- "io"
- "math"
-
- "gopkg.in/fatih/set.v0"
-
- "github.com/vapor/crypto/sha3pool"
- "github.com/vapor/protocol/bc/types/bytom"
-)
-
-// merkleFlag represent the type of merkle tree node, it's used to generate the structure of merkle tree
-// Bitcoin has only two flags, which zero means the hash of assist node. And one means the hash of the related
-// transaction node or it's parents, which distinguish them according to the height of the tree. But in the bytom,
-// the height of transaction node is not fixed, so we need three flags to distinguish these nodes.
-const (
- // FlagAssist represent assist node
- FlagAssist = iota
- // FlagTxParent represent the parent of transaction of node
- FlagTxParent
- // FlagTxLeaf represent transaction of node
- FlagTxLeaf
-)
-
-var (
- leafPrefix = []byte{0x00}
- interiorPrefix = []byte{0x01}
-)
-
-type merkleNode interface {
- WriteTo(io.Writer) (int64, error)
-}
-
-func merkleRoot(nodes []merkleNode) (root bytom.Hash, err error) {
- switch {
- case len(nodes) == 0:
- return bytom.EmptyStringHash, nil
-
- case len(nodes) == 1:
- root = leafMerkleHash(nodes[0])
- return root, nil
-
- default:
- k := prevPowerOfTwo(len(nodes))
- left, err := merkleRoot(nodes[:k])
- if err != nil {
- return root, err
- }
-
- right, err := merkleRoot(nodes[k:])
- if err != nil {
- return root, err
- }
-
- root = interiorMerkleHash(&left, &right)
- return root, nil
- }
-}
-
-func interiorMerkleHash(left merkleNode, right merkleNode) (hash bytom.Hash) {
- h := sha3pool.Get256()
- defer sha3pool.Put256(h)
- h.Write(interiorPrefix)
- left.WriteTo(h)
- right.WriteTo(h)
- hash.ReadFrom(h)
- return hash
-}
-
-func leafMerkleHash(node merkleNode) (hash bytom.Hash) {
- h := sha3pool.Get256()
- defer sha3pool.Put256(h)
- h.Write(leafPrefix)
- node.WriteTo(h)
- hash.ReadFrom(h)
- return hash
-}
-
-type merkleTreeNode struct {
- hash bytom.Hash
- left *merkleTreeNode
- right *merkleTreeNode
-}
-
-// buildMerkleTree construct a merkle tree based on the provide node data
-func buildMerkleTree(rawDatas []merkleNode) *merkleTreeNode {
- switch len(rawDatas) {
- case 0:
- return nil
- case 1:
- rawData := rawDatas[0]
- merkleHash := leafMerkleHash(rawData)
- node := newMerkleTreeNode(merkleHash, nil, nil)
- return node
- default:
- k := prevPowerOfTwo(len(rawDatas))
- left := buildMerkleTree(rawDatas[:k])
- right := buildMerkleTree(rawDatas[k:])
- merkleHash := interiorMerkleHash(&left.hash, &right.hash)
- node := newMerkleTreeNode(merkleHash, left, right)
- return node
- }
-}
-
-func (node *merkleTreeNode) getMerkleTreeProof(merkleHashSet *set.Set) ([]*bytom.Hash, []uint8) {
- var hashes []*bytom.Hash
- var flags []uint8
-
- if node.left == nil && node.right == nil {
- if key := node.hash.String(); merkleHashSet.Has(key) {
- hashes = append(hashes, &node.hash)
- flags = append(flags, FlagTxLeaf)
- return hashes, flags
- }
- return hashes, flags
- }
- var leftHashes, rightHashes []*bytom.Hash
- var leftFlags, rightFlags []uint8
- if node.left != nil {
- leftHashes, leftFlags = node.left.getMerkleTreeProof(merkleHashSet)
- }
- if node.right != nil {
- rightHashes, rightFlags = node.right.getMerkleTreeProof(merkleHashSet)
- }
- leftFind, rightFind := len(leftHashes) > 0, len(rightHashes) > 0
-
- if leftFind || rightFind {
- flags = append(flags, FlagTxParent)
- } else {
- return hashes, flags
- }
-
- if leftFind {
- hashes = append(hashes, leftHashes...)
- flags = append(flags, leftFlags...)
- } else {
- hashes = append(hashes, &node.left.hash)
- flags = append(flags, FlagAssist)
- }
-
- if rightFind {
- hashes = append(hashes, rightHashes...)
- flags = append(flags, rightFlags...)
- } else {
- hashes = append(hashes, &node.right.hash)
- flags = append(flags, FlagAssist)
- }
- return hashes, flags
-}
-
-func getMerkleTreeProof(rawDatas []merkleNode, relatedRawDatas []merkleNode) ([]*bytom.Hash, []uint8) {
- merkleTree := buildMerkleTree(rawDatas)
- if merkleTree == nil {
- return []*bytom.Hash{}, []uint8{}
- }
- merkleHashSet := set.New()
- for _, data := range relatedRawDatas {
- merkleHash := leafMerkleHash(data)
- merkleHashSet.Add(merkleHash.String())
- }
- if merkleHashSet.Size() == 0 {
- return []*bytom.Hash{&merkleTree.hash}, []uint8{FlagAssist}
- }
- return merkleTree.getMerkleTreeProof(merkleHashSet)
-}
-
-func (node *merkleTreeNode) getMerkleTreeProofByFlags(flagList *list.List) []*bytom.Hash {
- var hashes []*bytom.Hash
-
- if flagList.Len() == 0 {
- return hashes
- }
- flagEle := flagList.Front()
- flag := flagEle.Value.(uint8)
- flagList.Remove(flagEle)
-
- if flag == FlagTxLeaf || flag == FlagAssist {
- hashes = append(hashes, &node.hash)
- return hashes
- }
- if node.left != nil {
- leftHashes := node.left.getMerkleTreeProofByFlags(flagList)
- hashes = append(hashes, leftHashes...)
- }
- if node.right != nil {
- rightHashes := node.right.getMerkleTreeProofByFlags(flagList)
- hashes = append(hashes, rightHashes...)
- }
- return hashes
-}
-
-func getMerkleTreeProofByFlags(rawDatas []merkleNode, flagList *list.List) []*bytom.Hash {
- tree := buildMerkleTree(rawDatas)
- return tree.getMerkleTreeProofByFlags(flagList)
-}
-
-// GetTxMerkleTreeProof return a proof of merkle tree, which used to proof the transaction does
-// exist in the merkle tree
-func GetTxMerkleTreeProof(txs []*Tx, relatedTxs []*Tx) ([]*bytom.Hash, []uint8) {
- var rawDatas []merkleNode
- var relatedRawDatas []merkleNode
- for _, tx := range txs {
- rawDatas = append(rawDatas, &tx.ID)
- }
- for _, relatedTx := range relatedTxs {
- relatedRawDatas = append(relatedRawDatas, &relatedTx.ID)
- }
- return getMerkleTreeProof(rawDatas, relatedRawDatas)
-}
-
-// GetStatusMerkleTreeProof return a proof of merkle tree, which used to proof the status of transaction is valid
-func GetStatusMerkleTreeProof(statuses []*bytom.TxVerifyResult, flags []uint8) []*bytom.Hash {
- var rawDatas []merkleNode
- for _, status := range statuses {
- rawDatas = append(rawDatas, status)
- }
- flagList := list.New()
- for _, flag := range flags {
- flagList.PushBack(flag)
- }
- return getMerkleTreeProofByFlags(rawDatas, flagList)
-}
-
-// getMerkleRootByProof caculate the merkle root hash according to the proof
-func getMerkleRootByProof(hashList *list.List, flagList *list.List, merkleHashes *list.List) bytom.Hash {
- if flagList.Len() == 0 || hashList.Len() == 0 {
- return bytom.EmptyStringHash
- }
- flagEle := flagList.Front()
- flag := flagEle.Value.(uint8)
- flagList.Remove(flagEle)
- switch flag {
- case FlagAssist:
- {
- hash := hashList.Front()
- hashList.Remove(hash)
- return hash.Value.(bytom.Hash)
- }
- case FlagTxLeaf:
- {
- if merkleHashes.Len() == 0 {
- return bytom.EmptyStringHash
- }
- hashEle := hashList.Front()
- hash := hashEle.Value.(bytom.Hash)
- relatedHashEle := merkleHashes.Front()
- relatedHash := relatedHashEle.Value.(bytom.Hash)
- if hash == relatedHash {
- hashList.Remove(hashEle)
- merkleHashes.Remove(relatedHashEle)
- return hash
- }
- }
- case FlagTxParent:
- {
- leftHash := getMerkleRootByProof(hashList, flagList, merkleHashes)
- rightHash := getMerkleRootByProof(hashList, flagList, merkleHashes)
- hash := interiorMerkleHash(&leftHash, &rightHash)
- return hash
- }
- }
- return bytom.EmptyStringHash
-}
-
-func newMerkleTreeNode(merkleHash bytom.Hash, left *merkleTreeNode, right *merkleTreeNode) *merkleTreeNode {
- return &merkleTreeNode{
- hash: merkleHash,
- left: left,
- right: right,
- }
-}
-
-// ValidateMerkleTreeProof caculate the merkle root according to the hash of node and the flags
-// only if the merkle root by caculated equals to the specify merkle root, and the merkle tree
-// contains all of the related raw datas, the validate result will be true.
-func validateMerkleTreeProof(hashes []*bytom.Hash, flags []uint8, relatedNodes []merkleNode, merkleRoot bytom.Hash) bool {
- merkleHashes := list.New()
- for _, relatedNode := range relatedNodes {
- merkleHashes.PushBack(leafMerkleHash(relatedNode))
- }
- hashList := list.New()
- for _, hash := range hashes {
- hashList.PushBack(*hash)
- }
- flagList := list.New()
- for _, flag := range flags {
- flagList.PushBack(flag)
- }
- root := getMerkleRootByProof(hashList, flagList, merkleHashes)
- return root == merkleRoot && merkleHashes.Len() == 0
-}
-
-// ValidateTxMerkleTreeProof validate the merkle tree of transactions
-func ValidateTxMerkleTreeProof(hashes []*bytom.Hash, flags []uint8, relatedHashes []*bytom.Hash, merkleRoot bytom.Hash) bool {
- var relatedNodes []merkleNode
- for _, hash := range relatedHashes {
- relatedNodes = append(relatedNodes, hash)
- }
- return validateMerkleTreeProof(hashes, flags, relatedNodes, merkleRoot)
-}
-
-// ValidateStatusMerkleTreeProof validate the merkle tree of transaction status
-func ValidateStatusMerkleTreeProof(hashes []*bytom.Hash, flags []uint8, relatedStatus []*bytom.TxVerifyResult, merkleRoot bytom.Hash) bool {
- var relatedNodes []merkleNode
- for _, result := range relatedStatus {
- relatedNodes = append(relatedNodes, result)
- }
- return validateMerkleTreeProof(hashes, flags, relatedNodes, merkleRoot)
-}
-
-// TxStatusMerkleRoot creates a merkle tree from a slice of bytom.TxVerifyResult
-func TxStatusMerkleRoot(tvrs []*bytom.TxVerifyResult) (root bytom.Hash, err error) {
- nodes := []merkleNode{}
- for _, tvr := range tvrs {
- nodes = append(nodes, tvr)
- }
- return merkleRoot(nodes)
-}
-
-// TxMerkleRoot creates a merkle tree from a slice of transactions
-// and returns the root hash of the tree.
-func TxMerkleRoot(transactions []*bytom.Tx) (root bytom.Hash, err error) {
- nodes := []merkleNode{}
- for _, tx := range transactions {
- nodes = append(nodes, &tx.ID)
- }
- return merkleRoot(nodes)
-}
-
-// prevPowerOfTwo returns the largest power of two that is smaller than a given number.
-// In other words, for some input n, the prevPowerOfTwo k is a power of two such that
-// k < n <= 2k. This is a helper function used during the calculation of a merkle tree.
-func prevPowerOfTwo(n int) int {
- // If the number is a power of two, divide it by 2 and return.
- if n&(n-1) == 0 {
- return n / 2
- }
-
- // Otherwise, find the previous PoT.
- exponent := uint(math.Log2(float64(n)))
- return 1 << exponent // 2^exponent
-}
"github.com/vapor/crypto/sha3pool"
"github.com/vapor/encoding/blockchain"
"github.com/vapor/errors"
- "github.com/vapor/protocol/bc/types/bytom"
+ "github.com/vapor/protocol/bc"
)
// OutputCommitment contains the commitment data for a transaction output.
type OutputCommitment struct {
- bytom.AssetAmount
+ bc.AssetAmount
VMVersion uint64
ControlProgram []byte
}
})
}
-// Hash convert suffix && assetVersion to bytom.Hash
-func (oc *OutputCommitment) Hash(suffix []byte, assetVersion uint64) (outputhash bytom.Hash) {
+// Hash convert suffix && assetVersion to bc.Hash
+func (oc *OutputCommitment) Hash(suffix []byte, assetVersion uint64) (outputhash bc.Hash) {
h := sha3pool.Get256()
defer sha3pool.Put256(h)
oc.writeExtensibleString(h, suffix, assetVersion)
package types
import (
- "github.com/vapor/protocol/bc/types/bytom"
+ "github.com/vapor/protocol/bc"
)
// SpendInput satisfies the TypedInput interface and represents a spend transaction.
}
// NewSpendInput create a new SpendInput struct.
-func NewSpendInput(arguments [][]byte, sourceID bytom.Hash, assetID bytom.AssetID, amount, sourcePos uint64, controlProgram []byte) *TxInput {
+func NewSpendInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, amount, sourcePos uint64, controlProgram []byte) *TxInput {
sc := SpendCommitment{
- AssetAmount: bytom.AssetAmount{
+ AssetAmount: bc.AssetAmount{
AssetId: &assetID,
Amount: amount,
},
"github.com/vapor/encoding/blockchain"
"github.com/vapor/errors"
- "github.com/vapor/protocol/bc/types/bytom"
+ "github.com/vapor/protocol/bc"
)
// SpendCommitment contains the commitment data for a transaction output.
type SpendCommitment struct {
- bytom.AssetAmount
- SourceID bytom.Hash
+ bc.AssetAmount
+ SourceID bc.Hash
SourcePosition uint64
VMVersion uint64
ControlProgram []byte
"github.com/vapor/encoding/blockchain"
"github.com/vapor/errors"
+ "github.com/vapor/protocol/bc"
"github.com/vapor/protocol/bc/types/bytom"
)
}
// OutputID return the hash of the output position
-func (tx *Tx) OutputID(outputIndex int) *bytom.Hash {
+func (tx *Tx) OutputID(outputIndex int) *bc.Hash {
return tx.ResultIds[outputIndex]
}
id := tx.Tx.InputIDs[n]
e := tx.Entries[id]
switch e := e.(type) {
- case *bytom.Issuance:
+ case *bc.Issuance:
e.WitnessArguments = args
- case *bytom.Spend:
+ case *bc.Spend:
e.WitnessArguments = args
}
}
"github.com/vapor/encoding/blockchain"
"github.com/vapor/errors"
- "github.com/vapor/protocol/bc/types/bytom"
+ "github.com/vapor/protocol/bc"
+ "github.com/vapor/protocol/bc/types"
)
// serflag variables for input types.
var errBadAssetID = errors.New("asset ID does not match other issuance parameters")
// AssetAmount return the asset id and amount of the txinput.
-func (t *TxInput) AssetAmount() bytom.AssetAmount {
+func (t *TxInput) AssetAmount() bc.AssetAmount {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
assetID := inp.AssetID()
- return bytom.AssetAmount{
+ return bc.AssetAmount{
AssetId: &assetID,
Amount: inp.Amount,
}
case *SpendInput:
return inp.AssetAmount
}
- return bytom.AssetAmount{}
+ return bc.AssetAmount{}
}
// AssetID return the assetID of the txinput
-func (t *TxInput) AssetID() bytom.AssetID {
+func (t *TxInput) AssetID() bc.AssetID {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
return inp.AssetID()
case *SpendInput:
return *inp.AssetId
}
- return bytom.AssetID{}
+ return bc.AssetID{}
}
// Amount return the asset amount of the txinput
func (t *TxInput) Amount() uint64 {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
return inp.Amount
case *SpendInput:
return inp.Amount
// IssuanceProgram return the control program of the issuance input
func (t *TxInput) IssuanceProgram() []byte {
- if ii, ok := t.TypedInput.(*IssuanceInput); ok {
+ if ii, ok := t.TypedInput.(*types.IssuanceInput); ok {
return ii.IssuanceProgram
}
return nil
// Arguments get the args for the input
func (t *TxInput) Arguments() [][]byte {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
return inp.Arguments
case *SpendInput:
return inp.Arguments
// SetArguments set the args for the input
func (t *TxInput) SetArguments(args [][]byte) {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
inp.Arguments = args
case *SpendInput:
inp.Arguments = args
}
// SpentOutputID calculate the hash of spended output
-func (t *TxInput) SpentOutputID() (o bytom.Hash, err error) {
+func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
if si, ok := t.TypedInput.(*SpendInput); ok {
o, err = ComputeOutputID(&si.SpendCommitment)
}
return err
}
- var assetID bytom.AssetID
+ var assetID bc.AssetID
t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
if t.AssetVersion != 1 {
return nil
}
switch icType[0] {
case IssuanceInputType:
- ii := new(IssuanceInput)
+ ii := new(types.IssuanceInput)
t.TypedInput = ii
if ii.Nonce, err = blockchain.ReadVarstr31(r); err != nil {
}
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
return err
}
}
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
if _, err = w.Write([]byte{IssuanceInputType}); err != nil {
return err
}
return nil
}
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
+ case *types.IssuanceInput:
if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
return err
}
"github.com/vapor/encoding/blockchain"
"github.com/vapor/errors"
- "github.com/vapor/protocol/bc/types/bytom"
+ "github.com/vapor/protocol/bc"
)
// TxOutput is the top level struct of tx output.
}
// NewTxOutput create a new output struct
-func NewTxOutput(assetID bytom.AssetID, amount uint64, controlProgram []byte) *TxOutput {
+func NewTxOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *TxOutput {
return &TxOutput{
AssetVersion: 1,
OutputCommitment: OutputCommitment{
- AssetAmount: bytom.AssetAmount{
+ AssetAmount: bc.AssetAmount{
AssetId: &assetID,
Amount: amount,
},
// ComputeOutputID assembles an output entry given a spend commitment and
// computes and returns its corresponding entry ID.
-func ComputeOutputID(sc *SpendCommitment) (h bytom.Hash, err error) {
+func ComputeOutputID(sc *SpendCommitment) (h bc.Hash, err error) {
defer func() {
if r, ok := recover().(error); ok {
err = r
}
}()
- src := &bytom.ValueSource{
+ src := &bc.ValueSource{
Ref: &sc.SourceID,
Value: &sc.AssetAmount,
Position: sc.SourcePosition,
}
- o := bytom.NewOutput(src, &bytom.Program{VmVersion: sc.VMVersion, Code: sc.ControlProgram}, 0)
+ o := bc.NewOutput(src, &bc.Program{VmVersion: sc.VMVersion, Code: sc.ControlProgram}, 0)
- h = bytom.EntryID(o)
+ h = bc.EntryID(o)
return h, nil
}
if ok := c.txPool.HaveTransaction(&tx.ID); ok {
return false, c.txPool.GetErrCache(&tx.ID)
}
+
+ if ok := c.txPool.IsWithdrawSpent(tx); ok {
+ log.WithFields(log.Fields{"module": "ValidateTx", "error": "Cliam transactions already exist in the trading pool"}).Error("chain error")
+ return false, errors.New("Cliam transactions already exist in the trading pool")
+ }
+
bh := c.BestBlockHeader()
block := types.MapBlock(&types.Block{BlockHeader: *bh})
gasStatus, err := validation.ValidateTx(tx.Tx, block)
utxo map[bc.Hash]*types.Tx
orphans map[bc.Hash]*orphanTx
orphansByPrev map[bc.Hash]map[bc.Hash]*orphanTx
+ claimTx map[bc.Hash]bool
errCache *lru.Cache
msgCh chan *TxPoolMsg
}
utxo: make(map[bc.Hash]*types.Tx),
orphans: make(map[bc.Hash]*orphanTx),
orphansByPrev: make(map[bc.Hash]map[bc.Hash]*orphanTx),
+ claimTx: make(map[bc.Hash]bool),
errCache: lru.New(maxCachedErrTxs),
msgCh: make(chan *TxPoolMsg, maxMsgChSize),
}
for _, output := range txD.Tx.ResultIds {
delete(tp.utxo, *output)
}
+ tp.removeClaimTx(txD.Tx)
delete(tp.pool, *txHash)
atomic.StoreInt64(&tp.lastUpdated, time.Now().Unix())
tp.mtx.Lock()
defer tp.mtx.Unlock()
- if tp.isWithdrawSpent(tx) {
+ if tp.IsWithdrawSpent(tx) {
+ log.WithFields(log.Fields{"module": "ProcessTransaction", "error": "pegin-already-claimed"}).Error("ProcessTransaction error")
return false, errors.New("pegin-already-claimed")
}
return false, nil
}
-func (tp *TxPool) isWithdrawSpent(tx *types.Tx) bool {
+func (tp *TxPool) IsWithdrawSpent(tx *types.Tx) bool {
for key, value := range tx.Entries {
switch value.(type) {
case *bc.Claim:
- return tp.store.IsWithdrawSpent(&key)
+ _, ok := tp.claimTx[key]
+ return tp.store.IsWithdrawSpent(&key) || ok
default:
continue
}
return false
}
+func (tp *TxPool) addClaimTx(tx *types.Tx) {
+ for key, value := range tx.Entries {
+ switch value.(type) {
+ case *bc.Claim:
+ tp.claimTx[key] = true
+ default:
+ continue
+ }
+ }
+}
+
+func (tp *TxPool) removeClaimTx(tx *types.Tx) {
+ for key, value := range tx.Entries {
+ switch value.(type) {
+ case *bc.Claim:
+ delete(tp.claimTx, key)
+ default:
+ continue
+ }
+ }
+}
+
func (tp *TxPool) addOrphan(txD *TxDesc, requireParents []*bc.Hash) error {
if len(tp.orphans) >= maxOrphanNum {
return ErrPoolIsFull
tx := txD.Tx
txD.Added = time.Now()
tp.pool[tx.ID] = txD
+ // 增加一个claim id 到到claim pool中
+ tp.addClaimTx(tx)
for _, id := range tx.ResultIds {
output, err := tx.Output(*id)
if err != nil {
"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"
return errors.New("pegin-no-witness")
}
- if IsValidPeginWitness(stack, *spentOutput) == nil {
- return errors.New("PeginWitness invalid")
+ if err := IsValidPeginWitness(stack, *spentOutput); err != nil {
+ return err
}
- // 判断cliamd的输入是否已经被用
+ // 判断cliam tx的输入是否已经被用
eq, err := spentOutput.Source.Value.Equal(e.WitnessDestination.Value)
if err != nil {
}
type MerkleBlock struct {
- BlockHeader types.BlockHeader `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"`
+ 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) {
+ /*
+ assetID := bc.AssetID{}
+ assetID.V0 = prevout.Source.Value.AssetId.GetV0()
+ assetID.V1 = prevout.Source.Value.AssetId.GetV1()
+ assetID.V2 = prevout.Source.Value.AssetId.GetV2()
+ assetID.V3 = prevout.Source.Value.AssetId.GetV3()
+ //bytomPrevout.Source.Value.AssetId = &assetId
+
+ sourceID := bc.Hash{}
+ sourceID.V0 = prevout.Source.Ref.GetV0()
+ sourceID.V1 = prevout.Source.Ref.GetV1()
+ sourceID.V2 = prevout.Source.Ref.GetV2()
+ sourceID.V3 = prevout.Source.Ref.GetV3()
+ */
+
+ 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")
}
if err != nil {
return err
}
- if consensus.MoneyRange(amount) {
+ if !consensus.MoneyRange(amount) {
return errors.New("Amount out of range")
}
- if len(peginWitness[1]) != 32 {
+ if len(peginWitness[1]) != 64 {
return errors.New("The length of gennesisBlockHash is not correct")
}
claimScript := peginWitness[2]
- var rawTx types.Tx
- err = json.Unmarshal(peginWitness[3], &rawTx)
+ rawTx := &bytomtypes.Tx{}
+ err = rawTx.UnmarshalText(peginWitness[3])
if err != nil {
return err
}
- var merkleBlock MerkleBlock
- err = json.Unmarshal(peginWitness[4], &merkleBlock)
+
+ merkleBlock := &MerkleBlock{}
+ err = json.Unmarshal(peginWitness[4], merkleBlock)
if err != nil {
return err
}
for flag := range merkleBlock.Flags {
flags = append(flags, uint8(flag))
}
- if !types.ValidateTxMerkleTreeProof(merkleBlock.TxHashes, flags, merkleBlock.MatchedTxIDs, merkleBlock.BlockHeader.BlockCommitment.TransactionsMerkleRoot) {
+ 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")
}
- var txHash bc.Hash = rawTx.ID
+
// 交易进行验证
- if !checkPeginTx(&rawTx, &prevout, amount, claimScript) {
- return errors.New("check PeginTx fail")
+ if err = checkPeginTx(rawTx, bytomPrevout, amount, claimScript); err != nil {
+ return err
}
- // Check that the merkle proof corresponds to the txid
- if txHash != *prevout.Source.Ref {
- return errors.New("prevout hash don't match")
- }
// Check the genesis block corresponds to a valid peg (only one for now)
if !bytes.Equal(peginWitness[1], []byte(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(merkleBlock.BlockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
+ if err := util.IsConfirmedBytomBlock(blockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
return err
}
}
return nil
}
-func checkPeginTx(rawTx *types.Tx, prevout *bc.Output, claimAmount uint64, claimScript []byte) bool {
- // Check that transaction matches txid
- if rawTx.ID != *prevout.Source.Ref {
- return false
- }
+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 false
+ 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)
+ //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 false
+ return err
}
- if bytes.Equal(rawTx.Outputs[prevout.Source.Position].ControlProgram, controlProg) {
- return false
+ 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 true
+ return nil
}
func checkValidSrc(vstate *validationState, vs *bc.ValueSource) error {
--- /dev/null
+package main
+
+import (
+ "encoding/json"
+ "errors"
+ "io/ioutil"
+ "net/http"
+)
+
+type RespMsg struct {
+ MainchainAddress string `json:"mainchain_address,omitempty"`
+ ControlProgram string `json:"control_program,omitempty"`
+ ClaimScript string `json:"claim_script,omitempty"`
+}
+
+type Response struct {
+ Code int `json:"code,omitempty"`
+ Msg string `json:"msg,omitempty"`
+ Data string `json:"data,omitempty"`
+}
+
+func getPeginInfo() (map[string]string, error) {
+ resp, err := http.Get("http://127.0.0.1:8000/api/get_pegin_address")
+ if err != nil {
+ return nil, err
+ }
+ if resp.StatusCode < 200 || resp.StatusCode >= 300 {
+ return nil, errors.New("connect fail")
+ }
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ rep := Response{}
+ err = json.Unmarshal(body, &rep)
+ if err != nil {
+ return nil, err
+ }
+ var msg []RespMsg
+ err = json.Unmarshal([]byte(rep.Data), &msg)
+ if err != nil {
+ return nil, err
+ }
+ mapMsg := make(map[string]string)
+ for _, m := range msg {
+ mapMsg[m.ClaimScript] = m.ControlProgram
+ }
+ return mapMsg, nil
+}
--- /dev/null
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "log"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/spf13/cobra"
+ "github.com/vapor/config"
+ chainjson "github.com/vapor/encoding/json"
+ bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
+ "github.com/vapor/util"
+)
+
+var lock sync.Mutex
+var gClaimTxMap map[uint64]claimTx
+var currentHeight uint64
+
+type WSRequest struct {
+ Topic string `json:"topic"`
+}
+
+type WSResponse struct {
+ NotificationType string `json:"notification_type"`
+ Data interface{} `json:"data"`
+ ErrorDetail string `json:"error_detail,omitempty"`
+}
+
+type claimTx 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"`
+}
+
+var startHeight uint64 = 0
+
+var runCmd = &cobra.Command{
+ Use: "run",
+ Short: "monitor claim tx",
+ Run: run,
+}
+
+func init() {
+ runCmd.PersistentFlags().Uint64Var(&startHeight, "start_height", 0, "Start monitoring block height for transactions")
+}
+
+func run(cmd *cobra.Command, args []string) {
+
+}
+
+func main() {
+
+ if _, err := runCmd.ExecuteC(); err != nil {
+ os.Exit(util.ErrLocalExe)
+ }
+
+ gClaimTxMap = make(map[uint64]claimTx)
+ currentHeight = 0
+ client := &WSClient{}
+ if err := client.New("127.0.0.1:9888"); err != nil {
+ log.Println(err)
+ return
+ }
+ go sendClaimTx()
+ go getRawTransactionWithHeight()
+ req := WSRequest{
+ Topic: "notify_raw_blocks",
+ }
+ client.SendData(req)
+
+ for {
+ msg, err := client.RecvData()
+ if err != nil {
+ fmt.Println(err)
+ break
+ }
+ var rep WSResponse
+ err = json.Unmarshal(msg, &rep)
+ if err != nil {
+ log.Printf("Unmarshal error:", err)
+ }
+
+ block := &bytomtypes.Block{}
+ switch rep.NotificationType {
+ case "raw_blocks_connected":
+ data := fmt.Sprint(rep.Data)
+ err = block.UnmarshalText([]byte(data))
+ if err != nil {
+ block = nil
+ }
+ case "raw_blocks_disconnected":
+ data := fmt.Sprint(rep.Data)
+ err = block.UnmarshalText([]byte(data))
+ if err != nil {
+ block = nil
+ }
+ case "request_status":
+ if rep.ErrorDetail != "" {
+ log.Println(rep.ErrorDetail)
+ }
+ block = nil
+ default:
+ block = nil
+ }
+ if block != nil {
+ currentHeight = block.Height
+ err := getRawTransaction(block)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+ }
+}
+
+func sendClaimTx() {
+ for {
+ // 存储tx到数据库、列表中
+ for k, v := range gClaimTxMap {
+ if k <= currentHeight {
+ resp, exitCode := util.ClientCall("/claim-pegin-transaction", &v)
+ if exitCode != util.Success {
+ lock.Lock()
+ delete(gClaimTxMap, k)
+ lock.Unlock()
+ continue
+ }
+ type txID struct {
+ Txid string `json:"tx_id"`
+ }
+ var out txID
+ restoreStruct(resp, &out)
+ lock.Lock()
+ delete(gClaimTxMap, k)
+ lock.Unlock()
+ fmt.Println(out.Txid)
+ time.Sleep(3 * time.Second)
+ }
+ }
+ }
+
+}
+
+func restoreStruct(data interface{}, out interface{}) {
+ dataMap, ok := data.(map[string]interface{})
+ if ok != true {
+ fmt.Println("invalid type assertion")
+ os.Exit(util.ErrLocalParse)
+ }
+
+ rawData, err := json.MarshalIndent(dataMap, "", " ")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(util.ErrLocalParse)
+ }
+ json.Unmarshal(rawData, out)
+}
+
+func getRawTransaction(block *bytomtypes.Block) error {
+ peginInfo, err := getPeginInfo()
+ if err != nil {
+ return err
+ }
+ for _, tx := range block.Transactions {
+ for _, output := range tx.Outputs {
+ for k, v := range peginInfo {
+ var claimScript chainjson.HexBytes
+ if err := claimScript.UnmarshalText([]byte(k)); err != nil {
+ return err
+ }
+ var controlProgram chainjson.HexBytes
+ if err := controlProgram.UnmarshalText([]byte(v)); err != nil {
+ return err
+ }
+
+ if !bytes.Equal(output.ControlProgram, controlProgram) {
+ continue
+ }
+ blockHash := block.Hash()
+ merkleProof, err := getMerkleProof(blockHash.String(), tx.ID.String())
+ if err != nil {
+ return err
+ }
+ tmp := claimTx{
+ Password: "123456",
+ RawTx: *tx,
+ BlockHeader: merkleProof.BlockHeader,
+ TxHashes: merkleProof.TxHashes,
+ StatusHashes: merkleProof.StatusHashes,
+ Flags: merkleProof.Flags,
+ MatchedTxIDs: merkleProof.MatchedTxIDs,
+ ClaimScript: claimScript,
+ }
+ // 存储tx到数据库、列表中
+ height := block.Height + 6
+ lock.Lock()
+ gClaimTxMap[height] = tmp
+ lock.Unlock()
+ }
+ }
+ }
+
+ return nil
+}
+
+func getRawTransactionWithHeight() {
+ for {
+ if currentHeight > 0 {
+ num := currentHeight - startHeight
+ for i := uint64(0); i < num; i++ {
+ block, err := getBlockWithHeight(startHeight)
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = getRawTransaction(&block)
+ if err != nil {
+ log.Fatal(err)
+ }
+ startHeight += 1
+ }
+ if startHeight >= currentHeight {
+ break
+ }
+ }
+ time.Sleep(1 * time.Second)
+ }
+}
+
+type MerkleBlockResp struct {
+ 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"`
+}
+
+func getMerkleProof(blockHash string, txId string) (MerkleBlockResp, error) {
+ //body_json = {"tx_id": tx_id,"block_hash": block_hash}
+ type Req struct {
+ TxID string `json:"tx_id"`
+ BlockHash string `json:"block_hash"`
+ }
+ util.MainchainConfig = &config.MainChainRpcConfig{
+ MainchainRpcHost: "127.0.0.1",
+ MainchainRpcPort: "9888",
+ }
+ var blockHeader MerkleBlockResp
+ resp, err := util.CallRPC("/get-merkle-proof", &Req{TxID: txId, BlockHash: blockHash})
+ if err != nil {
+ return blockHeader, err
+ }
+ tmp, _ := json.Marshal(resp)
+
+ json.Unmarshal(tmp, &blockHeader)
+
+ return blockHeader, nil
+}
+
+func getBlockWithHeight(blockHeight uint64) (bytomtypes.Block, error) {
+ type Req struct {
+ BlockHeight uint64 `json:"block_height"`
+ }
+ util.MainchainConfig = &config.MainChainRpcConfig{
+ MainchainRpcHost: "127.0.0.1",
+ MainchainRpcPort: "9888",
+ }
+ type RawBlockResp struct {
+ RawBlock *bytomtypes.Block `json:"raw_block"`
+ }
+ var block RawBlockResp
+ resp, err := util.CallRPC("/get-raw-block", &Req{BlockHeight: blockHeight})
+ if err != nil {
+ return *block.RawBlock, err
+ }
+ tmp, _ := json.Marshal(resp)
+
+ json.Unmarshal(tmp, &block)
+ return *block.RawBlock, nil
+}
--- /dev/null
+package main
+
+import (
+ "encoding/json"
+ "net/url"
+
+ "github.com/gorilla/websocket"
+)
+
+type WSClient struct {
+ Conn *websocket.Conn
+}
+
+func (WS *WSClient) New(host string) error {
+ u := url.URL{Scheme: "ws", Host: host, Path: "/websocket-subscribe"}
+ c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
+ if err != nil {
+ return err
+ }
+ WS.Conn = c
+ return nil
+}
+
+func (WS *WSClient) SendData(req interface{}) {
+ msg, _ := json.Marshal(req)
+ WS.Conn.WriteMessage(websocket.TextMessage, msg)
+}
+
+func (WS *WSClient) RecvData() ([]byte, error) {
+ _, msg, err := WS.Conn.ReadMessage()
+ return msg, err
+}
import requests
import json
+from websocket import create_connection
class Connection(object):
@staticmethod
def generate():
return Connection("http://127.0.0.1:9888")
+
+
+class WSClient(object):
+ def __init__(self, url):
+ self.ws = create_connection(url)
+
+ def send(self, data):
+ self.ws.send(data)
+
+ def recv(self):
+ return self.ws.recv()
+
+ def close(self):
+ self.ws.close()
#from sqlalchemy.exc import SQLAlchemyError, IntegrityError
from . import api
-from .Connection import Connection
+from .Connection import Connection, WSClient
from .. import db
from ..models import KeyPair, PeginAddress
accountID = request.json['account_id']
connSide = Connection("http://127.0.0.1:8888")
body_json = {"account_id": accountID}
- response = connSide.request("/get-pegin-address",body_json)
+ response = connSide.request("/get-pegin-contract-address",body_json)
resp_json = json.loads(response.text)
if resp_json['status'] == 'success':
mainchain_address = resp_json['data']['mainchain_address']
+ control_program = resp_json['data']['control_program']
claim_script = resp_json['data']['claim_script']
- pegin = PeginAddress(address=mainchain_address, claim_script=claim_script)
+ pegin = PeginAddress(address=mainchain_address, control_program=control_program, claim_script=claim_script)
db.session.add(pegin)
db.session.commit()
elif resp_json['status'] == 'fail':
for peginAddr in peginAddrs:
data = {
"mainchain_address":peginAddr.address.encode('utf-8'),
+ "control_program":peginAddr.control_program.encode('utf-8'),
"claim_script": peginAddr.claim_script.encode('utf-8')
}
json_data = json_data + json.dumps(data)
@api.route('/claim_tx', methods=['GET', 'POST', 'OPTIONS'])
def claim_tx():
- print request.json
if not request.json or not 'claim_script' in request.json or not 'block_height' in request.json or not 'tx_id' in request.json or not 'password' in request.json:
return json_contents(jsonify(code=-1, msg="The json format is incorrect"))
block_height = int(request.json['block_height'])
if resp_json['status'] == 'success':
raw_block = resp_json['data']['raw_block'].encode('utf-8')
elif resp_json['status'] == 'fail':
- return json_contents(jsonify(code=-1, msg="get-raw-block: " + resp_json['msg']))
+ print resp_json
+ return json_contents(jsonify(code=-1, msg="get-raw-block: " + resp_json['error_detail']))
else:
return json_contents(jsonify(code=-1, msg="get raw block fail"))
raw_transaction = resp_json['data']['raw_transaction'].encode('utf-8')
block_hash = resp_json['data']['block_hash'].encode('utf-8')
elif resp_json['status'] == 'fail':
- return json_contents(jsonify(code=-1, msg="get-raw-transaction: " + resp_json['msg']))
+ print resp_json
+ return json_contents(jsonify(code=-1, msg="get-raw-transaction: " + resp_json['error_detail']))
else:
return json_contents(jsonify(code=-1, msg="get raw transaction fail"))
# 主链获取proof
+ print block_hash
body_json = {"tx_id": tx_id,"block_hash": block_hash}
response = connMain.request("/get-merkle-proof",body_json)
resp_json = json.loads(response.text)
if resp_json['status'] == 'success':
proof = json.dumps(resp_json['data']).strip('{}')
elif resp_json['status'] == 'fail':
- return json_contents(jsonify(code=-1, msg="get-merkle-proof:" + resp_json['msg']))
+ print resp_json
+ return json_contents(jsonify(code=-1, msg="get-merkle-proof:" + resp_json['error_detail']))
else:
return json_contents(jsonify(code=-1, msg="get raw transaction fail"))
if resp_json['status'] == 'success':
return json_contents(jsonify(code=200, msg=resp_json['data']))
elif resp_json['status'] == 'fail':
- return json_contents(jsonify(code=-1, msg="claim-pegin-transaction: " + resp_json['msg']))
+ print resp_json
+ return json_contents(jsonify(code=-1, msg="claim-pegin-transaction: " + resp_json['error_detail']))
else:
return json_contents(jsonify(code=-1, msg="claim pegin transaction fail"))
return json_contents(jsonify(code=-1, msg="get side raw transaction fail"))
# 构建主链交易
- body_json = '{"claim_script":"%s","raw_transaction": "%s","alias": "%s","control_program":"%s","root_xpubs":%s,%s}' % (claim_script,raw_transaction,alias,control_program,root_xpubs,utxo)
- print body_json
+ body_json = '{"claim_script":"%s","raw_transaction": "%s","control_program":"%s","root_xpubs":%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 = ""
return json_contents(jsonify(code=-1, msg="build mainchain transaction fail"))
# 签名
- #xpubs = request.json['root_xpubs']
- #xprvs = request.json['xprvs']
- #for index in range(len(xpubs)):
for key,value in key_pair.items():
- #xprv = request.json['xprv'].encode('utf-8')
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':
+ tmpl = json.dumps(resp_json['data']['transaction'])
raw_transaction = resp_json['data']['transaction']['raw_transaction'].encode('utf-8')
elif resp_json['status'] == 'fail':
return json_contents(jsonify(code=-1, msg="sign-with-key: " + resp_json['msg']))
body_json = '{"raw_transaction": "%s"}' % (raw_transaction)
response = connMain.request("/submit-transaction",json.loads(body_json))
resp_json = json.loads(response.text.encode('utf-8'))
+ print resp_json
if resp_json['status'] == 'success':
return json_contents(jsonify(code=200, msg=resp_json['data']))
elif resp_json['status'] == 'fail':
__tablename__ = 'pegin_address'
id = db.Column(db.Integer, primary_key=True)
address = db.Column(db.String, nullable=True, unique=True)
+ control_program = db.Column(db.String, nullable=True, unique=True)
claim_script = db.Column(db.String, nullable=True, unique=True)
class TxInfo(db.Model):
id = db.Column(db.Integer, primary_key=True)
block_height = db.Column(db.Integer, nullable=True, unique=True)
txid_main = db.Column(db.String, nullable=True, unique=True)
- txid_claim = db.Column(db.String, nullable=True, unique=True)
\ No newline at end of file
+ txid_claim = db.Column(db.String, nullable=True, unique=True)
./vapor init --chain_id solonet -r "side_chain"
nohup ./vapor node -r "side_chain" > /dev/null &
sleep 30
-curl -s -X POST -d '{}' http://127.0.0.1:8888/create-key-pair > key_pair
+curl -s -X POST -d '{}' http://127.0.0.1:8888/create-key-pair >> key_pair
ps -ef | grep vapor | grep -v grep | awk '{print $2}' |xargs kill -9
rm -rf side_chain
fi
touch install
fi
-nohup python manager.py runserver -p 8080 -h 0.0.0.0 > /dev/null &
+nohup python manager.py runserver -p 8000 -h 0.0.0.0 > /dev/null &
sleep 30
cd web
-nohup python -m SimpleHTTPServer 80 > /dev/null &
+nohup python -m SimpleHTTPServer 8080 > /dev/null &