Skip to content

Commit

Permalink
more router tests. market buy bug fix
Browse files Browse the repository at this point in the history
  • Loading branch information
buck54321 committed Dec 1, 2021
1 parent 86dff7d commit 5cf469a
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 92 deletions.
2 changes: 2 additions & 0 deletions server/asset/eth/coiner_test.go
Expand Up @@ -163,6 +163,7 @@ func TestNewSwapCoin(t *testing.T) {
node: node,
log: tLogger,
contractAddr: *contractAddr,
initTxSize: uint32(dexeth.InitGas(1, 0)),
}
sc, err := eth.newSwapCoin(test.coinID, test.ct)
if test.wantErr {
Expand Down Expand Up @@ -320,6 +321,7 @@ func TestConfirmations(t *testing.T) {
node: node,
log: tLogger,
contractAddr: *contractAddr,
initTxSize: uint32(dexeth.InitGas(1, 0)),
}

sc, err := eth.newSwapCoin(txCoinIDBytes, test.ct)
Expand Down
19 changes: 7 additions & 12 deletions server/asset/eth/eth.go
Expand Up @@ -106,7 +106,6 @@ type ethFetcher interface {
type Backend struct {
// A connection-scoped Context is used to cancel active RPCs on
// connection shutdown.
ver uint32
rpcCtx context.Context
cancelRPCs context.CancelFunc
cfg *config
Expand All @@ -127,6 +126,8 @@ type Backend struct {
// case of updating where two contracts may be valid for some time,
// possibly disallowing initialization for the deprecated one only.
contractAddr common.Address
// initTxSize is the gas used for an initiation transaction with one swap.
initTxSize uint32
}

// Check that Backend satisfies the Backend interface.
Expand Down Expand Up @@ -157,6 +158,7 @@ func unconnectedETH(logger dex.Logger, cfg *config) *Backend {
log: logger,
blockChans: make(map[chan *asset.BlockUpdate]struct{}),
contractAddr: contractAddr,
initTxSize: uint32(dexeth.InitGas(1, version)),
}
}

Expand Down Expand Up @@ -226,21 +228,14 @@ func (eth *Backend) TxData(coinID []byte) ([]byte, error) {
return tx.MarshalBinary()
}

// InitTxSize is not size for eth. In ethereum the size of a non-standard
// transaction does not say anything about the processing power the ethereum
// virtual machine will use in order to process it, and therefor gas needed
// cannot be ascertained from it. Multiplying the required gas by the gas price
// will give us the actual fee needed, so returning gas here.
// InitTxSize is an upper limit on the gas used for an initiation.
func (eth *Backend) InitTxSize() uint32 {
return uint32(dexeth.InitGas(1, eth.ver))
return eth.initTxSize
}

// InitTxSizeBase is used in fee.go in a fee calculation. Currently we are
// unable to batch eth contract calls like UTXO coins so all contracts will
// need to be per transaction. Setting this to zero produces the expected
// result in fee calculations.
// InitTxSizeBase is the same as InitTxSize for ETH.
func (eth *Backend) InitTxSizeBase() uint32 {
return uint32(dexeth.InitGas(1, eth.ver))
return eth.initTxSize
}

// FeeRate returns the current optimal fee rate in gwei / gas.
Expand Down
4 changes: 3 additions & 1 deletion server/asset/eth/eth_test.go
Expand Up @@ -336,7 +336,9 @@ func TestSynced(t *testing.T) {
// TestRequiredOrderFunds ensures that a fee calculation in the calc package
// will come up with the correct required funds.
func TestRequiredOrderFunds(t *testing.T) {
eth := new(Backend)
eth := &Backend{
initTxSize: uint32(dexeth.InitGas(1, 0)),
}
swapVal := uint64(1000000000) // gwei
numSwaps := uint64(17) // swaps
initSizeBase := uint64(eth.InitTxSizeBase()) // 0 gas
Expand Down
10 changes: 9 additions & 1 deletion server/market/balancer.go
Expand Up @@ -18,7 +18,7 @@ type DEXBalancer struct {
matchNegotiator MatchNegotiator
}

// NewDEXBalancer is a constructor for a BackedBalancer. Provided assets will
// NewDEXBalancer is a constructor for a DEXBalancer. Provided assets will
// be filtered for those that are account-based. The matchNegotitator is
// satisfied by the *Swapper.
func NewDEXBalancer(tunnels map[string]MarketTunnel, assets map[uint32]*asset.BackedAsset, matchNegotiator MatchNegotiator) *DEXBalancer {
Expand Down Expand Up @@ -53,6 +53,10 @@ func (b *DEXBalancer) CheckBalance(acctAddr string, assetID uint32, qty, lots ui
log.Errorf("asset ID %d not found in accountBalancer assets map", assetID)
return false
}

log.Tracef("balance check for %s - %s: new qty = %d, new lots = %d, new redeems = %d",
backedAsset.assetInfo.Symbol, acctAddr, qty, lots, redeems)

bal, err := backedAsset.balancer.AccountBalance(acctAddr)
if err != nil {
log.Error("error getting account balance for %q: %v", acctAddr, err)
Expand All @@ -77,6 +81,10 @@ func (b *DEXBalancer) CheckBalance(acctAddr string, assetID uint32, qty, lots ui
redeemCosts := uint64(redeems) * assetInfo.RedeemSize * assetInfo.MaxFeeRate
reqFunds := calc.RequiredOrderFunds(qty, 0, lots, assetInfo) + redeemCosts

log.Tracef("balance check for %s - %s: total qty = %d, total lots = %d, "+
"total redeems = %d, redeemCosts = %d, required = %d, bal = %d",
backedAsset.assetInfo.Symbol, acctAddr, qty, lots, redeems, redeemCosts, reqFunds, bal)

return bal >= reqFunds
}

Expand Down
2 changes: 1 addition & 1 deletion server/market/market.go
Expand Up @@ -374,7 +374,7 @@ ordersLoop:
log.Debugf("Checking %d base asset (%d) balances.", len(baseAcctStats), base)
for acctAddr, stats := range baseAcctStats {
if !cfg.Balancer.CheckBalance(acctAddr, mktInfo.Base, stats.qty, stats.lots, stats.redeems) {
log.Errorf("%s base asset account failed the startup balance check on the %s market", acctAddr, mktInfo.Name)
log.Info("%s base asset account failed the startup balance check on the %s market", acctAddr, mktInfo.Name)
failedBaseAccts[acctAddr] = true
}
}
Expand Down
13 changes: 6 additions & 7 deletions server/market/orderrouter.go
Expand Up @@ -366,7 +366,6 @@ func (r *OrderRouter) handleMarket(user account.AccountID, msg *msgjson.Message)
var commit order.Commitment
copy(commit[:], market.Commit)

// fundingAsset := assets.funding
coinIDs := make([]order.CoinID, 0, len(market.Trade.Coins))
for _, coin := range market.Trade.Coins {
coinID := order.CoinID(coin.ID)
Expand Down Expand Up @@ -416,13 +415,13 @@ func (r *OrderRouter) processTrade(oRecord *orderRecord, tunnel MarketTunnel, as
receivingBalancer, isToAccount := assets.receiving.Backend.(asset.AccountBalancer)
if isToAccount {
if redeemSig == nil {
log.Errorf("user %s did not include a RedeemSig for received asset %s", user, assets.receiving.Symbol)
log.Info("user %s did not include a RedeemSig for received asset %s", user, assets.receiving.Symbol)
return msgjson.NewError(msgjson.OrderParameterError, "no redeem address verification included for asset %s", assets.receiving.Symbol)
}

acctAddr := trade.ToAccount()
if err := receivingBalancer.ValidateSignature(acctAddr, redeemSig.PubKey, sigMsg, redeemSig.Sig); err != nil {
log.Errorf("user %s failed redeem signature validation for order %s: %v",
log.Info("user %s failed redeem signature validation for order %s: %v",
user, oRecord.order.ID(), err)
return msgjson.NewError(msgjson.SignatureError, "redeem signature validation failed")
}
Expand All @@ -439,12 +438,12 @@ func (r *OrderRouter) processTrade(oRecord *orderRecord, tunnel MarketTunnel, as
// Validate that the coins are correct for an account-based-asset-funded
// order. There should be 1 coin, 1 sig, 1 pubkey, and no redeem script.
if len(coins) != 1 {
log.Errorf("user %s submitted an %s-funded order with %d coin IDs", user, assets.funding.Symbol, len(coins))
log.Info("user %s submitted an %s-funded order with %d coin IDs", user, assets.funding.Symbol, len(coins))
return msgjson.NewError(msgjson.OrderParameterError, "account-type asset funding requires exactly one coin ID")
}
acctProof := coins[0]
if len(acctProof.PubKeys) != 1 || len(acctProof.Sigs) != 1 || len(acctProof.Redeem) > 0 {
log.Errorf("user %s submitted an %s-funded order with %d pubkeys, %d sigs, redeem script length %d",
log.Info("user %s submitted an %s-funded order with %d pubkeys, %d sigs, redeem script length %d",
user, assets.funding.Symbol, len(acctProof.PubKeys), len(acctProof.Sigs), len(acctProof.Redeem))
return msgjson.NewError(msgjson.OrderParameterError, "account-type asset funding requires exactly one coin ID")
}
Expand All @@ -453,7 +452,7 @@ func (r *OrderRouter) processTrade(oRecord *orderRecord, tunnel MarketTunnel, as
pubKey := acctProof.PubKeys[0]
sig := acctProof.Sigs[0]
if err := fundingBalancer.ValidateSignature(acctAddr, pubKey, sigMsg, sig); err != nil {
log.Errorf("user %s failed signature validation for order %s: %v",
log.Info("user %s failed signature validation for order %s: %v",
user, oRecord.order.ID(), err)
return msgjson.NewError(msgjson.SignatureError, "signature validation failed")
}
Expand Down Expand Up @@ -649,7 +648,7 @@ func (r *OrderRouter) sufficientAccountBalance(accountAddr string, ord order.Ord
fundingQty = calc.BaseToQuote(lo.Rate, trade.Quantity)
fundingLots = trade.Quantity / tunnel.LotSize()
} else { // market buy
fundingQty = calc.QuoteToBase(safeMidGap(tunnel), trade.Quantity)
fundingQty = trade.Quantity
fundingLots = fundingQty / tunnel.LotSize()
}
}
Expand Down

0 comments on commit 5cf469a

Please sign in to comment.