6 "github.com/bytom/vapor/consensus"
7 "github.com/bytom/vapor/protocol/bc"
8 "github.com/bytom/vapor/protocol/vm"
9 "github.com/bytom/vapor/protocol/vm/vmutil"
12 // IsP2WScript is used to determine whether it is a P2WScript or not
13 func IsP2WScript(prog []byte) bool {
14 return IsP2WPKHScript(prog) || IsP2WSHScript(prog) || IsStraightforward(prog)
17 // IsStraightforward is used to determine whether it is a Straightforward script or not
18 func IsStraightforward(prog []byte) bool {
19 insts, err := vm.ParseProgram(prog)
26 return insts[0].Op == vm.OP_TRUE || insts[0].Op == vm.OP_FAIL
29 // IsP2WPKHScript is used to determine whether it is a P2WPKH script or not
30 func IsP2WPKHScript(prog []byte) bool {
31 insts, err := vm.ParseProgram(prog)
38 if insts[0].Op > vm.OP_16 {
41 return insts[1].Op == vm.OP_DATA_20 && len(insts[1].Data) == consensus.PayToWitnessPubKeyHashDataSize
44 // IsP2WSHScript is used to determine whether it is a P2WSH script or not
45 func IsP2WSHScript(prog []byte) bool {
46 insts, err := vm.ParseProgram(prog)
53 if insts[0].Op > vm.OP_16 {
56 return insts[1].Op == vm.OP_DATA_32 && len(insts[1].Data) == consensus.PayToWitnessScriptHashDataSize
59 // IsP2WMCScript is used to determine whether it is a P2WMC script or not
60 func IsP2WMCScript(prog []byte) bool {
61 insts, err := vm.ParseProgram(prog)
70 if insts[0].Op > vm.OP_16 {
74 if insts[1].Op != vm.OP_DATA_32 || len(insts[1].Data) != 32 {
78 if !(insts[2].IsPushdata() && insts[3].IsPushdata() && insts[4].IsPushdata()) {
82 if _, err = vm.AsInt64(insts[2].Data); err != nil {
86 if _, err = vm.AsInt64(insts[3].Data); err != nil {
90 if !IsP2WScript(insts[4].Data) {
94 return insts[5].Op == vm.OP_DATA_32 && len(insts[5].Data) == 32
97 // ConvertP2PKHSigProgram convert standard P2WPKH program into P2PKH program
98 func ConvertP2PKHSigProgram(prog []byte) ([]byte, error) {
99 insts, err := vm.ParseProgram(prog)
103 if insts[0].Op == vm.OP_0 {
104 return vmutil.P2PKHSigProgram(insts[1].Data)
106 return nil, errors.New("unknow P2PKH version number")
109 // ConvertP2SHProgram convert standard P2WSH program into P2SH program
110 func ConvertP2SHProgram(prog []byte) ([]byte, error) {
111 insts, err := vm.ParseProgram(prog)
115 if insts[0].Op == vm.OP_0 {
116 return vmutil.P2SHProgram(insts[1].Data)
118 return nil, errors.New("unknow P2SHP version number")
121 // ConvertP2MCProgram convert standard P2WMC program into P2MC program
122 func ConvertP2MCProgram(prog []byte) ([]byte, error) {
123 magneticContractArgs, err := DecodeP2WMCProgram(prog)
127 return vmutil.P2MCProgram(*magneticContractArgs)
130 // DecodeP2WMCProgram parse standard P2WMC arguments to magneticContractArgs
131 func DecodeP2WMCProgram(prog []byte) (*vmutil.MagneticContractArgs, error) {
132 if !IsP2WMCScript(prog) {
133 return nil, errors.New("invalid P2MC program")
136 insts, err := vm.ParseProgram(prog)
141 magneticContractArgs := &vmutil.MagneticContractArgs{
142 SellerProgram: insts[4].Data,
143 SellerKey: insts[5].Data,
145 requestedAsset := [32]byte{}
146 copy(requestedAsset[:], insts[1].Data)
147 magneticContractArgs.RequestedAsset = bc.NewAssetID(requestedAsset)
149 if magneticContractArgs.RatioNumerator, err = vm.AsInt64(insts[2].Data); err != nil {
153 if magneticContractArgs.RatioDenominator, err = vm.AsInt64(insts[3].Data); err != nil {
157 return magneticContractArgs, nil
160 // GetHashFromStandardProg get hash from standard program
161 func GetHashFromStandardProg(prog []byte) ([]byte, error) {
162 insts, err := vm.ParseProgram(prog)
167 return insts[1].Data, nil