OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / protocol / validation / tx.go
index 421cc8a..e81fe11 100644 (file)
@@ -1,24 +1,16 @@
 package validation
 
 import (
-       "bytes"
-       "encoding/json"
        "fmt"
        "math"
-       "strconv"
 
+       "github.com/vapor/claim"
        "github.com/vapor/consensus"
        "github.com/vapor/consensus/segwit"
-       "github.com/vapor/crypto"
-       "github.com/vapor/equity/pegin_contract"
        "github.com/vapor/errors"
        "github.com/vapor/math/checked"
        "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-       bytomtypes "github.com/vapor/protocol/bc/types/bytom/types"
        "github.com/vapor/protocol/vm"
-       "github.com/vapor/protocol/vm/vmutil"
-       "github.com/vapor/util"
 )
 
 // validate transaction error
@@ -148,6 +140,11 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
        case *bc.Mux:
                parity := make(map[bc.AssetID]int64)
                for i, src := range e.Sources {
+                       _, ok := vs.tx.Entries[*src.Ref]
+                       if !ok {
+                               return errors.Wrapf(bc.ErrMissingEntry, "entry for bytom input %x not found", *src.Ref)
+                       }
+
                        if src.Value.Amount > math.MaxInt64 {
                                return errors.WithDetailf(ErrOverflow, "amount %d exceeds maximum value 2^63", src.Value.Amount)
                        }
@@ -188,7 +185,6 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        if !ok {
                                return errors.Wrapf(bc.ErrMissingEntry, "entry for bytom input %x not found", BTMInputID)
                        }
-
                        vs2 := *vs
                        vs2.entryID = BTMInputID
                        if err := checkValid(&vs2, e); err != nil {
@@ -260,7 +256,6 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                if err != nil {
                        return errors.Wrap(err, "getting spend prevout")
                }
-
                gasLeft, err := vm.Verify(NewTxVMContext(vs, e, spentOutput.ControlProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
                if err != nil {
                        return errors.Wrap(err, "checking control program")
@@ -326,12 +321,12 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        return errors.New("pegin-no-witness")
                }
 
-               if err := IsValidPeginWitness(stack, *spentOutput); err != nil {
+               // 根据claim链类型选择验证类型
+               validation := &claim.BytomClaimValidation{}
+               if err := validation.IsValidPeginWitness(stack, *spentOutput); err != nil {
                        return err
                }
 
-               // 判断cliam tx的输入是否已经被用
-
                eq, err := spentOutput.Source.Value.Equal(e.WitnessDestination.Value)
                if err != nil {
                        return err
@@ -360,130 +355,6 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
        return nil
 }
 
-type MerkleBlock struct {
-       BlockHeader  []byte     `json:"block_header"`
-       TxHashes     []*bc.Hash `json:"tx_hashes"`
-       StatusHashes []*bc.Hash `json:"status_hashes"`
-       Flags        []uint32   `json:"flags"`
-       MatchedTxIDs []*bc.Hash `json:"matched_tx_ids"`
-}
-
-func IsValidPeginWitness(peginWitness [][]byte, prevout bc.Output) (err error) {
-       /*
-               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")
-       }
-       amount, err := strconv.ParseUint(string(peginWitness[0]), 10, 64)
-       if err != nil {
-               return err
-       }
-       if !consensus.MoneyRange(amount) {
-               return errors.New("Amount out of range")
-       }
-
-       if len(peginWitness[1]) != 64 {
-               return errors.New("The length of gennesisBlockHash is not correct")
-       }
-
-       claimScript := peginWitness[2]
-
-       rawTx := &bytomtypes.Tx{}
-       err = rawTx.UnmarshalText(peginWitness[3])
-       if err != nil {
-               return err
-       }
-
-       merkleBlock := &MerkleBlock{}
-       err = json.Unmarshal(peginWitness[4], merkleBlock)
-       if err != nil {
-               return err
-       }
-       // proof验证
-       var flags []uint8
-       for flag := range merkleBlock.Flags {
-               flags = append(flags, uint8(flag))
-       }
-       blockHeader := &bytomtypes.BlockHeader{}
-       if err = blockHeader.UnmarshalText(merkleBlock.BlockHeader); err != nil {
-               return err
-       }
-
-       if !types.ValidateTxMerkleTreeProof(merkleBlock.TxHashes, flags, merkleBlock.MatchedTxIDs, blockHeader.BlockCommitment.TransactionsMerkleRoot) {
-               return errors.New("Merkleblock validation failed")
-       }
-
-       // 交易进行验证
-       if err = checkPeginTx(rawTx, bytomPrevout, amount, claimScript); err != nil {
-               return err
-       }
-
-       // 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(blockHeader.Height, consensus.ActiveNetParams.PeginMinDepth); err != nil {
-                       return err
-               }
-       }
-
-       return nil
-}
-
-func checkPeginTx(rawTx *bytomtypes.Tx, prevout *bc.Output, claimAmount uint64, claimScript []byte) error {
-       // Check the transaction nout/value matches
-       amount := rawTx.Outputs[prevout.Source.Position].Amount
-       if claimAmount != amount {
-               return errors.New("transaction nout/value do not matches")
-       }
-       // Check that the witness program matches the p2ch on the p2sh-p2wsh transaction output
-       //federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
-       //scriptHash := crypto.Sha256(federationRedeemScript)
-       peginContractPrograms, err := pegin_contract.GetPeginContractPrograms(claimScript)
-       if err != nil {
-               return err
-       }
-
-       scriptHash := crypto.Sha256(peginContractPrograms)
-       controlProg, err := vmutil.P2WSHProgram(scriptHash)
-       if err != nil {
-               return err
-       }
-       if !bytes.Equal(rawTx.Outputs[prevout.Source.Position].ControlProgram, controlProg) {
-               return errors.New("The output control program of transaction does not match the control program of the system's alliance contract")
-       }
-       return nil
-}
-
 func checkValidSrc(vstate *validationState, vs *bc.ValueSource) error {
        if vs == nil {
                return errors.Wrap(ErrMissingField, "empty value source")