Skip to content

Commit

Permalink
Don't sort transactions.
Browse files Browse the repository at this point in the history
  • Loading branch information
martonp committed Apr 16, 2022
1 parent 8ec7017 commit 0067de8
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 108 deletions.
128 changes: 26 additions & 102 deletions client/asset/btc/btc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1933,7 +1933,7 @@ func (btc *baseWallet) AccelerationEstimate(swapCoins, accelerationCoins []dex.B
// since either the earliest unconfirmed transaction in the chain, or the
// latest acceleration transaction. It also returns the minimum time when
// the user can do an acceleration.
func tooEarlyToAccelerate(sortedTxChain []*GetTransactionResult, accelerationCoins []dex.Bytes) (bool, uint64, error) {
func tooEarlyToAccelerate(txs []*GetTransactionResult, accelerationCoins []dex.Bytes) (bool, uint64, error) {
accelerationTxs := make(map[string]bool, len(accelerationCoins))
for _, accelerationCoin := range accelerationCoins {
txHash, _, err := decodeCoinID(accelerationCoin)
Expand All @@ -1943,24 +1943,30 @@ func tooEarlyToAccelerate(sortedTxChain []*GetTransactionResult, accelerationCoi
accelerationTxs[txHash.String()] = true
}

var timeToCompare uint64
for _, tx := range sortedTxChain {
var latestAcceleration, earliestUnconfirmed uint64
for _, tx := range txs {
if tx.Confirmations > 0 {
continue
}
if timeToCompare == 0 {
timeToCompare = tx.Time
if accelerationTxs[tx.TxID] && tx.Time > latestAcceleration {
latestAcceleration = tx.Time
continue
}
if accelerationTxs[tx.TxID] {
timeToCompare = tx.Time
if earliestUnconfirmed == 0 || tx.Time < earliestUnconfirmed {
earliestUnconfirmed = tx.Time
}
}

if timeToCompare == 0 {
if latestAcceleration == 0 && earliestUnconfirmed == 0 {
return false, 0, fmt.Errorf("no need to accelerate because all tx are confirmed")
}

var timeToCompare uint64
if latestAcceleration != 0 {
timeToCompare = latestAcceleration
} else {
timeToCompare = earliestUnconfirmed
}

currentTime := uint64(time.Now().Unix())
minAccelerationTime := timeToCompare + minTimeBeforeAcceleration
return minAccelerationTime > currentTime, minAccelerationTime, nil
Expand All @@ -1984,13 +1990,13 @@ func (btc *baseWallet) PreAccelerate(swapCoins, accelerationCoins []dex.Bytes, c
return makeError(err)
}

sortedTxChain, err := btc.sortedTxChain(swapCoins, accelerationCoins, changeCoin)
txs, err := btc.getTransactions(append(swapCoins, accelerationCoins...))
if err != nil {
return makeError(fmt.Errorf("failed to sort swap chain: %w", err))
}

var swapTxsSize, feesAlreadyPaid uint64
for _, tx := range sortedTxChain {
for _, tx := range txs {
if tx.Confirmations > 0 {
continue
}
Expand All @@ -2008,7 +2014,7 @@ func (btc *baseWallet) PreAccelerate(swapCoins, accelerationCoins []dex.Bytes, c
}

if btc.net != dex.Simnet {
tooEarly, minAccelerationTime, err := tooEarlyToAccelerate(sortedTxChain, accelerationCoins)
tooEarly, minAccelerationTime, err := tooEarlyToAccelerate(txs, accelerationCoins)
if err != nil {
return makeError(err)
}
Expand Down Expand Up @@ -2114,7 +2120,7 @@ func (btc *baseWallet) signedAccelerationTx(swapCoins, accelerationCoins []dex.B
return makeError(err)
}

sortedTxChain, err := btc.sortedTxChain(swapCoins, accelerationCoins, changeCoin)
txs, err := btc.getTransactions(append(swapCoins, accelerationCoins...))
if err != nil {
return makeError(fmt.Errorf("failed to sort swap chain: %w", err))
}
Expand All @@ -2124,7 +2130,7 @@ func (btc *baseWallet) signedAccelerationTx(swapCoins, accelerationCoins []dex.B
return makeError(err)
}

additionalFeesRequired, err := btc.additionalFeesRequired(sortedTxChain, newFeeRate)
additionalFeesRequired, err := btc.additionalFeesRequired(txs, newFeeRate)
if err != nil {
return makeError(err)
}
Expand All @@ -2134,7 +2140,7 @@ func (btc *baseWallet) signedAccelerationTx(swapCoins, accelerationCoins []dex.B
}

if btc.net != dex.Simnet {
tooEarly, minAccelerationTime, err := tooEarlyToAccelerate(sortedTxChain, accelerationCoins)
tooEarly, minAccelerationTime, err := tooEarlyToAccelerate(txs, accelerationCoins)
if err != nil {
return makeError(err)
}
Expand Down Expand Up @@ -2273,29 +2279,14 @@ func (btc *baseWallet) changeCanBeAccelerated(changeTxHash *chainhash.Hash, chan
return nil
}

// sortedTxChain takes a list of swap coins, acceleration tx IDs, and a change
// coin, and returns a sorted list of transactions. An error is returned if a
// sorted list of transactions that ends with a transaction containing the change
// cannot be created using each of the swap coins and acceleration transactions.
func (btc *baseWallet) sortedTxChain(swapCoins, accelerationCoins []dex.Bytes, change dex.Bytes) ([]*GetTransactionResult, error) {
txChain := make([]*GetTransactionResult, 0, len(swapCoins)+len(accelerationCoins))
if len(swapCoins) == 0 {
// getTransactions retrieves the transactions that created coins.
func (btc *baseWallet) getTransactions(coins []dex.Bytes) ([]*GetTransactionResult, error) {
txChain := make([]*GetTransactionResult, 0, len(coins))
if len(coins) == 0 {
return txChain, nil
}

for _, coinID := range swapCoins {
txHash, _, err := decodeCoinID(coinID)
if err != nil {
return nil, err
}
getTxRes, err := btc.node.getWalletTransaction(txHash)
if err != nil {
return nil, err
}
txChain = append(txChain, getTxRes)
}

for _, coinID := range accelerationCoins {
for _, coinID := range coins {
txHash, _, err := decodeCoinID(coinID)
if err != nil {
return nil, err
Expand All @@ -2307,73 +2298,6 @@ func (btc *baseWallet) sortedTxChain(swapCoins, accelerationCoins []dex.Bytes, c
txChain = append(txChain, getTxRes)
}

msgTxs := make(map[string]*wire.MsgTx, len(txChain))
for _, gtr := range txChain {
msgTx, err := msgTxFromBytes(gtr.Hex)
if err != nil {
return nil, err
}
msgTxs[gtr.TxID] = msgTx
}

changeTxHash, _, err := decodeCoinID(change)
if err != nil {
return nil, err
}

swap := func(i, j int) {
temp := txChain[j]
txChain[j] = txChain[i]
txChain[i] = temp
}

// sourcesOfTxInputs finds the transaction IDs that the inputs
// for a certain transaction come from. If all the transactions
// are from the same order, only the first transaction in
// the chain can have multiple inputs.
sourcesOfTxInputs := func(txID string) (map[string]bool, error) {
lastTx, found := msgTxs[txID]
if !found {
// this should never happen
return nil, fmt.Errorf("could not find tx with id: %v", txID)
}

inputSources := make(map[string]bool, len(lastTx.TxIn))
for _, in := range lastTx.TxIn {
inputSources[in.PreviousOutPoint.Hash.String()] = true
}
return inputSources, nil
}

// The last tx in the chain must have the same tx hash as the change.
for i, tx := range txChain {
if tx.TxID == changeTxHash.String() {
swap(i, len(txChain)-1)
break
}
if i == len(txChain)-1 {
return nil, fmt.Errorf("could not find tx containing change coin")
}
}

// We work backwards to find each element of the swap chain.
for i := len(txChain) - 2; i >= 0; i-- {
lastTxInputs, err := sourcesOfTxInputs(txChain[i+1].TxID)
if err != nil {
return nil, err
}

for j, getTxRes := range txChain {
if lastTxInputs[getTxRes.TxID] {
swap(i, j)
break
}
if j == len(txChain)-1 {
return nil, errors.New("could not find previous element of sorted chain")
}
}
}

return txChain, nil
}

Expand Down
12 changes: 6 additions & 6 deletions client/asset/btc/btc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3846,7 +3846,7 @@ func testAccelerateOrder(t *testing.T, segwit bool, walletType string) {
}
}

func TestTooEarlyToAcceelrate(t *testing.T) {
func TestTooEarlyToAccelerate(t *testing.T) {
tests := []struct {
name string
confirmations []uint64
Expand All @@ -3870,26 +3870,26 @@ func TestTooEarlyToAcceelrate(t *testing.T) {
},
{
name: "no accelerations, not too early",
confirmations: []uint64{2, 2, 0, 0},
confirmations: []uint64{2, 0, 0, 2},
isAcceleration: []bool{false, false, false, false},
secondsBeforeNow: []uint64{
minTimeBeforeAcceleration + 1000,
minTimeBeforeAcceleration + 800,
minTimeBeforeAcceleration + 500,
minTimeBeforeAcceleration + 300,
minTimeBeforeAcceleration + 800,
},
expectTooEarly: false,
expectMinTimeToAccelerate: -500,
},
{
name: "acceleration after unconfirmed, not too early",
confirmations: []uint64{2, 2, 0, 0},
isAcceleration: []bool{false, false, false, true},
confirmations: []uint64{0, 2, 2, 0},
isAcceleration: []bool{true, false, false, false},
secondsBeforeNow: []uint64{
minTimeBeforeAcceleration + 300,
minTimeBeforeAcceleration + 1000,
minTimeBeforeAcceleration + 800,
minTimeBeforeAcceleration + 500,
minTimeBeforeAcceleration + 300,
},
expectTooEarly: false,
expectMinTimeToAccelerate: -300,
Expand Down

0 comments on commit 0067de8

Please sign in to comment.