5 stdjson "encoding/json"
8 "golang.org/x/crypto/sha3"
10 "github.com/vapor/common"
11 cfg "github.com/vapor/config"
12 "github.com/vapor/consensus"
13 "github.com/vapor/encoding/json"
14 "github.com/vapor/protocol/bc"
15 "github.com/vapor/protocol/bc/types"
16 "github.com/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"`
156 func (a *crossOutAction) Build(ctx context.Context, b *TemplateBuilder) error {
159 missing = append(missing, "address")
161 if a.AssetId.IsZero() {
162 missing = append(missing, "asset_id")
165 missing = append(missing, "amount")
167 if len(missing) > 0 {
168 return MissingFieldsError(missing...)
171 address, err := common.DecodeAddress(a.Address, consensus.BytomMainNetParams(&consensus.ActiveNetParams))
176 redeemContract := address.ScriptAddress()
178 switch address.(type) {
179 case *common.AddressWitnessPubKeyHash:
180 program, err = vmutil.P2WPKHProgram(redeemContract)
181 case *common.AddressWitnessScriptHash:
182 program, err = vmutil.P2WSHProgram(redeemContract)
184 return errors.New("unsupport address type")
190 out := types.NewCrossChainOutput(*a.AssetId, a.Amount, program)
191 return b.AddOutput(out)
194 func (a *crossOutAction) ActionType() string {
195 return "cross_chain_out"
198 // DecodeVoteOutputAction convert input data to action struct
199 func DecodeVoteOutputAction(data []byte) (Action, error) {
200 a := new(voteOutputAction)
201 err := stdjson.Unmarshal(data, a)
205 type voteOutputAction struct {
207 Address string `json:"address"`
208 Vote json.HexBytes `json:"vote"`
211 func (a *voteOutputAction) Build(ctx context.Context, b *TemplateBuilder) error {
214 missing = append(missing, "address")
216 if a.AssetId.IsZero() {
217 missing = append(missing, "asset_id")
220 missing = append(missing, "amount")
222 if len(a.Vote) == 0 {
223 missing = append(missing, "vote")
225 if len(missing) > 0 {
226 return MissingFieldsError(missing...)
229 address, err := common.DecodeAddress(a.Address, &consensus.ActiveNetParams)
234 redeemContract := address.ScriptAddress()
236 switch address.(type) {
237 case *common.AddressWitnessPubKeyHash:
238 program, err = vmutil.P2WPKHProgram(redeemContract)
239 case *common.AddressWitnessScriptHash:
240 program, err = vmutil.P2WSHProgram(redeemContract)
242 return errors.New("unsupport address type")
248 out := types.NewVoteOutput(*a.AssetId, a.Amount, program, a.Vote)
249 return b.AddOutput(out)
252 func (a *voteOutputAction) ActionType() string {
256 // DecodeCrossInAction convert input data to action struct
257 func DecodeCrossInAction(data []byte) (Action, error) {
258 a := new(crossInAction)
259 err := stdjson.Unmarshal(data, a)
263 type crossInAction struct {
265 SourceID bc.Hash `json:"source_id"`
266 SourcePos uint64 `json:"source_pos"`
267 VMVersion uint64 `json:"vm_version"`
268 RawDefinitionByte json.HexBytes `json:"raw_definition_byte"`
269 IssuanceProgram json.HexBytes `json:"issuance_program"`
272 func (a *crossInAction) Build(ctx context.Context, builder *TemplateBuilder) error {
274 if a.SourceID.IsZero() {
275 missing = append(missing, "source_id")
277 if a.AssetId.IsZero() {
278 missing = append(missing, "asset_id")
281 missing = append(missing, "amount")
284 if len(missing) > 0 {
285 return MissingFieldsError(missing...)
288 if err := a.checkAssetID(); err != nil {
292 // arguments will be set when materializeWitnesses
293 txin := types.NewCrossChainInput(nil, a.SourceID, *a.AssetId, a.Amount, a.SourcePos, a.VMVersion, a.RawDefinitionByte, a.IssuanceProgram)
294 tplIn := &SigningInstruction{}
295 fed := cfg.CommonConfig.Federation
296 tplIn.AddRawWitnessKeys(fed.Xpubs, cfg.FedAddressPath, fed.Quorum)
297 tplIn.AddDataWitness(cfg.FederationPMultiSigScript(cfg.CommonConfig))
298 return builder.AddInput(txin, tplIn)
301 func (a *crossInAction) ActionType() string {
302 return "cross_chain_in"
305 func (c *crossInAction) checkAssetID() error {
306 defHash := bc.NewHash(sha3.Sum256(c.RawDefinitionByte))
307 assetID := bc.ComputeAssetID(c.IssuanceProgram, c.VMVersion, &defHash)
309 if *c.AssetId != *consensus.BTMAssetID && assetID != *c.AssetAmount.AssetId {
310 return errors.New("incorrect asset_idincorrect asset_id")