OSDN Git Service

Mov (#518)
[bytom/vapor.git] / application / mov / common / type.go
index d56dac0..11d89bb 100644 (file)
@@ -1,7 +1,17 @@
 package common
 
 package common
 
-import "github.com/bytom/vapor/protocol/bc"
+import (
+       "encoding/hex"
+       "fmt"
+       "math/big"
 
 
+       "github.com/bytom/vapor/consensus/segwit"
+       "github.com/bytom/vapor/errors"
+       "github.com/bytom/vapor/protocol/bc"
+       "github.com/bytom/vapor/protocol/bc/types"
+)
+
+// MovUtxo store the utxo information for mov order
 type MovUtxo struct {
        SourceID       *bc.Hash
        SourcePos      uint64
 type MovUtxo struct {
        SourceID       *bc.Hash
        SourcePos      uint64
@@ -9,19 +19,150 @@ type MovUtxo struct {
        ControlProgram []byte
 }
 
        ControlProgram []byte
 }
 
+// Order store all the order information
 type Order struct {
 type Order struct {
-       FromAssetID *bc.AssetID
-       ToAssetID   *bc.AssetID
-       Utxo        *MovUtxo
-       Rate        float64
+       FromAssetID      *bc.AssetID
+       ToAssetID        *bc.AssetID
+       Utxo             *MovUtxo
+       RatioNumerator   int64
+       RatioDenominator int64
+}
+
+// Rate return the exchange represented by float64
+func (o *Order) Rate() float64 {
+       if o.RatioDenominator == 0 {
+               return 0
+       }
+       rate := big.NewRat(o.RatioNumerator, o.RatioDenominator)
+       result, _ := rate.Float64()
+       return result
+}
+
+// cmpRate compares rate of x and y and returns -1 if x <  y, 0 if x == y, +1 if x >  y
+func (o *Order) cmpRate(other *Order) int {
+       rate := big.NewRat(o.RatioNumerator, o.RatioDenominator)
+       otherRate := big.NewRat(other.RatioNumerator, other.RatioDenominator)
+       return rate.Cmp(otherRate)
+}
+
+// Cmp first compare the rate, if rate is equals, then compare the utxo hash
+func (o *Order) Cmp(other *Order) int {
+       cmp := o.cmpRate(other)
+       if cmp == 0 {
+               if hex.EncodeToString(o.UTXOHash().Bytes()) < hex.EncodeToString(other.UTXOHash().Bytes()) {
+                       return -1
+               }
+               return 1
+       }
+       return cmp
+}
+
+// OrderSlice is define for order's sort
+type OrderSlice []*Order
+
+func (o OrderSlice) Len() int      { return len(o) }
+func (o OrderSlice) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
+func (o OrderSlice) Less(i, j int) bool {
+       return o[i].Cmp(o[j]) < 0
+}
+
+// NewOrderFromOutput convert txinput to order
+func NewOrderFromOutput(tx *types.Tx, outputIndex int) (*Order, error) {
+       outputID := tx.OutputID(outputIndex)
+       output, err := tx.IntraChainOutput(*outputID)
+       if err != nil {
+               return nil, err
+       }
+
+       contractArgs, err := segwit.DecodeP2WMCProgram(output.ControlProgram.Code)
+       if err != nil {
+               return nil, err
+       }
+
+       assetAmount := output.Source.Value
+       return &Order{
+               FromAssetID:      assetAmount.AssetId,
+               ToAssetID:        &contractArgs.RequestedAsset,
+               RatioNumerator:   contractArgs.RatioNumerator,
+               RatioDenominator: contractArgs.RatioDenominator,
+               Utxo: &MovUtxo{
+                       SourceID:       output.Source.Ref,
+                       Amount:         assetAmount.Amount,
+                       SourcePos:      uint64(outputIndex),
+                       ControlProgram: output.ControlProgram.Code,
+               },
+       }, nil
+}
+
+// NewOrderFromInput convert txoutput to order
+func NewOrderFromInput(tx *types.Tx, inputIndex int) (*Order, error) {
+       input, ok := tx.Inputs[inputIndex].TypedInput.(*types.SpendInput)
+       if !ok {
+               return nil, errors.New("input is not type of spend input")
+       }
+
+       contractArgs, err := segwit.DecodeP2WMCProgram(input.ControlProgram)
+       if err != nil {
+               return nil, err
+       }
+
+       return &Order{
+               FromAssetID:      input.AssetId,
+               ToAssetID:        &contractArgs.RequestedAsset,
+               RatioNumerator:   contractArgs.RatioNumerator,
+               RatioDenominator: contractArgs.RatioDenominator,
+               Utxo: &MovUtxo{
+                       SourceID:       &input.SourceID,
+                       Amount:         input.Amount,
+                       SourcePos:      input.SourcePosition,
+                       ControlProgram: input.ControlProgram,
+               },
+       }, nil
+}
+
+// Key return the unique key for representing this order
+func (o *Order) Key() string {
+       return fmt.Sprintf("%s:%d", o.Utxo.SourceID, o.Utxo.SourcePos)
 }
 
 }
 
+// TradePair return the trade pair info
+func (o *Order) TradePair() *TradePair {
+       return &TradePair{FromAssetID: o.FromAssetID, ToAssetID: o.ToAssetID}
+}
+
+// UTXOHash calculate the utxo hash of this order
+func (o *Order) UTXOHash() *bc.Hash {
+       prog := &bc.Program{VmVersion: 1, Code: o.Utxo.ControlProgram}
+       src := &bc.ValueSource{
+               Ref:      o.Utxo.SourceID,
+               Value:    &bc.AssetAmount{AssetId: o.FromAssetID, Amount: o.Utxo.Amount},
+               Position: o.Utxo.SourcePos,
+       }
+       hash := bc.EntryID(bc.NewIntraChainOutput(src, prog, 0))
+       return &hash
+}
+
+// TradePair is the object for record trade pair info
 type TradePair struct {
        FromAssetID *bc.AssetID
        ToAssetID   *bc.AssetID
        Count       int
 }
 
 type TradePair struct {
        FromAssetID *bc.AssetID
        ToAssetID   *bc.AssetID
        Count       int
 }
 
+// Key return the unique key for representing this trade pair
+func (t *TradePair) Key() string {
+       return fmt.Sprintf("%s:%s", t.FromAssetID, t.ToAssetID)
+}
+
+// Reverse return the reverse trade pair object
+func (t *TradePair) Reverse() *TradePair {
+       return &TradePair{
+               FromAssetID: t.ToAssetID,
+               ToAssetID:   t.FromAssetID,
+       }
+}
+
+// MovDatabaseState is object to record DB image status
 type MovDatabaseState struct {
        Height uint64
        Hash   *bc.Hash
 type MovDatabaseState struct {
        Height uint64
        Hash   *bc.Hash