OSDN Git Service

minor
[bytom/vapor.git] / asset / builder.go
1 package asset
2
3 import (
4         "context"
5         stdjson "encoding/json"
6         "fmt"
7
8         log "github.com/sirupsen/logrus"
9
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"
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        bc.Hash                `json:"source_id"`
28         SourcePos       uint64                 `json:"source_pos"`
29         AssetDefinition map[string]interface{} `json:"asset_definition"`
30 }
31
32 func (a *crossInAction) Build(ctx context.Context, builder *txbuilder.TemplateBuilder) error {
33         var missing []string
34         if a.SourceID.IsZero() {
35                 missing = append(missing, "source_id")
36         }
37         if a.AssetId.IsZero() {
38                 missing = append(missing, "asset_id")
39         }
40         if a.Amount == 0 {
41                 missing = append(missing, "amount")
42         }
43         if len(missing) > 0 {
44                 return txbuilder.MissingFieldsError(missing...)
45         }
46
47         sourceKey := []byte(fmt.Sprintf("SC:%v:%v", a.SourceID, a.SourcePos))
48         a.reg.assetMu.Lock()
49         defer a.reg.assetMu.Unlock()
50         if existed := a.reg.db.Get(sourceKey); existed != nil {
51                 return errors.New("mainchain output double spent")
52         }
53
54         rawDefinitionByte, err := serializeAssetDef(a.AssetDefinition)
55         if err != nil {
56                 return ErrSerializing
57         }
58
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)
68 }
69
70 func (a *crossInAction) ActionType() string {
71         return "cross_chain_in"
72 }