OSDN Git Service

versoin1.1.9 (#594)
[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         SellerProgram    []byte
30         BlockHeight      uint64
31         TxIndex          uint64
32 }
33
34 // Rate return the exchange represented by float64
35 func (o *Order) Rate() float64 {
36         if o.RatioDenominator == 0 {
37                 return 0
38         }
39         rate := big.NewRat(o.RatioNumerator, o.RatioDenominator)
40         result, _ := rate.Float64()
41         return result
42 }
43
44 // cmpRate compares rate of x and y and returns -1 if x <  y, 0 if x == y, +1 if x >  y
45 func (o *Order) cmpRate(other *Order) int {
46         rate := big.NewRat(o.RatioNumerator, o.RatioDenominator)
47         otherRate := big.NewRat(other.RatioNumerator, other.RatioDenominator)
48         return rate.Cmp(otherRate)
49 }
50
51 // Cmp first compare the rate, if rate is equals, then compare the utxo hash
52 func (o *Order) Cmp(other *Order) int {
53         cmp := o.cmpRate(other)
54         if cmp == 0 {
55                 if hex.EncodeToString(o.UTXOHash().Bytes()) < hex.EncodeToString(other.UTXOHash().Bytes()) {
56                         return -1
57                 }
58                 return 1
59         }
60         return cmp
61 }
62
63 // OrderSlice is define for order's sort
64 type OrderSlice []*Order
65
66 func (o OrderSlice) Len() int      { return len(o) }
67 func (o OrderSlice) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
68 func (o OrderSlice) Less(i, j int) bool {
69         return o[i].Cmp(o[j]) < 0
70 }
71
72 // NewOrderFromOutput convert txinput to order
73 func NewOrderFromOutput(tx *types.Tx, outputIndex int, blockHeight, txIndex uint64) (*Order, error) {
74         outputID := tx.OutputID(outputIndex)
75         output, err := tx.IntraChainOutput(*outputID)
76         if err != nil {
77                 return nil, err
78         }
79
80         contractArgs, err := segwit.DecodeP2WMCProgram(output.ControlProgram.Code)
81         if err != nil {
82                 return nil, err
83         }
84
85         assetAmount := output.Source.Value
86         return &Order{
87                 FromAssetID:      assetAmount.AssetId,
88                 ToAssetID:        &contractArgs.RequestedAsset,
89                 RatioNumerator:   contractArgs.RatioNumerator,
90                 RatioDenominator: contractArgs.RatioDenominator,
91                 SellerProgram:    contractArgs.SellerProgram,
92                 BlockHeight:      blockHeight,
93                 TxIndex:          txIndex,
94                 Utxo: &MovUtxo{
95                         SourceID:       output.Source.Ref,
96                         Amount:         assetAmount.Amount,
97                         SourcePos:      uint64(outputIndex),
98                         ControlProgram: output.ControlProgram.Code,
99                 },
100         }, nil
101 }
102
103 // NewOrderFromInput convert txoutput to order
104 func NewOrderFromInput(tx *types.Tx, inputIndex int) (*Order, error) {
105         input, ok := tx.Inputs[inputIndex].TypedInput.(*types.SpendInput)
106         if !ok {
107                 return nil, errors.New("input is not type of spend input")
108         }
109
110         contractArgs, err := segwit.DecodeP2WMCProgram(input.ControlProgram)
111         if err != nil {
112                 return nil, err
113         }
114
115         return &Order{
116                 FromAssetID:      input.AssetId,
117                 ToAssetID:        &contractArgs.RequestedAsset,
118                 RatioNumerator:   contractArgs.RatioNumerator,
119                 RatioDenominator: contractArgs.RatioDenominator,
120                 SellerProgram:    contractArgs.SellerProgram,
121                 Utxo: &MovUtxo{
122                         SourceID:       &input.SourceID,
123                         Amount:         input.Amount,
124                         SourcePos:      input.SourcePosition,
125                         ControlProgram: input.ControlProgram,
126                 },
127         }, nil
128 }
129
130 // Key return the unique key for representing this order
131 func (o *Order) Key() string {
132         return fmt.Sprintf("%s:%d", o.Utxo.SourceID, o.Utxo.SourcePos)
133 }
134
135 // TradePair return the trade pair info
136 func (o *Order) TradePair() *TradePair {
137         return &TradePair{FromAssetID: o.FromAssetID, ToAssetID: o.ToAssetID}
138 }
139
140 // UTXOHash calculate the utxo hash of this order
141 func (o *Order) UTXOHash() *bc.Hash {
142         prog := &bc.Program{VmVersion: 1, Code: o.Utxo.ControlProgram}
143         src := &bc.ValueSource{
144                 Ref:      o.Utxo.SourceID,
145                 Value:    &bc.AssetAmount{AssetId: o.FromAssetID, Amount: o.Utxo.Amount},
146                 Position: o.Utxo.SourcePos,
147         }
148         hash := bc.EntryID(bc.NewIntraChainOutput(src, prog, 0))
149         return &hash
150 }
151
152 // TradePair is the object for record trade pair info
153 type TradePair struct {
154         FromAssetID *bc.AssetID
155         ToAssetID   *bc.AssetID
156         Count       int
157 }
158
159 // Key return the unique key for representing this trade pair
160 func (t *TradePair) Key() string {
161         return fmt.Sprintf("%s:%s", t.FromAssetID, t.ToAssetID)
162 }
163
164 // Reverse return the reverse trade pair object
165 func (t *TradePair) Reverse() *TradePair {
166         return &TradePair{
167                 FromAssetID: t.ToAssetID,
168                 ToAssetID:   t.FromAssetID,
169         }
170 }
171
172 // MovDatabaseState is object to record DB image status
173 type MovDatabaseState struct {
174         Height uint64
175         Hash   *bc.Hash
176 }