Skip to content

Commit

Permalink
update server/asset.Backend.Redemption with data arg
Browse files Browse the repository at this point in the history
  • Loading branch information
chappjc committed Dec 7, 2021
1 parent e3c4068 commit 607cdde
Show file tree
Hide file tree
Showing 13 changed files with 60 additions and 45 deletions.
4 changes: 2 additions & 2 deletions server/asset/btc/btc.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ func (btc *Backend) Synced() (bool, error) {
}

// Redemption is an input that redeems a swap contract.
func (btc *Backend) Redemption(redemptionID, contractID []byte) (asset.Coin, error) {
func (btc *Backend) Redemption(redemptionID, contractID, _ []byte) (asset.Coin, error) {
txHash, vin, err := decodeCoinID(redemptionID)
if err != nil {
return nil, fmt.Errorf("error decoding redemption coin ID %x: %w", txHash, err)
Expand Down Expand Up @@ -917,7 +917,7 @@ func (btc *Backend) auditContract(contract *Output) (*asset.Contract, error) {
return &asset.Contract{
Coin: contract,
SwapAddress: receiver.String(),
RedeemScript: contract.redeemScript,
ContractData: contract.redeemScript,
LockTime: time.Unix(int64(lockTime), 0),
TxData: contract.tx.raw,
}, nil
Expand Down
8 changes: 4 additions & 4 deletions server/asset/btc/btc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ func testRedemption(t *testing.T, segwit bool) {
// A valid mempool redemption.
verboseTx = testAddTxVerbose(msg.tx, txHash, nil, 0)
verboseTx.Vin = append(verboseTx.Vin, vin)
redemption, err := btc.Redemption(redemptionID, spentID)
redemption, err := btc.Redemption(redemptionID, spentID, nil)
if err != nil {
t.Fatalf("Redemption error: %v", err)
}
Expand All @@ -1136,7 +1136,7 @@ func testRedemption(t *testing.T, segwit bool) {
testChainMtx.Lock()
delete(testChain.txRaws, *txHash)
testChainMtx.Unlock()
_, err = btc.Redemption(redemptionID, spentID)
_, err = btc.Redemption(redemptionID, spentID, nil)
if err == nil {
t.Fatalf("No error for missing transaction")
}
Expand All @@ -1146,7 +1146,7 @@ func testRedemption(t *testing.T, segwit bool) {
verboseTx.Vin = append(verboseTx.Vin, btcjson.Vin{
Txid: randomHash().String(),
})
_, err = btc.Redemption(redemptionID, spentID)
_, err = btc.Redemption(redemptionID, spentID, nil)
if err == nil {
t.Fatalf("No error for wrong previous outpoint")
}
Expand All @@ -1157,7 +1157,7 @@ func testRedemption(t *testing.T, segwit bool) {
verboseTx = testAddTxVerbose(msg.tx, txHash, blockHash, int64(blockHeight))
verboseTx.Vin = append(verboseTx.Vin, vin)
testAddBlockVerbose(blockHash, nil, 1, blockHeight)
redemption, err = btc.Redemption(redemptionID, spentID)
redemption, err = btc.Redemption(redemptionID, spentID, nil)
if err != nil {
t.Fatalf("Redemption with confs error: %v", err)
}
Expand Down
17 changes: 10 additions & 7 deletions server/asset/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,17 @@ type Backend interface {
// of the asset.
dex.Connector
// Contract returns a Contract only for outputs that would be spendable on
// the blockchain immediately. The redeem script is required in order to
// calculate sigScript length and verify pubkeys.
Contract(coinID []byte, redeemScript []byte) (*Contract, error)
// the blockchain immediately. Contract data (e.g. the redeem script for
// UTXO assets) is required in order to calculate sigScript length and
// verify pubkeys.
Contract(coinID []byte, contractData []byte) (*Contract, error)
// TxData fetches the raw transaction data for the specified coin.
TxData(coinID []byte) ([]byte, error)
// ValidateSecret checks that the secret satisfies the contract.
ValidateSecret(secret, contract []byte) bool
ValidateSecret(secret, contractData []byte) bool
// Redemption returns a Coin for redemptionID, a transaction input, that
// spends contract ID, an output containing the swap contract.
Redemption(redemptionID, contractID []byte) (Coin, error)
Redemption(redemptionID, contractID, contractData []byte) (Coin, error)
// BlockChannel creates and returns a new channel on which to receive updates
// when new blocks are connected.
BlockChannel(size int) <-chan *BlockUpdate
Expand Down Expand Up @@ -144,8 +145,10 @@ type Contract struct {
Coin
// SwapAddress is the receiving address of the swap contract.
SwapAddress string
// RedeemScript is the contract redeem script.
RedeemScript []byte
// ContractData is essential data about this swap. For example, the redeem
// script for UTXO contracts, or a secret hash that keys swaps for account-
// based contracts.
ContractData []byte
// LockTime is the refund locktime.
LockTime time.Time
// TxData is raw transaction data. This data is provided for some assets
Expand Down
2 changes: 1 addition & 1 deletion server/asset/dcr/dcr.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ func (dcr *Backend) Synced() (bool, error) {
}

// Redemption is an input that redeems a swap contract.
func (dcr *Backend) Redemption(redemptionID, contractID []byte) (asset.Coin, error) {
func (dcr *Backend) Redemption(redemptionID, contractID, _ []byte) (asset.Coin, error) {
txHash, vin, err := decodeCoinID(redemptionID)
if err != nil {
return nil, fmt.Errorf("error decoding redemption coin ID %x: %w", txHash, err)
Expand Down
8 changes: 4 additions & 4 deletions server/asset/dcr/dcr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1181,7 +1181,7 @@ func TestRedemption(t *testing.T) {
// A valid mempool redemption.
verboseTx := testAddTxVerbose(msg.tx, txHash, nil, 0, 0)
verboseTx.Vin = append(verboseTx.Vin, vin)
redemption, err := dcr.Redemption(redemptionID, spentID)
redemption, err := dcr.Redemption(redemptionID, spentID, nil)
if err != nil {
t.Fatalf("Redemption error: %v", err)
}
Expand All @@ -1197,7 +1197,7 @@ func TestRedemption(t *testing.T) {
testChainMtx.Lock()
delete(testChain.txRaws, *txHash)
testChainMtx.Unlock()
_, err = dcr.Redemption(redemptionID, spentID)
_, err = dcr.Redemption(redemptionID, spentID, nil)
if err == nil {
t.Fatalf("No error for missing transaction")
}
Expand All @@ -1207,7 +1207,7 @@ func TestRedemption(t *testing.T) {
verboseTx.Vin = append(verboseTx.Vin, chainjson.Vin{
Txid: randomHash().String(),
})
_, err = dcr.Redemption(redemptionID, spentID)
_, err = dcr.Redemption(redemptionID, spentID, nil)
if err == nil {
t.Fatalf("No error for wrong previous outpoint")
}
Expand All @@ -1218,7 +1218,7 @@ func TestRedemption(t *testing.T) {
verboseTx = testAddTxVerbose(msg.tx, txHash, blockHash, int64(blockHeight), 1)
verboseTx.Vin = append(verboseTx.Vin, vin)
testAddBlockVerbose(blockHash, 1, blockHeight, 1)
redemption, err = dcr.Redemption(redemptionID, spentID)
redemption, err = dcr.Redemption(redemptionID, spentID, nil)
if err != nil {
t.Fatalf("Redemption with confs error: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion server/asset/dcr/utxo.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ func auditContract(op *Output) (*asset.Contract, error) {
return &asset.Contract{
Coin: op,
SwapAddress: receiver.String(),
RedeemScript: op.redeemScript,
ContractData: op.redeemScript,
LockTime: time.Unix(int64(lockTime), 0),
TxData: op.tx.raw,
}, nil
Expand Down
35 changes: 23 additions & 12 deletions server/asset/eth/coiner.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package eth
import (
"bytes"
"context"
"encoding/hex"
"errors"
"fmt"
"math/big"
Expand All @@ -28,6 +27,17 @@ const (
sctRedeem
)

func (sct swapCoinType) String() string {
switch sct {
case sctInit:
return "init"
case sctRedeem:
return "redeem"
default:
return "invalid type"
}
}

var _ asset.Coin = (*swapCoin)(nil)

type swapCoin struct {
Expand All @@ -36,6 +46,7 @@ type swapCoin struct {
secret, secretHash [32]byte
value uint64
gasPrice uint64
txHash common.Hash
txid string
locktime int64
sct swapCoinType
Expand All @@ -59,11 +70,11 @@ func (backend *Backend) newSwapCoin(coinID []byte, contract []byte, sct swapCoin
return nil, fmt.Errorf("unknown swapCoin type: %d", sct)
}

txid, err := dexeth.DecodeCoinID(coinID)
txHash, err := dexeth.DecodeCoinID(coinID)
if err != nil {
return nil, err
}
tx, _, err := backend.node.transaction(backend.rpcCtx, txid)
tx, _, err := backend.node.transaction(backend.rpcCtx, txHash)
if err != nil {
if errors.Is(err, ethereum.NotFound) {
return nil, asset.CoinNotFoundError
Expand Down Expand Up @@ -103,7 +114,7 @@ func (backend *Backend) newSwapCoin(coinID []byte, contract []byte, sct swapCoin
}
}
if initiation == nil {
return nil, fmt.Errorf("tx %x does not contain initiation with secret hash %x", txid, secretHash)
return nil, fmt.Errorf("tx %v does not contain initiation with secret hash %x", txHash, secretHash)
}
counterParty = &initiation.Participant
secretHash = initiation.SecretHash
Expand All @@ -120,7 +131,7 @@ func (backend *Backend) newSwapCoin(coinID []byte, contract []byte, sct swapCoin
}
}
if redemption == nil {
return nil, fmt.Errorf("tx %x does not contain redemption with secret hash %x", txid, secretHash)
return nil, fmt.Errorf("tx %v does not contain redemption with secret hash %x", txHash, secretHash)
}
secret = redemption.Secret
secretHash = redemption.SecretHash
Expand Down Expand Up @@ -158,7 +169,8 @@ func (backend *Backend) newSwapCoin(coinID []byte, contract []byte, sct swapCoin
secretHash: secretHash,
value: value,
gasPrice: gasPrice,
txid: hex.EncodeToString(txid[:]),
txHash: txHash,
txid: txHash.Hex(), // == String(), with 0x prefix
counterParty: *counterParty,
locktime: locktime,
sct: sct,
Expand All @@ -185,7 +197,7 @@ func (c *swapCoin) validateRedeem(contractID []byte) error {
// confirming a swap. Even though we check the initial transaction's data, if
// that transaction were in mempool at the time, it could be swapped out with
// any other values if a user sent another transaction with a higher gas fee
// and the same account and nonce, effectivly voiding the transaction we
// and the same account and nonce, effectively voiding the transaction we
// expected to be mined.
func (c *swapCoin) Confirmations(_ context.Context) (int64, error) {
swap, err := c.backend.node.swap(c.backend.rpcCtx, c.secretHash)
Expand Down Expand Up @@ -224,7 +236,7 @@ func (c *swapCoin) Confirmations(_ context.Context) (int64, error) {
// Uninitiated state is zero confs. It could still be in mempool.
// It is important to only trust confirmations according to the
// swap contract. Until there are confirmations we cannot be sure
// that initiation happened successfuly.
// that initiation happened successfully.
if dexeth.SwapStep(swap.State) == dexeth.SSNone {
// Assume the tx still has a chance of being mined.
return 0, nil
Expand All @@ -234,7 +246,7 @@ func (c *swapCoin) Confirmations(_ context.Context) (int64, error) {

// The swap initiation transaction has some number of
// confirmations, and we are sure the secret hash belongs to
// this swap. Assert that the value, reciever, and locktime are
// this swap. Assert that the value, receiver, and locktime are
// as expected.
value, err := dexeth.ToGwei(new(big.Int).Set(swap.Value))
if err != nil {
Expand Down Expand Up @@ -269,8 +281,7 @@ func (c *swapCoin) Confirmations(_ context.Context) (int64, error) {

// ID is the swap's coin ID.
func (c *swapCoin) ID() []byte {
b, _ := hex.DecodeString(c.txid) // or store it as a field
return b
return c.txHash.Bytes() // c.txHash[:]
}

// TxID is the original init transaction txid.
Expand All @@ -280,7 +291,7 @@ func (c *swapCoin) TxID() string {

// String is a human readable representation of the swap coin.
func (c *swapCoin) String() string {
return c.txid
return fmt.Sprintf("%v (%s)", c.txid, c.sct)
}

// Value is the amount paid to the swap, set in initialization. Always zero for
Expand Down
9 changes: 5 additions & 4 deletions server/asset/eth/coiner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
package eth

import (
"encoding/hex"
"errors"
"fmt"
"math/big"
"testing"

Expand Down Expand Up @@ -36,8 +36,9 @@ func randomAddress() *common.Address {

func TestNewSwapCoin(t *testing.T) {
contractAddr, randomAddr := randomAddress(), randomAddress()
secret, secretHash, txHash := [32]byte{}, [32]byte{}, [32]byte{}
var secret, secretHash, txHash [32]byte
copy(txHash[:], encode.RandomBytes(32))
txid := fmt.Sprintf("%#x", txHash[:]) // 0xababab...
copy(secret[:], redeemSecretB)
copy(secretHash[:], redeemSecretHashB)
txCoinIDBytes := txHash[:]
Expand Down Expand Up @@ -221,8 +222,8 @@ func TestNewSwapCoin(t *testing.T) {
sc.gasPrice != wantGas ||
sc.locktime != lt ||
sc.sct != sct ||
sc.txid != hex.EncodeToString(txHash[:]) {
t.Fatalf("returns do not match expected for test %q", test.name)
sc.txid != txid {
t.Fatalf("returns do not match expected for test %q / %v", test.name, sc)
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions server/asset/eth/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func (eth *Backend) Contract(coinID, contract []byte) (*asset.Contract, error) {
return &asset.Contract{
Coin: sc,
SwapAddress: sc.counterParty.String(),
RedeemScript: sc.secretHash[:],
ContractData: sc.secretHash[:],
LockTime: encode.UnixTimeMilli(sc.locktime),
}, nil
}
Expand Down Expand Up @@ -308,14 +308,14 @@ func (eth *Backend) Synced() (bool, error) {
// Redemption returns a coin that represents a contract redemption. redeemCoinID
// should be the transaction that sent a redemption, while contractCoinID is the
// swap contract this redemption redeems.
func (eth *Backend) Redemption(redeemCoinID, contractCoinID []byte) (asset.Coin, error) {
cnr, err := eth.newSwapCoin(redeemCoinID, contractCoinID, sctRedeem)
func (eth *Backend) Redemption(redeemCoinID, _, contractData []byte) (asset.Coin, error) {
cnr, err := eth.newSwapCoin(redeemCoinID, contractData, sctRedeem)
if err != nil {
return nil, fmt.Errorf("unable to create coiner: %w", err)
}
// Ensure that the redeem is for the same coin hash and contract as the
// contract coin.
if err = cnr.validateRedeem(contractCoinID); err != nil {
if err = cnr.validateRedeem(contractData); err != nil {
return nil, fmt.Errorf("unable to validate redeem: %v", err)
}
// Confirmations performs some extra swap status checks if the the tx
Expand Down
2 changes: 1 addition & 1 deletion server/asset/eth/eth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ func TestRedemption(t *testing.T) {
log: tLogger,
contractAddr: *contractAddr,
}
_, err := eth.Redemption(test.coinID, test.contractID)
_, err := eth.Redemption(test.coinID, nil, test.contractID)
if test.wantErr {
if err == nil {
t.Fatalf("expected error for test %q", test.name)
Expand Down
2 changes: 1 addition & 1 deletion server/market/routers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ func (b *TBackend) Contract(coinID, redeemScript []byte) (*asset.Contract, error
}
return &asset.Contract{Coin: c}, nil
}
func (b *TBackend) Redemption(redemptionID, contractID []byte) (asset.Coin, error) {
func (b *TBackend) Redemption(redemptionID, contractID, contractData []byte) (asset.Coin, error) {
return b.utxo(redemptionID)
}
func (b *TBackend) BlockChannel(size int) <-chan *asset.BlockUpdate { return nil }
Expand Down
6 changes: 3 additions & 3 deletions server/swap/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ func (s *Swapper) restoreActiveSwaps(allowPartial bool) error {

if redeemCoin := ssd.RedeemCoinIn; len(redeemCoin) > 0 {
assetID := ssd.RedeemAsset
redeem, err := s.coins[assetID].Backend.Redemption(redeemCoin, cpSwapCoin)
redeem, err := s.coins[assetID].Backend.Redemption(redeemCoin, cpSwapCoin, ssd.ContractScript)
if err != nil {
return fmt.Errorf("unable to find redeem in coin %x for asset %d: %w", redeemCoin, assetID, err)
}
Expand Down Expand Up @@ -1534,7 +1534,7 @@ func (s *Swapper) processRedeem(msg *msgjson.Message, params *msgjson.Redeem, st
// Make sure that the expected output is being spent.
actor, counterParty := stepInfo.actor, stepInfo.counterParty
counterParty.status.mtx.RLock()
cpContract := counterParty.status.swap.RedeemScript
cpContract := counterParty.status.swap.ContractData
cpSwapCoin := counterParty.status.swap.ID()
cpSwapStr := counterParty.status.swap.String()
counterParty.status.mtx.RUnlock()
Expand All @@ -1549,7 +1549,7 @@ func (s *Swapper) processRedeem(msg *msgjson.Message, params *msgjson.Redeem, st
s.respondError(msg.ID, actor.user, msgjson.UnknownMarketError, "secret validation failed")
return wait.DontTryAgain
}
redemption, err := chain.Redemption(params.CoinID, cpSwapCoin)
redemption, err := chain.Redemption(params.CoinID, cpSwapCoin, cpContract)
// If there is an error, don't return an error yet, since it could be due to
// network latency. Instead, queue it up for another check.
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion server/swap/swap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ func (a *TBackend) Contract(coinID, redeemScript []byte) (*asset.Contract, error

return contract, nil
}
func (a *TBackend) Redemption(redemptionID, cpSwapCoinID []byte) (asset.Coin, error) {
func (a *TBackend) Redemption(redemptionID, cpSwapCoinID, contractData []byte) (asset.Coin, error) {
a.mtx.RLock()
defer a.mtx.RUnlock()
if a.redemptionErr != nil {
Expand Down

0 comments on commit 607cdde

Please sign in to comment.