5 stdjson "encoding/json"
8 log "github.com/sirupsen/logrus"
10 "github.com/vapor/blockchain/txbuilder"
11 "github.com/vapor/consensus/federation"
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 bc.Hash `json:"source_id"`
28 SourcePos uint64 `json:"source_pos"`
29 AssetDefinition map[string]interface{} `json:"asset_definition"`
32 func (a *crossInAction) Build(ctx context.Context, builder *txbuilder.TemplateBuilder) error {
34 if a.SourceID.IsZero() {
35 missing = append(missing, "source_id")
37 if a.AssetId.IsZero() {
38 missing = append(missing, "asset_id")
41 missing = append(missing, "amount")
44 return txbuilder.MissingFieldsError(missing...)
47 sourceKey := []byte(fmt.Sprintf("SC:%v:%v", a.SourceID, a.SourcePos))
49 defer a.reg.assetMu.Unlock()
50 if existed := a.reg.db.Get(sourceKey); existed != nil {
51 return errors.New("mainchain output double spent")
54 rawDefinitionByte, err := serializeAssetDef(a.AssetDefinition)
59 // 1. arguments will be set when materializeWitnesses
60 // 2. need to fill in issuance program here
61 txin := types.NewCrossChainInput(nil, a.SourceID, *a.AssetId, a.Amount, a.SourcePos, nil, rawDefinitionByte)
62 log.Info("cross-chain input action built")
63 tplIn := &txbuilder.SigningInstruction{}
64 fed := federation.GetFederation()
65 tplIn.AddRawWitnessKeys(fed.XPubs, fed.Path, fed.Quorum)
66 a.reg.db.Set(sourceKey, []byte("true"))
67 return builder.AddInput(txin, tplIn)
70 func (a *crossInAction) ActionType() string {
71 return "cross_chain_in"