github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/blockchain/txbuilder/actions.go (about)

     1  package txbuilder
     2  
     3  import (
     4  	"context"
     5  	stdjson "encoding/json"
     6  	"errors"
     7  
     8  	"github.com/bytom/bytom/common"
     9  	"github.com/bytom/bytom/consensus"
    10  	"github.com/bytom/bytom/encoding/json"
    11  	"github.com/bytom/bytom/protocol/bc"
    12  	"github.com/bytom/bytom/protocol/bc/types"
    13  	"github.com/bytom/bytom/protocol/vm/vmutil"
    14  )
    15  
    16  // DecodeControlAddressAction convert input data to action struct
    17  func DecodeControlAddressAction(data []byte) (Action, error) {
    18  	a := new(controlAddressAction)
    19  	err := stdjson.Unmarshal(data, a)
    20  	return a, err
    21  }
    22  
    23  type controlAddressAction struct {
    24  	bc.AssetAmount
    25  	Address string `json:"address"`
    26  }
    27  
    28  func (a *controlAddressAction) Build(ctx context.Context, b *TemplateBuilder) error {
    29  	var missing []string
    30  	if a.Address == "" {
    31  		missing = append(missing, "address")
    32  	}
    33  	if a.AssetId.IsZero() {
    34  		missing = append(missing, "asset_id")
    35  	}
    36  	if a.Amount == 0 {
    37  		missing = append(missing, "amount")
    38  	}
    39  	if len(missing) > 0 {
    40  		return MissingFieldsError(missing...)
    41  	}
    42  
    43  	address, err := common.DecodeAddress(a.Address, &consensus.ActiveNetParams)
    44  	if err != nil {
    45  		return err
    46  	}
    47  	redeemContract := address.ScriptAddress()
    48  	program := []byte{}
    49  
    50  	switch address.(type) {
    51  	case *common.AddressWitnessPubKeyHash:
    52  		program, err = vmutil.P2WPKHProgram(redeemContract)
    53  	case *common.AddressWitnessScriptHash:
    54  		program, err = vmutil.P2WSHProgram(redeemContract)
    55  	default:
    56  		return errors.New("unsupport address type")
    57  	}
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	out := types.NewTxOutput(*a.AssetId, a.Amount, program)
    63  	return b.AddOutput(out)
    64  }
    65  
    66  func (a *controlAddressAction) ActionType() string {
    67  	return "control_address"
    68  }
    69  
    70  // DecodeControlProgramAction convert input data to action struct
    71  func DecodeControlProgramAction(data []byte) (Action, error) {
    72  	a := new(controlProgramAction)
    73  	err := stdjson.Unmarshal(data, a)
    74  	return a, err
    75  }
    76  
    77  type controlProgramAction struct {
    78  	bc.AssetAmount
    79  	Program json.HexBytes `json:"control_program"`
    80  }
    81  
    82  func (a *controlProgramAction) Build(ctx context.Context, b *TemplateBuilder) error {
    83  	var missing []string
    84  	if len(a.Program) == 0 {
    85  		missing = append(missing, "control_program")
    86  	}
    87  	if a.AssetId.IsZero() {
    88  		missing = append(missing, "asset_id")
    89  	}
    90  	if a.Amount == 0 {
    91  		missing = append(missing, "amount")
    92  	}
    93  	if len(missing) > 0 {
    94  		return MissingFieldsError(missing...)
    95  	}
    96  
    97  	out := types.NewTxOutput(*a.AssetId, a.Amount, a.Program)
    98  	return b.AddOutput(out)
    99  }
   100  
   101  func (a *controlProgramAction) ActionType() string {
   102  	return "control_program"
   103  }
   104  
   105  // DecodeRetireAction convert input data to action struct
   106  func DecodeRetireAction(data []byte) (Action, error) {
   107  	a := new(retireAction)
   108  	err := stdjson.Unmarshal(data, a)
   109  	return a, err
   110  }
   111  
   112  type retireAction struct {
   113  	bc.AssetAmount
   114  	Arbitrary json.HexBytes `json:"arbitrary"`
   115  }
   116  
   117  func (a *retireAction) Build(ctx context.Context, b *TemplateBuilder) error {
   118  	var missing []string
   119  	if a.AssetId.IsZero() {
   120  		missing = append(missing, "asset_id")
   121  	}
   122  	if a.Amount == 0 {
   123  		missing = append(missing, "amount")
   124  	}
   125  	if len(missing) > 0 {
   126  		return MissingFieldsError(missing...)
   127  	}
   128  
   129  	program, err := vmutil.RetireProgram(a.Arbitrary)
   130  	if err != nil {
   131  		return err
   132  	}
   133  	out := types.NewTxOutput(*a.AssetId, a.Amount, program)
   134  	return b.AddOutput(out)
   135  }
   136  
   137  func (a *retireAction) ActionType() string {
   138  	return "retire"
   139  }