OSDN Git Service

fix
[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 )
16
17 // DecodeCrossInAction convert input data to action struct
18 func (r *Registry) DecodeCrossInAction(data []byte) (txbuilder.Action, error) {
19         a := &crossInAction{reg: r}
20         err := stdjson.Unmarshal(data, a)
21         return a, err
22 }
23
24 type crossInAction struct {
25         reg *Registry
26         bc.AssetAmount
27         SourceID        string                 `json:"source_id"` // AnnotatedUTXO
28         SourcePos       uint64                 `json:"source_pos"`
29         Program         chainjson.HexBytes     `json:"control_program"`
30         AssetDefinition map[string]interface{} `json:"asset_definition"`
31         Arguments       []chainjson.HexBytes   `json:"arguments"`
32 }
33
34 // func (reg *Registry) DefineCrossInAsset(a *Asset, alias string) error {
35 //     defHash := bc.NewHash(sha3.Sum256(rawDefinition))
36 //     a := &Asset{
37 //         DefinitionMap:     definition,
38 //         RawDefinitionByte: rawDefinition,
39 //         VMVersion:         vmver,
40 //         IssuanceProgram:   issuanceProgram,
41 //         AssetID:           bc.ComputeAssetID(issuanceProgram, vmver, &defHash),
42 //         Alias:             &alias,
43 //     }
44 //     return a, reg.SaveAsset(a, alias)
45 // }
46
47 // TODO: also need to hard-code mapTx
48 // TODO: iter cross-in and save asset
49 // TODO: federation can sign? check arguments length?
50 func (a *crossInAction) Build(ctx context.Context, builder *txbuilder.TemplateBuilder) error {
51         var missing []string
52         if len(a.Program) == 0 {
53                 missing = append(missing, "control_program")
54         }
55         if a.SourceID == "" {
56                 missing = append(missing, "source_id")
57         }
58         if a.AssetId.IsZero() {
59                 missing = append(missing, "asset_id")
60         }
61         if a.Amount == 0 {
62                 missing = append(missing, "amount")
63         }
64         if len(missing) > 0 {
65                 return txbuilder.MissingFieldsError(missing...)
66         }
67
68         asset := &Asset{}
69         var err error
70         // Handle asset definition.
71         // Asset issuance's legality is guaranteed by the federation.
72         if preAsset, _ := a.reg.GetAsset(a.AssetId.String()); preAsset != nil {
73                 asset = preAsset
74         } else {
75                 asset.RawDefinitionByte, err = serializeAssetDef(a.AssetDefinition)
76                 if err != nil {
77                         return ErrSerializing
78                 }
79
80                 if !chainjson.IsValidJSON(asset.RawDefinitionByte) {
81                         return errors.New("asset definition is not in valid json format")
82                 }
83
84                 asset.DefinitionMap = a.AssetDefinition
85                 asset.VMVersion = 1
86                 // TODO: asset.IssuanceProgram
87                 asset.AssetID = *a.AssetId
88                 extAlias := a.AssetId.String()
89                 asset.Alias = &(extAlias)
90                 a.reg.SaveAsset(asset, extAlias)
91         }
92
93         arguments := [][]byte{}
94         for _, argument := range a.Arguments {
95                 arguments = append(arguments, argument)
96         }
97
98         var sourceID bc.Hash
99         if err := sourceID.UnmarshalText([]byte(a.SourceID)); err != nil {
100                 return errors.New("invalid source ID format")
101         }
102
103         txin := types.NewCrossChainInput(arguments, sourceID, *a.AssetId, a.Amount, a.SourcePos, a.Program, asset.RawDefinitionByte)
104         log.Info("cross-chain input action build")
105         builder.RestrictMinTime(time.Now())
106         return builder.AddInput(txin, &txbuilder.SigningInstruction{})
107 }
108
109 func (a *crossInAction) ActionType() string {
110         return "cross_chain_in"
111 }