5 stdjson "encoding/json"
8 log "github.com/sirupsen/logrus"
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"
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)
24 type crossInAction struct {
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"`
34 // func (reg *Registry) DefineCrossInAsset(a *Asset, alias string) error {
35 // defHash := bc.NewHash(sha3.Sum256(rawDefinition))
37 // DefinitionMap: definition,
38 // RawDefinitionByte: rawDefinition,
40 // IssuanceProgram: issuanceProgram,
41 // AssetID: bc.ComputeAssetID(issuanceProgram, vmver, &defHash),
44 // return a, reg.SaveAsset(a, alias)
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 {
52 if len(a.Program) == 0 {
53 missing = append(missing, "control_program")
56 missing = append(missing, "source_id")
58 if a.AssetId.IsZero() {
59 missing = append(missing, "asset_id")
62 missing = append(missing, "amount")
65 return txbuilder.MissingFieldsError(missing...)
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 {
75 asset.RawDefinitionByte, err = serializeAssetDef(a.AssetDefinition)
80 if !chainjson.IsValidJSON(asset.RawDefinitionByte) {
81 return errors.New("asset definition is not in valid json format")
84 asset.DefinitionMap = a.AssetDefinition
86 // TODO: asset.IssuanceProgram
87 asset.AssetID = *a.AssetId
88 extAlias := a.AssetId.String()
89 asset.Alias = &(extAlias)
90 a.reg.SaveAsset(asset, extAlias)
93 arguments := [][]byte{}
94 for _, argument := range a.Arguments {
95 arguments = append(arguments, argument)
99 if err := sourceID.UnmarshalText([]byte(a.SourceID)); err != nil {
100 return errors.New("invalid source ID format")
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{})
109 func (a *crossInAction) ActionType() string {
110 return "cross_chain_in"