8 bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
9 "github.com/vapor/consensus"
10 "github.com/vapor/crypto"
11 "github.com/vapor/equity/pegin_contract"
12 "github.com/vapor/errors"
13 "github.com/vapor/protocol/bc"
14 "github.com/vapor/protocol/bc/types"
15 "github.com/vapor/protocol/vm/vmutil"
16 "github.com/vapor/util"
19 type MerkleBlock struct {
20 BlockHeader []byte `json:"block_header"`
21 TxHashes []*bc.Hash `json:"tx_hashes"`
22 StatusHashes []*bc.Hash `json:"status_hashes"`
23 Flags []uint32 `json:"flags"`
24 MatchedTxIDs []*bc.Hash `json:"matched_tx_ids"`
27 type BytomClaimValidation struct {
30 func (b *BytomClaimValidation) IsValidPeginWitness(peginWitness [][]byte, prevout bc.Output) (err error) {
32 assetAmount := &bc.AssetAmount{
33 AssetId: prevout.Source.Value.AssetId,
34 Amount: prevout.Source.Value.Amount,
37 src := &bc.ValueSource{
38 Ref: prevout.Source.Ref,
40 Position: prevout.Source.Position,
42 prog := &bc.Program{prevout.ControlProgram.VmVersion, prevout.ControlProgram.Code}
43 bytomPrevout := bc.NewOutput(src, prog, prevout.Source.Position)
45 if len(peginWitness) != 5 {
46 return errors.New("peginWitness is error")
48 amount, err := strconv.ParseUint(string(peginWitness[0]), 10, 64)
52 if !consensus.MoneyRange(amount) {
53 return errors.New("Amount out of range")
56 if len(peginWitness[1]) != 32 {
57 return errors.New("The length of gennesisBlockHash is not correct")
60 claimScript := peginWitness[2]
62 rawTx := &bytomtypes.Tx{}
63 err = rawTx.UnmarshalText(peginWitness[3])
68 merkleBlock := &MerkleBlock{}
69 err = json.Unmarshal(peginWitness[4], merkleBlock)
75 for flag := range merkleBlock.Flags {
76 flags = append(flags, uint8(flag))
78 blockHeader := &bytomtypes.BlockHeader{}
79 if err = blockHeader.UnmarshalText(merkleBlock.BlockHeader); err != nil {
83 if !types.ValidateTxMerkleTreeProof(merkleBlock.TxHashes, flags, merkleBlock.MatchedTxIDs, blockHeader.BlockCommitment.TransactionsMerkleRoot) {
84 return errors.New("Merkleblock validation failed")
88 if err = b.checkPeginTx(rawTx, bytomPrevout, amount, claimScript); err != nil {
92 hash.UnmarshalText(peginWitness[1])
93 // Check the genesis block corresponds to a valid peg (only one for now)
94 if hash.String() != consensus.ActiveNetParams.ParentGenesisBlockHash {
95 return errors.New("ParentGenesisBlockHash don't match")
97 // TODO Finally, validate peg-in via rpc call
99 if util.ValidatePegin {
100 if err := util.IsConfirmedBytomBlock(blockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
108 func (b *BytomClaimValidation) checkPeginTx(rawTx *bytomtypes.Tx, prevout *bc.Output, claimAmount uint64, claimScript []byte) error {
109 // Check the transaction nout/value matches
110 amount := rawTx.Outputs[prevout.Source.Position].Amount
111 if claimAmount != amount {
112 return errors.New("transaction nout/value do not matches")
114 // Check that the witness program matches the p2ch on the p2sh-p2wsh transaction output
115 //federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
116 //scriptHash := crypto.Sha256(federationRedeemScript)
117 peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(claimScript)
122 scriptHash := crypto.Sha256(peginContractPrograms)
123 controlProg, err := vmutil.P2WSHProgram(scriptHash)
127 if !bytes.Equal(rawTx.Outputs[prevout.Source.Position].ControlProgram, controlProg) {
128 return errors.New("The output control program of transaction does not match the control program of the system's alliance contract")