OSDN Git Service

10a04a3618a1b0e5612ad45f2259fdb242d2af9e
[bytom/vapor.git] / asset / builder.go
1 package asset
2
3 import (
4         "context"
5         stdjson "encoding/json"
6         "time"
7
8         log "github.com/sirupsen/logrus"
9
10         "github.com/vapor/blockchain/txbuilder"
11         chainjson "github.com/vapor/encoding/json"
12         "github.com/vapor/errors"
13         "github.com/vapor/protocol/bc"
14         "github.com/vapor/protocol/bc/types"
15         "github.com/vapor/testutil"
16 )
17
18 // DecodeCrossInAction convert input data to action struct
19 func (r *Registry) DecodeCrossInAction(data []byte) (txbuilder.Action, error) {
20         a := &crossInAction{assets: r}
21         err := stdjson.Unmarshal(data, a)
22         return a, err
23 }
24
25 type crossInAction struct {
26         assets *Registry
27         bc.AssetAmount
28         SourceID        string                       `json:"source_id"` // AnnotatedUTXO
29         SourcePos       uint64                       `json:"source_pos"`
30         Program         json.HexBytes                `json:"control_program"`
31         AssetDefinition map[string]interface{}       `json:"asset_definition"`
32         UpdateAssetDef  bool                         `json:"update_asset_definition"`
33         Arguments       []txbuilder.ContractArgument `json:"arguments"`
34 }
35
36 // type AnnotatedInput struct {
37 //  Type             string               `json:"type"`
38 //  AssetID          bc.AssetID           `json:"asset_id"`
39 //  AssetAlias       string               `json:"asset_alias,omitempty"`
40 //  AssetDefinition  *json.RawMessage     `json:"asset_definition,omitempty"`
41 //  Amount           uint64               `json:"amount"`
42 //  ControlProgram   chainjson.HexBytes   `json:"control_program,omitempty"`
43 //  Address          string               `json:"address,omitempty"`
44 //  SpentOutputID    *bc.Hash             `json:"spent_output_id,omitempty"`
45 //  AccountID        string               `json:"account_id,omitempty"`
46 //  AccountAlias     string               `json:"account_alias,omitempty"`
47 //  Arbitrary        chainjson.HexBytes   `json:"arbitrary,omitempty"`
48 //  InputID          bc.Hash              `json:"input_id"`
49 //  WitnessArguments []chainjson.HexBytes `json:"witness_arguments"`
50 // }
51
52 func (a *crossInAction) Build(ctx context.Context, builder *txbuilder.TemplateBuilder) error {
53         var missing []string
54         if len(a.Program) == 0 {
55                 missing = append(missing, "control_program")
56         }
57         if a.AssetId.IsZero() {
58                 missing = append(missing, "asset_id")
59         }
60         if a.Amount == 0 {
61                 missing = append(missing, "amount")
62         }
63         if len(missing) > 0 {
64                 return txbuilder.MissingFieldsError(missing...)
65         }
66
67         // Handle asset definition.
68         // Asset issuance's legality is guaranteed by the federation.
69         rawDefinition, err := SerializeAssetDef(a.AssetDefinition)
70         if err != nil {
71                 return ErrSerializing
72         }
73         // TODO: may need to skip here
74         if !chainjson.IsValidJSON(rawDefinition) {
75                 return errors.New("asset definition is not in valid json format")
76         }
77         if preAsset, _ := a.assets.GetAsset(a.AssetId.String()); preAsset != nil {
78                 // GetAsset() doesn't unmashall for RawDefinitionBytes
79                 preRawDefinition, err := SerializeAssetDef(preAsset.DefinitionMap)
80                 if err != nil {
81                         return ErrSerializing
82                 }
83
84                 if !testutil.DeepEqual(preRawDefinition, rawDefinition) && !a.UpdateAssetDef {
85                         return errors.New("asset definition mismatch with previous definition")
86                 }
87                 // TODO: update asset def here?
88         }
89
90         // TODO: also need to hard-code mapTx
91         // TODO: save AssetDefinition
92
93         sourceID := testutil.MustDecodeHash(a.SourceID)
94         // input's arguments will be set when signing
95         // arguments?
96         // in :=  types.NewCrossChainInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, amount, sourcePos uint64, controlProgram, assetDefinition []byte)
97         txin := types.NewCrossChainInput(nil, sourceID, *a.AssetId, a.Amount, a.SourcePos, a.Program, rawDefinition)
98         log.Info("cross-chain input action build")
99         builder.RestrictMinTime(time.Now())
100         return builder.AddInput(txin, &txbuilder.SigningInstruction{})
101 }
102
103 func (a *crossInAction) ActionType() string {
104         return "cross_chain_in"
105 }