OSDN Git Service

14b3f9ec29f73778bd14ed9e115fee291b19a449
[bytom/vapor.git] / application / mov / common / type.go
1 package common
2
3 import (
4         "encoding/hex"
5         "fmt"
6         "math/big"
7
8         "github.com/bytom/vapor/consensus/segwit"
9         "github.com/bytom/vapor/errors"
10         "github.com/bytom/vapor/protocol/bc"
11         "github.com/bytom/vapor/protocol/bc/types"
12 )
13
14 // MovUtxo store the utxo information for mov order
15 type MovUtxo struct {
16         SourceID       *bc.Hash
17         SourcePos      uint64
18         Amount         uint64
19         ControlProgram []byte
20 }
21
22 // Order store all the order information
23 type Order struct {
24         FromAssetID      *bc.AssetID
25         ToAssetID        *bc.AssetID
26         Utxo             *MovUtxo
27         RatioNumerator   int64
28         RatioDenominator int64
29 }
30
31 func (o *Order) Rate() float64 {
32         if o.RatioDenominator == 0 {
33                 return 0
34         }
35         rate := big.NewFloat(0).SetInt64(o.RatioNumerator)
36         rate.Quo(rate, big.NewFloat(0).SetInt64(o.RatioDenominator))
37         result, _ := rate.Float64()
38         return result
39 }
40
41 func (o *Order) Cmp(other *Order) int {
42         rate := big.NewRat(o.RatioNumerator, o.RatioDenominator)
43         otherRate := big.NewRat(other.RatioNumerator, other.RatioDenominator)
44         return rate.Cmp(otherRate)
45 }
46
47 // OrderSlice is define for order's sort
48 type OrderSlice []*Order
49
50 func (o OrderSlice) Len() int      { return len(o) }
51 func (o OrderSlice) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
52 func (o OrderSlice) Less(i, j int) bool {
53         cmp := o[i].Cmp(o[j])
54         if cmp == 0 {
55                 return hex.EncodeToString(o[i].UTXOHash().Bytes()) < hex.EncodeToString(o[j].UTXOHash().Bytes())
56         }
57         return cmp < 0
58 }
59
60 // NewOrderFromOutput convert txinput to order
61 func NewOrderFromOutput(tx *types.Tx, outputIndex int) (*Order, error) {
62         outputID := tx.OutputID(outputIndex)
63         output, err := tx.IntraChainOutput(*outputID)
64         if err != nil {
65                 return nil, err
66         }
67
68         contractArgs, err := segwit.DecodeP2WMCProgram(output.ControlProgram.Code)
69         if err != nil {
70                 return nil, err
71         }
72
73         assetAmount := output.Source.Value
74         return &Order{
75                 FromAssetID:      assetAmount.AssetId,
76                 ToAssetID:        &contractArgs.RequestedAsset,
77                 RatioNumerator:   contractArgs.RatioNumerator,
78                 RatioDenominator: contractArgs.RatioDenominator,
79                 Utxo: &MovUtxo{
80                         SourceID:       output.Source.Ref,
81                         Amount:         assetAmount.Amount,
82                         SourcePos:      uint64(outputIndex),
83                         ControlProgram: output.ControlProgram.Code,
84                 },
85         }, nil
86 }
87
88 // NewOrderFromInput convert txoutput to order
89 func NewOrderFromInput(tx *types.Tx, inputIndex int) (*Order, error) {
90         input, ok := tx.Inputs[inputIndex].TypedInput.(*types.SpendInput)
91         if !ok {
92                 return nil, errors.New("input is not type of spend input")
93         }
94
95         contractArgs, err := segwit.DecodeP2WMCProgram(input.ControlProgram)
96         if err != nil {
97                 return nil, err
98         }
99
100         return &Order{
101                 FromAssetID:      input.AssetId,
102                 ToAssetID:        &contractArgs.RequestedAsset,
103                 RatioNumerator:   contractArgs.RatioNumerator,
104                 RatioDenominator: contractArgs.RatioDenominator,
105                 Utxo: &MovUtxo{
106                         SourceID:       &input.SourceID,
107                         Amount:         input.Amount,
108                         SourcePos:      input.SourcePosition,
109                         ControlProgram: input.ControlProgram,
110                 },
111         }, nil
112 }
113
114 // Key return the unique key for representing this order
115 func (o *Order) Key() string {
116         return fmt.Sprintf("%s:%d", o.Utxo.SourceID, o.Utxo.SourcePos)
117 }
118
119 // TradePair return the trade pair info
120 func (o *Order) TradePair() *TradePair {
121         return &TradePair{FromAssetID: o.FromAssetID, ToAssetID: o.ToAssetID}
122 }
123
124 // UTXOHash calculate the utxo hash of this order
125 func (o *Order) UTXOHash() *bc.Hash {
126         prog := &bc.Program{VmVersion: 1, Code: o.Utxo.ControlProgram}
127         src := &bc.ValueSource{
128                 Ref:      o.Utxo.SourceID,
129                 Value:    &bc.AssetAmount{AssetId: o.FromAssetID, Amount: o.Utxo.Amount},
130                 Position: o.Utxo.SourcePos,
131         }
132         hash := bc.EntryID(bc.NewIntraChainOutput(src, prog, 0))
133         return &hash
134 }
135
136 // TradePair is the object for record trade pair info
137 type TradePair struct {
138         FromAssetID *bc.AssetID
139         ToAssetID   *bc.AssetID
140         Count       int
141 }
142
143 // Key return the unique key for representing this trade pair
144 func (t *TradePair) Key() string {
145         return fmt.Sprintf("%s:%s", t.FromAssetID, t.ToAssetID)
146 }
147
148 // Reverse return the reverse trade pair object
149 func (t *TradePair) Reverse() *TradePair {
150         return &TradePair{
151                 FromAssetID: t.ToAssetID,
152                 ToAssetID:   t.FromAssetID,
153         }
154 }
155
156 // MovDatabaseState is object to record DB image status
157 type MovDatabaseState struct {
158         Height uint64
159         Hash   *bc.Hash
160 }