X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=application%2Fmov%2Fcommon%2Ftype.go;fp=application%2Fmov%2Fcommon%2Ftype.go;h=11d89bb16cc21e3315802e9a01fa98c344acf75a;hp=d56dac088a815d9dce515b044de0fefe73b9740a;hb=78ef45d4238457b2ad498d738db5a7a7a30df167;hpb=3adffe8810801582032e851f8ecb86cc83f253f4 diff --git a/application/mov/common/type.go b/application/mov/common/type.go index d56dac08..11d89bb1 100644 --- a/application/mov/common/type.go +++ b/application/mov/common/type.go @@ -1,7 +1,17 @@ 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 @@ -9,19 +19,150 @@ type MovUtxo struct { ControlProgram []byte } +// Order store all the order information 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 } +// 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