github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/consensus/bcrp/bcrp.go (about)

     1  package bcrp
     2  
     3  import (
     4  	"bytes"
     5  
     6  	"github.com/bytom/bytom/consensus"
     7  	"github.com/bytom/bytom/errors"
     8  	"github.com/bytom/bytom/protocol/vm"
     9  )
    10  
    11  const (
    12  	// BCRP bytom contract register protocol
    13  	BCRP = "bcrp"
    14  	// Version bcrp version
    15  	Version = 1
    16  )
    17  
    18  // IsBCRPScript checks if a control program is bytom contract register protocol
    19  // BCRP script format: OP_FAIL + OP_DATA_4 + "bcrp" + OP_DATA_1 + "1" + {{dynamic_op}} + contract
    20  // 0 < len(contract) <= 75       dynamic_op -> OP_DATA_N
    21  // 75 <len(contract) < 256       dynamic_op -> OP_PUSHDATA1
    22  // 256 <= len(contract) < 65536  dynamic_op -> OP_PUSHDATA2
    23  // len(contract) >= 65536        dynamic_op -> OP_PUSHDATA4
    24  func IsBCRPScript(prog []byte) bool {
    25  	inst, err := vm.ParseProgram(prog)
    26  	if err != nil {
    27  		return false
    28  	}
    29  
    30  	if len(inst) != 4 {
    31  		return false
    32  	}
    33  
    34  	if inst[0].Op != vm.OP_FAIL {
    35  		return false
    36  	}
    37  
    38  	if inst[1].Op != vm.OP_DATA_4 || !bytes.Equal(inst[1].Data, []byte(BCRP)) {
    39  		return false
    40  	}
    41  
    42  	if inst[2].Op != vm.OP_DATA_1 || !bytes.Equal(inst[2].Data, []byte{byte(Version)}) {
    43  		return false
    44  	}
    45  
    46  	return len(inst[3].Data) > 0
    47  }
    48  
    49  // IsCallContractScript checks if a program is script call contract registered by BCRP
    50  // call contract script format: OP_DATA_4 + "bcrp"+ OP_DATA_32 + SHA3-256(contract)
    51  func IsCallContractScript(prog []byte) bool {
    52  	insts, err := vm.ParseProgram(prog)
    53  	if err != nil {
    54  		return false
    55  	}
    56  
    57  	if len(insts) != 2 {
    58  		return false
    59  	}
    60  
    61  	if insts[0].Op != vm.OP_DATA_4 || !bytes.Equal(insts[0].Data, []byte(BCRP)) {
    62  		return false
    63  	}
    64  
    65  	return insts[1].Op == vm.OP_DATA_32 && len(insts[1].Data) == consensus.BCRPContractHashDataSize
    66  }
    67  
    68  // ParseContract parse contract from BCRP script
    69  // BCRP script format: OP_FAIL + OP_DATA_4 + "bcrp" + OP_DATA_1 + "1" + {{dynamic_op}} + contract
    70  func ParseContract(prog []byte) ([]byte, error) {
    71  	insts, err := vm.ParseProgram(prog)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	if len(insts) != 4 {
    77  		return nil, errors.New("unsupport program")
    78  	}
    79  
    80  	return insts[3].Data, nil
    81  }
    82  
    83  // ParseContractHash parse contract hash from call BCRP script
    84  // call contract script format: OP_DATA_4 + "bcrp"+ OP_DATA_32 + SHA3-256(contract)
    85  func ParseContractHash(prog []byte) ([32]byte, error) {
    86  	insts, err := vm.ParseProgram(prog)
    87  	if err != nil {
    88  		return [32]byte{}, err
    89  	}
    90  
    91  	if len(insts) != 2 {
    92  		return [32]byte{}, errors.New("unsupport program")
    93  	}
    94  
    95  	var hash [32]byte
    96  	copy(hash[:], insts[1].Data)
    97  
    98  	return hash, nil
    99  }