5 stdjson "encoding/json"
9 log "github.com/sirupsen/logrus"
11 "github.com/vapor/blockchain/txbuilder"
12 "github.com/vapor/consensus/federation"
13 chainjson "github.com/vapor/encoding/json"
14 "github.com/vapor/errors"
15 "github.com/vapor/protocol/bc"
16 "github.com/vapor/protocol/bc/types"
19 // DecodeCrossInAction convert input data to action struct
20 func (r *Registry) DecodeCrossInAction(data []byte) (txbuilder.Action, error) {
21 a := &crossInAction{reg: r}
22 err := stdjson.Unmarshal(data, a)
26 type crossInAction struct {
29 SourceID bc.Hash `json:"source_id"`
30 SourcePos uint64 `json:"source_pos"`
31 AssetDefinition map[string]interface{} `json:"asset_definition"`
34 func (a *crossInAction) Build(ctx context.Context, builder *txbuilder.TemplateBuilder) error {
36 if a.SourceID.IsZero() {
37 missing = append(missing, "source_id")
39 if a.AssetId.IsZero() {
40 missing = append(missing, "asset_id")
43 missing = append(missing, "amount")
46 return txbuilder.MissingFieldsError(missing...)
49 sourceKey := []byte(fmt.Sprintf("SC:%v:%v", a.SourceID, a.SourcePos))
51 defer a.reg.assetMu.Unlock()
52 if existed := a.reg.db.Get(sourceKey); existed != nil {
53 return errors.New("mainchain output double spent")
58 if preAsset, _ := a.reg.GetAsset(a.AssetId.String()); preAsset != nil {
61 asset.RawDefinitionByte, err = serializeAssetDef(a.AssetDefinition)
66 if !chainjson.IsValidJSON(asset.RawDefinitionByte) {
67 return errors.New("asset definition is not in valid json format")
70 asset.DefinitionMap = a.AssetDefinition
72 asset.AssetID = *a.AssetId
73 extAlias := a.AssetId.String()
74 asset.Alias = &(extAlias)
75 a.reg.SaveExtAsset(asset)
78 fed := federation.GetFederation()
79 // arguments will be set when materializeWitnesses
80 txin := types.NewCrossChainInput(nil, a.SourceID, *a.AssetId, a.Amount, a.SourcePos, fed.ControlProgram, asset.RawDefinitionByte)
81 log.Info("cross-chain input action built")
82 builder.RestrictMinTime(time.Now())
83 tplIn := &txbuilder.SigningInstruction{}
84 tplIn.AddRawWitnessKeys(fed.XPubs, fed.Path, fed.Quorum)
85 a.reg.db.Set(sourceKey, []byte("true"))
86 return builder.AddInput(txin, tplIn)
89 func (a *crossInAction) ActionType() string {
90 return "cross_chain_in"