Skip to content

Commit

Permalink
Merge pull request ethereum#556 from thanhnguyennguyen/verify-matched…
Browse files Browse the repository at this point in the history
…-txs

Verify matched txs
  • Loading branch information
ngtuna authored Jul 22, 2019
2 parents 848bb23 + 0a14b27 commit 85b35b5
Show file tree
Hide file tree
Showing 10 changed files with 745 additions and 145 deletions.
27 changes: 14 additions & 13 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,20 @@ import (
)

const (
HashLength = 32
AddressLength = 20
BlockSigners = "0x0000000000000000000000000000000000000089"
MasternodeVotingSMC = "0x0000000000000000000000000000000000000088"
RandomizeSMC = "0x0000000000000000000000000000000000000090"
FoudationAddr = "0x0000000000000000000000000000000000000068"
TeamAddr = "0x0000000000000000000000000000000000000099"
TomoXAddr = "0x0000000000000000000000000000000000000091"
VoteMethod = "0x6dd7d8ea"
UnvoteMethod = "0x02aa9be2"
ProposeMethod = "0x01267951"
ResignMethod = "0xae6e43f5"
SignMethod = "0xe341eaa4"
HashLength = 32
AddressLength = 20
BlockSigners = "0x0000000000000000000000000000000000000089"
MasternodeVotingSMC = "0x0000000000000000000000000000000000000088"
RandomizeSMC = "0x0000000000000000000000000000000000000090"
FoudationAddr = "0x0000000000000000000000000000000000000068"
TeamAddr = "0x0000000000000000000000000000000000000099"
TomoXAddr = "0x0000000000000000000000000000000000000091"
RelayerRegistrationSMC = "0x00000000000000000000000000000000000000xx"
VoteMethod = "0x6dd7d8ea"
UnvoteMethod = "0x02aa9be2"
ProposeMethod = "0x01267951"
ResignMethod = "0xae6e43f5"
SignMethod = "0xe341eaa4"
)

var (
Expand Down
150 changes: 104 additions & 46 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,81 +55,58 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin
// ValidateBody validates the given block's uncles and verifies the the block
// header's transaction and uncle roots. The headers are assumed to be already
// validated at this point.
func (v *BlockValidator) ValidateBody(block *types.Block) error {
func (v *BlockValidator) ValidateBody(block *types.Block) (error, []common.Hash) {
// Check whether the block's known, and if not, that it's linkable
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
return ErrKnownBlock
return ErrKnownBlock, []common.Hash{}
}
if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
return consensus.ErrUnknownAncestor
return consensus.ErrUnknownAncestor, []common.Hash{}
}
return consensus.ErrPrunedAncestor
return consensus.ErrPrunedAncestor, []common.Hash{}
}
// Header validity is known at this point, check the uncles and transactions
header := block.Header()
if err := v.engine.VerifyUncles(v.bc, block); err != nil {
return err
return err, []common.Hash{}
}
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
return fmt.Errorf("uncle root hash mismatch: have %x, want %x", hash, header.UncleHash)
return fmt.Errorf("uncle root hash mismatch: have %x, want %x", hash, header.UncleHash), []common.Hash{}
}
if hash := types.DeriveSha(block.Transactions()); hash != header.TxHash {
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash), []common.Hash{}
}

engine, _ := v.engine.(*posv.Posv)
tomoXService := engine.GetTomoXService()

currentState, err := v.bc.State()
if err != nil {
return err, []common.Hash{}
}

// validate matchedOrder txs
processedHashes := []common.Hash{}
// clear the previous dry-run cache
if tomoXService != nil {
tomoXService.GetDB().InitDryRunMode()
}
for _, tx := range block.Transactions() {
if tx.IsMatchingTransaction() {
if tomoXService == nil {
log.Error("tomox not found")
return tomox.ErrTomoXServiceNotFound
return tomox.ErrTomoXServiceNotFound, []common.Hash{}
}
log.Debug("process tx match")
txMatch := &tomox.TxDataMatch{}
if err := json.Unmarshal(tx.Data(), txMatch); err != nil {
return fmt.Errorf("transaction match is corrupted. Failed unmarshal. Error: ", err)
}
log.Debug("tx unmarshal", "txMatch", txMatch, "tx.Data()", tx.Data())
order, err := txMatch.DecodeOrder()
hash, err := v.validateMatchedOrder(tomoXService, currentState, tx)
if err != nil {
return fmt.Errorf("transaction match is corrupted. Failed decode order. Error: ", err)
}
trades := txMatch.GetTrades()
log.Debug("Got trades", "number", len(trades), "trades", trades)
for _, trade := range trades {
tradeSDK := &sdktypes.Trade{}
if q, ok := trade["quantity"]; ok {
tradeSDK.Amount = new(big.Int)
tradeSDK.Amount.SetString(q, 10)
}
tradeSDK.PricePoint = order.Price
tradeSDK.PairName = order.PairName
tradeSDK.BaseToken = order.BaseToken
tradeSDK.QuoteToken = order.QuoteToken
tradeSDK.Status = sdktypes.TradeStatusSuccess
tradeSDK.Maker = order.UserAddress
tradeSDK.MakerOrderHash = order.Hash
if u, ok := trade["uAddr"]; ok {
tradeSDK.Taker = common.Address{}
tradeSDK.Taker.SetString(u)
}
tradeSDK.TakerOrderHash = order.Hash //FIXME: will update txMatch to include TakerOrderHash = headOrder.Item.Hash
tradeSDK.TxHash = tx.Hash()
tradeSDK.Hash = tradeSDK.ComputeHash()
log.Debug("TRADE history", "order", order, "trade", tradeSDK)
// put tradeSDK to mongodb on SDK node
if tomoXService.IsSDKNode() {
db := tomoXService.GetDB()
return db.Put(tomox.EmptyKey(), tradeSDK, true)
}
return err, []common.Hash{}
}
processedHashes = append(processedHashes, hash)
}
}

return nil
return nil, processedHashes
}

// ValidateState validates the various changes that happen after a state
Expand Down Expand Up @@ -160,6 +137,53 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
return nil
}

// return values
// hash: for removing from pending list and add to processed list
// orderbook according to the order
func (v *BlockValidator) validateMatchedOrder(tomoXService *tomox.TomoX, currentState *state.StateDB, tx *types.Transaction) (common.Hash, error) {
txMatch := &tomox.TxDataMatch{}
if err := json.Unmarshal(tx.Data(), txMatch); err != nil {
return common.Hash{}, fmt.Errorf("transaction match is corrupted. Failed unmarshal. Error: %s", err.Error())
}

// verify orderItem
order, err := txMatch.DecodeOrder()
if err != nil {
return common.Hash{},fmt.Errorf("transaction match is corrupted. Failed decode order. Error: %s ", err.Error())
}
if err := order.VerifyMatchedOrder(currentState); err != nil {
return common.Hash{},err
}

ob, err := tomoXService.GetOrderBook(order.PairName, true)
// if orderbook of this pairName has been updated by previous tx in this block, use it

if err != nil {
return common.Hash{}, err
}

// verify old state: orderbook hash, bidTree hash, askTree hash
if err := txMatch.VerifyOldTomoXState(ob); err != nil {
return common.Hash{}, err
}

// process Matching Engine
if _, _, err := ob.ProcessOrder(order, true, true); err != nil {
return common.Hash{}, err
}

// verify new state
if err := txMatch.VerifyNewTomoXState(ob); err != nil {
return common.Hash{}, err
}

trades := txMatch.GetTrades()
if err := logTrades(tomoXService, tx.Hash(), order, trades); err != nil {
return common.Hash{}, err
}
return order.Hash, nil
}

// CalcGasLimit computes the gas limit of the next block after parent.
// This is miner strategy, not consensus protocol.
func CalcGasLimit(parent *types.Block) uint64 {
Expand Down Expand Up @@ -190,3 +214,37 @@ func CalcGasLimit(parent *types.Block) uint64 {
}
return limit
}

func logTrades(tomoXService *tomox.TomoX, txHash common.Hash, order *tomox.OrderItem, trades []map[string]string) error {
log.Debug("Got trades", "number", len(trades), "trades", trades)
for _, trade := range trades {
tradeSDK := &sdktypes.Trade{}
if q, ok := trade["quantity"]; ok {
tradeSDK.Amount = new(big.Int)
tradeSDK.Amount.SetString(q, 10)
}
tradeSDK.PricePoint = order.Price
tradeSDK.PairName = order.PairName
tradeSDK.BaseToken = order.BaseToken
tradeSDK.QuoteToken = order.QuoteToken
tradeSDK.Status = sdktypes.TradeStatusSuccess
tradeSDK.Maker = order.UserAddress
tradeSDK.MakerOrderHash = order.Hash
if u, ok := trade["uAddr"]; ok {
tradeSDK.Taker = common.Address{}
tradeSDK.Taker.SetString(u)
}
tradeSDK.TakerOrderHash = order.Hash //FIXME: will update txMatch to include TakerOrderHash = headOrder.Item.Hash
tradeSDK.TxHash = txHash
tradeSDK.Hash = tradeSDK.ComputeHash()
log.Debug("TRADE history", "order", order, "trade", tradeSDK)
// put tradeSDK to mongodb on SDK node
if tomoXService.IsSDKNode() {
db := tomoXService.GetDB()
if err := db.Put(tomox.EmptyKey(), tradeSDK, true); err != nil {
return fmt.Errorf("failed to store tradeSDK %s", err.Error())
}
}
}
return nil
}
Loading

0 comments on commit 85b35b5

Please sign in to comment.