OSDN Git Service

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