5 stdjson "encoding/json"
8 "golang.org/x/crypto/sha3"
10 "github.com/bytom/vapor/common"
11 cfg "github.com/bytom/vapor/config"
12 "github.com/bytom/vapor/consensus"
13 "github.com/bytom/vapor/encoding/json"
14 "github.com/bytom/vapor/protocol/bc"
15 "github.com/bytom/vapor/protocol/bc/types"
16 "github.com/bytom/vapor/protocol/vm/vmutil"
19 // DecodeControlAddressAction convert input data to action struct
20 func DecodeControlAddressAction(data []byte) (Action, error) {
21 a := new(controlAddressAction)
22 err := stdjson.Unmarshal(data, a)
26 type controlAddressAction struct {
28 Address string `json:"address"`
31 func (a *controlAddressAction) Build(ctx context.Context, b *TemplateBuilder) error {
34 missing = append(missing, "address")
36 if a.AssetId.IsZero() {
37 missing = append(missing, "asset_id")
40 missing = append(missing, "amount")
43 return MissingFieldsError(missing...)
46 address, err := common.DecodeAddress(a.Address, &consensus.ActiveNetParams)
51 redeemContract := address.ScriptAddress()
53 switch address.(type) {
54 case *common.AddressWitnessPubKeyHash:
55 program, err = vmutil.P2WPKHProgram(redeemContract)
56 case *common.AddressWitnessScriptHash:
57 program, err = vmutil.P2WSHProgram(redeemContract)
59 return errors.New("unsupport address type")
65 out := types.NewIntraChainOutput(*a.AssetId, a.Amount, program)
66 return b.AddOutput(out)
69 func (a *controlAddressAction) ActionType() string {
70 return "control_address"
73 // DecodeControlProgramAction convert input data to action struct
74 func DecodeControlProgramAction(data []byte) (Action, error) {
75 a := new(controlProgramAction)
76 err := stdjson.Unmarshal(data, a)
80 type controlProgramAction struct {
82 Program json.HexBytes `json:"control_program"`
85 func (a *controlProgramAction) Build(ctx context.Context, b *TemplateBuilder) error {
87 if len(a.Program) == 0 {
88 missing = append(missing, "control_program")
90 if a.AssetId.IsZero() {
91 missing = append(missing, "asset_id")
94 missing = append(missing, "amount")
97 return MissingFieldsError(missing...)
100 out := types.NewIntraChainOutput(*a.AssetId, a.Amount, a.Program)
101 return b.AddOutput(out)
104 func (a *controlProgramAction) ActionType() string {
105 return "control_program"
108 // DecodeRetireAction convert input data to action struct
109 func DecodeRetireAction(data []byte) (Action, error) {
110 a := new(retireAction)
111 err := stdjson.Unmarshal(data, a)
115 type retireAction struct {
117 Arbitrary json.HexBytes `json:"arbitrary"`
120 func (a *retireAction) Build(ctx context.Context, b *TemplateBuilder) error {
122 if a.AssetId.IsZero() {
123 missing = append(missing, "asset_id")
126 missing = append(missing, "amount")
128 if len(missing) > 0 {
129 return MissingFieldsError(missing...)
132 program, err := vmutil.RetireProgram(a.Arbitrary)
136 out := types.NewIntraChainOutput(*a.AssetId, a.Amount, program)
137 return b.AddOutput(out)
140 func (a *retireAction) ActionType() string {
144 // DecodeCrossOutAction convert input data to action struct
145 func DecodeCrossOutAction(data []byte) (Action, error) {
146 a := new(crossOutAction)
147 err := stdjson.Unmarshal(data, a)
151 type crossOutAction struct {
153 Address string `json:"address"`
154 Program json.HexBytes `json:"control_program"`
157 func (a *crossOutAction) Build(ctx context.Context, b *TemplateBuilder) error {
159 if a.Address == "" && len(a.Program) == 0 {
160 missing = append(missing, "address or program")
162 if a.AssetId.IsZero() {
163 missing = append(missing, "asset_id")
166 missing = append(missing, "amount")
168 if len(missing) > 0 {
169 return MissingFieldsError(missing...)
174 address, err := common.DecodeAddress(a.Address, consensus.BytomMainNetParams(&consensus.ActiveNetParams))
179 redeemContract := address.ScriptAddress()
180 switch address.(type) {
181 case *common.AddressWitnessPubKeyHash:
182 program, err = vmutil.P2WPKHProgram(redeemContract)
183 case *common.AddressWitnessScriptHash:
184 program, err = vmutil.P2WSHProgram(redeemContract)
186 return errors.New("unsupport address type")
193 out := types.NewCrossChainOutput(*a.AssetId, a.Amount, program)
194 return b.AddOutput(out)
197 func (a *crossOutAction) ActionType() string {
198 return "cross_chain_out"
201 // DecodeVoteOutputAction convert input data to action struct
202 func DecodeVoteOutputAction(data []byte) (Action, error) {
203 a := new(voteOutputAction)
204 err := stdjson.Unmarshal(data, a)
208 type voteOutputAction struct {
210 Address string `json:"address"`
211 Vote json.HexBytes `json:"vote"`
214 func (a *voteOutputAction) Build(ctx context.Context, b *TemplateBuilder) error {
217 missing = append(missing, "address")
219 if a.AssetId.IsZero() {
220 missing = append(missing, "asset_id")
223 missing = append(missing, "amount")
225 if len(a.Vote) == 0 {
226 missing = append(missing, "vote")
228 if len(missing) > 0 {
229 return MissingFieldsError(missing...)
232 address, err := common.DecodeAddress(a.Address, &consensus.ActiveNetParams)
237 redeemContract := address.ScriptAddress()
239 switch address.(type) {
240 case *common.AddressWitnessPubKeyHash:
241 program, err = vmutil.P2WPKHProgram(redeemContract)
242 case *common.AddressWitnessScriptHash:
243 program, err = vmutil.P2WSHProgram(redeemContract)
245 return errors.New("unsupport address type")
251 out := types.NewVoteOutput(*a.AssetId, a.Amount, program, a.Vote)
252 return b.AddOutput(out)
255 func (a *voteOutputAction) ActionType() string {
259 // DecodeCrossInAction convert input data to action struct
260 func DecodeCrossInAction(data []byte) (Action, error) {
261 a := new(crossInAction)
262 err := stdjson.Unmarshal(data, a)
266 type crossInAction struct {
268 SourceID bc.Hash `json:"source_id"`
269 SourcePos uint64 `json:"source_pos"`
270 VMVersion uint64 `json:"vm_version"`
271 RawDefinitionByte json.HexBytes `json:"raw_definition_byte"`
272 IssuanceProgram json.HexBytes `json:"issuance_program"`
275 func (c *crossInAction) Build(ctx context.Context, builder *TemplateBuilder) error {
277 if c.SourceID.IsZero() {
278 missing = append(missing, "source_id")
280 if c.AssetId.IsZero() {
281 missing = append(missing, "asset_id")
284 missing = append(missing, "amount")
287 if len(missing) > 0 {
288 return MissingFieldsError(missing...)
291 if err := c.checkAssetID(); err != nil {
295 // arguments will be set when materializeWitnesses
296 txin := types.NewCrossChainInput(nil, c.SourceID, *c.AssetId, c.Amount, c.SourcePos, c.VMVersion, c.RawDefinitionByte, c.IssuanceProgram)
297 tplIn := &SigningInstruction{}
298 fed := cfg.CommonConfig.Federation
300 if !common.IsOpenFederationIssueAsset(c.RawDefinitionByte) {
301 tplIn.AddRawWitnessKeys(fed.Xpubs, cfg.FedAddressPath, fed.Quorum)
302 tplIn.AddDataWitness(cfg.FederationPMultiSigScript(cfg.CommonConfig))
305 return builder.AddInput(txin, tplIn)
308 func (c *crossInAction) ActionType() string {
309 return "cross_chain_in"
312 func (c *crossInAction) checkAssetID() error {
313 defHash := bc.NewHash(sha3.Sum256(c.RawDefinitionByte))
314 assetID := bc.ComputeAssetID(c.IssuanceProgram, c.VMVersion, &defHash)
316 if *c.AssetId != *consensus.BTMAssetID && assetID != *c.AssetAmount.AssetId {
317 return errors.New("incorrect asset_idincorrect asset_id")