OSDN Git Service

066ceef601a6a13530ca003ab3bf810c91052e49
[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         ReferenceData json.Map  `json:"reference_data"`
30 }
31
32 func (a *controlReceiverAction) Build(ctx context.Context, b *TemplateBuilder) error {
33         var missing []string
34         if a.Receiver == nil {
35                 missing = append(missing, "receiver")
36         } else {
37                 if len(a.Receiver.ControlProgram) == 0 {
38                         missing = append(missing, "receiver.control_program")
39                 }
40         }
41         if a.AssetId.IsZero() {
42                 missing = append(missing, "asset_id")
43         }
44         if len(missing) > 0 {
45                 return MissingFieldsError(missing...)
46         }
47
48         out := legacy.NewTxOutput(*a.AssetId, a.Amount, a.Receiver.ControlProgram, a.ReferenceData)
49         return b.AddOutput(out)
50 }
51
52 // DecodeControlAddressAction convert input data to action struct
53 func DecodeControlAddressAction(data []byte) (Action, error) {
54         a := new(controlAddressAction)
55         err := stdjson.Unmarshal(data, a)
56         return a, err
57 }
58
59 type controlAddressAction struct {
60         bc.AssetAmount
61         Address       string   `json:"address"`
62         ReferenceData json.Map `json:"reference_data"`
63 }
64
65 func (a *controlAddressAction) Build(ctx context.Context, b *TemplateBuilder) error {
66         var missing []string
67         if a.Address == "" {
68                 missing = append(missing, "address")
69         }
70         if a.AssetId.IsZero() {
71                 missing = append(missing, "asset_id")
72         }
73         if len(missing) > 0 {
74                 return MissingFieldsError(missing...)
75         }
76
77         address, err := common.DecodeAddress(a.Address, &consensus.MainNetParams)
78         if err != nil {
79                 return err
80         }
81         redeemContract := address.ScriptAddress()
82         program := []byte{}
83
84         switch address.(type) {
85         case *common.AddressWitnessPubKeyHash:
86                 program, err = vmutil.P2WPKHProgram(redeemContract)
87         case *common.AddressWitnessScriptHash:
88                 program, err = vmutil.P2WSHProgram(redeemContract)
89         default:
90                 return errors.New("unsupport address type")
91         }
92         if err != nil {
93                 return err
94         }
95
96         out := legacy.NewTxOutput(*a.AssetId, a.Amount, program, a.ReferenceData)
97         return b.AddOutput(out)
98 }
99
100 // DecodeControlProgramAction convert input data to action struct
101 func DecodeControlProgramAction(data []byte) (Action, error) {
102         a := new(controlProgramAction)
103         err := stdjson.Unmarshal(data, a)
104         return a, err
105 }
106
107 type controlProgramAction struct {
108         bc.AssetAmount
109         Program       json.HexBytes `json:"control_program"`
110         ReferenceData json.Map      `json:"reference_data"`
111 }
112
113 func (a *controlProgramAction) Build(ctx context.Context, b *TemplateBuilder) error {
114         var missing []string
115         if len(a.Program) == 0 {
116                 missing = append(missing, "control_program")
117         }
118         if a.AssetId.IsZero() {
119                 missing = append(missing, "asset_id")
120         }
121         if len(missing) > 0 {
122                 return MissingFieldsError(missing...)
123         }
124
125         out := legacy.NewTxOutput(*a.AssetId, a.Amount, a.Program, a.ReferenceData)
126         return b.AddOutput(out)
127 }
128
129 // DecodeSetTxRefDataAction convert input data to action struct
130 func DecodeSetTxRefDataAction(data []byte) (Action, error) {
131         a := new(setTxRefDataAction)
132         err := stdjson.Unmarshal(data, a)
133         return a, err
134 }
135
136 type setTxRefDataAction struct {
137         Data json.Map `json:"reference_data"`
138 }
139
140 func (a *setTxRefDataAction) Build(ctx context.Context, b *TemplateBuilder) error {
141         if len(a.Data) == 0 {
142                 return MissingFieldsError("reference_data")
143         }
144         return b.setReferenceData(a.Data)
145 }
146
147 // DecodeRetireAction convert input data to action struct
148 func DecodeRetireAction(data []byte) (Action, error) {
149         a := new(retireAction)
150         err := stdjson.Unmarshal(data, a)
151         return a, err
152 }
153
154 type retireAction struct {
155         bc.AssetAmount
156         ReferenceData json.Map `json:"reference_data"`
157 }
158
159 func (a *retireAction) Build(ctx context.Context, b *TemplateBuilder) error {
160         var missing []string
161         if a.AssetId.IsZero() {
162                 missing = append(missing, "asset_id")
163         }
164         if a.Amount == 0 {
165                 missing = append(missing, "amount")
166         }
167         if len(missing) > 0 {
168                 return MissingFieldsError(missing...)
169         }
170
171         out := legacy.NewTxOutput(*a.AssetId, a.Amount, retirementProgram, a.ReferenceData)
172         return b.AddOutput(out)
173 }