Skip to content

Commit 6860081

Browse files
committed
checkpoint. redid server. tests passing. no v1 tests on server yet.
1 parent 20a390e commit 6860081

12 files changed

Lines changed: 758 additions & 436 deletions

File tree

client/asset/eth/contractor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ func (c *contractorV1) redeem(txOpts *bind.TransactOpts, redeems []*asset.Redemp
699699

700700
// Not checking version from DecodeLocator because it was already
701701
// audited and incorrect version locator would err below anyway.
702-
_, locator, err := dexeth.DecodeLocator(r.Spends.Contract)
702+
_, locator, err := dexeth.DecodeContractData(r.Spends.Contract)
703703
if err != nil {
704704
return nil, fmt.Errorf("error parsing locator redeem: %w", err)
705705
}

client/asset/eth/eth.go

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,6 @@ const (
9797
// TODO: Find a way to ask the host about their config set max fee and
9898
// gas values.
9999
maxTxFeeGwei = 1_000_000_000
100-
101-
contractVersionERC20 = ^uint32(0)
102-
contractVersionUnknown = contractVersionERC20 - 1
103100
)
104101

105102
var (
@@ -619,14 +616,7 @@ func privKeyFromSeed(seed []byte) (pk []byte, zero func(), err error) {
619616
// contractVersion converts a server version to a contract version. It applies
620617
// to both tokens and eth right now, but that may not always be the case.
621618
func contractVersion(serverVer uint32) uint32 {
622-
switch serverVer {
623-
case 0:
624-
return 0
625-
case 1:
626-
return 1
627-
default:
628-
return contractVersionUnknown
629-
}
619+
return dexeth.ProtocolVersion(serverVer).ContractVersion()
630620
}
631621

632622
// CreateWallet creates a new internal ETH wallet and stores the private key
@@ -2149,7 +2139,7 @@ func (w *assetWallet) Redeem(form *asset.RedeemForm, feeWallet *assetWallet, non
21492139
// from redemption.Spends.Contract. Even for scriptable UTXO assets, the
21502140
// redeem script in this Contract field is redundant with the SecretHash
21512141
// field as ExtractSwapDetails can be applied to extract the hash.
2152-
ver, locator, err := dexeth.DecodeLocator(redemption.Spends.Contract)
2142+
ver, locator, err := dexeth.DecodeContractData(redemption.Spends.Contract)
21532143
if err != nil {
21542144
return fail(fmt.Errorf("Redeem: invalid versioned swap contract data: %w", err))
21552145
}
@@ -2304,7 +2294,7 @@ func recoverPubkey(msgHash, sig []byte) ([]byte, error) {
23042294
// tokenBalance checks the token balance of the account handled by the wallet.
23052295
func (w *assetWallet) tokenBalance() (bal *big.Int, err error) {
23062296
// We don't care about the version.
2307-
return bal, w.withTokenContractor(w.assetID, contractVersionERC20, func(c tokenContractor) error {
2297+
return bal, w.withTokenContractor(w.assetID, dexeth.ContractVersionERC20, func(c tokenContractor) error {
23082298
bal, err = c.balance(w.ctx)
23092299
return err
23102300
})
@@ -2313,7 +2303,7 @@ func (w *assetWallet) tokenBalance() (bal *big.Int, err error) {
23132303
// tokenAllowance checks the amount of tokens that the swap contract is approved
23142304
// to spend on behalf of the account handled by the wallet.
23152305
func (w *assetWallet) tokenAllowance() (allowance *big.Int, err error) {
2316-
return allowance, w.withTokenContractor(w.assetID, contractVersionERC20, func(c tokenContractor) error {
2306+
return allowance, w.withTokenContractor(w.assetID, dexeth.ContractVersionERC20, func(c tokenContractor) error {
23172307
allowance, err = c.allowance(w.ctx)
23182308
return err
23192309
})
@@ -2678,7 +2668,7 @@ func (w *assetWallet) AuditContract(coinID, contract, serializedTx dex.Bytes, re
26782668
return nil, fmt.Errorf("AuditContract: coin id != txHash - coin id: %x, txHash: %s", coinID, tx.Hash())
26792669
}
26802670

2681-
version, locator, err := dexeth.DecodeLocator(contract)
2671+
version, locator, err := dexeth.DecodeContractData(contract)
26822672
if err != nil {
26832673
return nil, fmt.Errorf("AuditContract: failed to decode contract data: %w", err)
26842674
}
@@ -2720,19 +2710,8 @@ func (w *assetWallet) AuditContract(coinID, contract, serializedTx dex.Bytes, re
27202710
if !ok {
27212711
return nil, errors.New("AuditContract: tx does not initiate secret hash")
27222712
}
2723-
// Check vector equivalence. Secret hash equivalence is implied by the
2724-
// vectors presence in the map returned from ParseInitiateData.
2725-
if vec.Value != txVec.Value {
2726-
return nil, errors.New("tx data value doesn't match reported locator data")
2727-
}
2728-
if vec.To != txVec.To {
2729-
return nil, errors.New("tx to address doesn't match reported locator data")
2730-
}
2731-
if vec.From != txVec.From {
2732-
return nil, errors.New("tx from address doesn't match reported locator data")
2733-
}
2734-
if vec.LockTime != txVec.LockTime {
2735-
return nil, errors.New("tx lock time doesn't match reported locator data")
2713+
if !dexeth.CompareVectors(vec, txVec) {
2714+
return nil, fmt.Errorf("tx vector doesn't match expectation. %+v != %+v", txVec, vec)
27362715
}
27372716
val = vec.Value
27382717
participant = vec.To.String()
@@ -2781,7 +2760,7 @@ func (w *assetWallet) LockTimeExpired(ctx context.Context, lockTime time.Time) (
27812760
// ContractLockTimeExpired returns true if the specified contract's locktime has
27822761
// expired, making it possible to issue a Refund.
27832762
func (w *assetWallet) ContractLockTimeExpired(ctx context.Context, contract dex.Bytes) (bool, time.Time, error) {
2784-
contractVer, locator, err := dexeth.DecodeLocator(contract)
2763+
contractVer, locator, err := dexeth.DecodeContractData(contract)
27852764
if err != nil {
27862765
return false, time.Time{}, err
27872766
}
@@ -2869,7 +2848,7 @@ func (w *assetWallet) FindRedemption(ctx context.Context, _, contract dex.Bytes)
28692848
// contract, so we are basically doing the next best thing here.
28702849
const coinIDTmpl = coinIDTakerFoundMakerRedemption + "%s"
28712850

2872-
contractVer, locator, err := dexeth.DecodeLocator(contract)
2851+
contractVer, locator, err := dexeth.DecodeContractData(contract)
28732852
if err != nil {
28742853
return nil, nil, err
28752854
}
@@ -2948,7 +2927,7 @@ func (w *assetWallet) findSecret(locator []byte, contractVer uint32) ([]byte, st
29482927
// Refund refunds a contract. This can only be used after the time lock has
29492928
// expired.
29502929
func (w *assetWallet) Refund(_, contract dex.Bytes, feeRate uint64) (dex.Bytes, error) {
2951-
contractVer, locator, err := dexeth.DecodeLocator(contract)
2930+
contractVer, locator, err := dexeth.DecodeContractData(contract)
29522931
if err != nil {
29532932
return nil, fmt.Errorf("Refund: failed to decode contract: %w", err)
29542933
}
@@ -3046,7 +3025,7 @@ func (w *ETHWallet) EstimateRegistrationTxFee(feeRate uint64) uint64 {
30463025
// EstimateRegistrationTxFee returns an estimate for the tx fee needed to
30473026
// pay the registration fee using the provided feeRate.
30483027
func (w *TokenWallet) EstimateRegistrationTxFee(feeRate uint64) uint64 {
3049-
g := w.gases(contractVersionERC20)
3028+
g := w.gases(dexeth.ContractVersionERC20)
30503029
if g == nil {
30513030
w.log.Errorf("no gas table")
30523031
return math.MaxUint64
@@ -3121,7 +3100,7 @@ func (w *TokenWallet) canSend(value uint64, verifyBalance, isPreEstimate bool) (
31213100
return 0, nil, fmt.Errorf("error getting max fee rate: %w", err)
31223101
}
31233102

3124-
g := w.gases(contractVersionERC20)
3103+
g := w.gases(dexeth.ContractVersionERC20)
31253104
if g == nil {
31263105
return 0, nil, fmt.Errorf("gas table not found")
31273106
}
@@ -3213,7 +3192,7 @@ func (w *assetWallet) RestorationInfo(seed []byte) ([]*asset.WalletRestoration,
32133192
// SwapConfirmations gets the number of confirmations and the spend status
32143193
// for the specified swap.
32153194
func (w *assetWallet) SwapConfirmations(ctx context.Context, coinID dex.Bytes, contract dex.Bytes, _ time.Time) (confs uint32, spent bool, err error) {
3216-
contractVer, secretHash, err := dexeth.DecodeLocator(contract)
3195+
contractVer, secretHash, err := dexeth.DecodeContractData(contract)
32173196
if err != nil {
32183197
return 0, false, err
32193198
}
@@ -3392,7 +3371,7 @@ func (eth *assetWallet) DynamicRedemptionFeesPaid(ctx context.Context, coinID, c
33923371
// secret hashes.
33933372
func (eth *baseWallet) swapOrRedemptionFeesPaid(ctx context.Context, coinID, contractData dex.Bytes,
33943373
isInit bool) (fee uint64, secretHashes [][]byte, err error) {
3395-
contractVer, locator, err := dexeth.DecodeLocator(contractData)
3374+
contractVer, locator, err := dexeth.DecodeContractData(contractData)
33963375
if err != nil {
33973376
return 0, nil, err
33983377
}
@@ -3996,7 +3975,7 @@ func (w *assetWallet) checkUnconfirmedRedemption(locator []byte, contractVer uin
39963975
// entire redemption batch, a new transaction containing only the swap we are
39973976
// searching for will be created.
39983977
func (w *assetWallet) confirmRedemptionWithoutMonitoredTx(txHash common.Hash, redemption *asset.Redemption, feeWallet *assetWallet) (*asset.ConfirmRedemptionStatus, error) {
3999-
contractVer, locator, err := dexeth.DecodeLocator(redemption.Spends.Contract)
3978+
contractVer, locator, err := dexeth.DecodeContractData(redemption.Spends.Contract)
40003979
if err != nil {
40013980
return nil, fmt.Errorf("failed to decode contract data: %w", err)
40023981
}
@@ -4089,7 +4068,7 @@ func (w *assetWallet) confirmRedemption(coinID dex.Bytes, redemption *asset.Rede
40894068
txHash = monitoredTxHash
40904069
}
40914070

4092-
contractVer, locator, err := dexeth.DecodeLocator(redemption.Spends.Contract)
4071+
contractVer, locator, err := dexeth.DecodeContractData(redemption.Spends.Contract)
40934072
if err != nil {
40944073
return nil, fmt.Errorf("failed to decode contract data: %w", err)
40954074
}
@@ -4393,15 +4372,15 @@ func (w *ETHWallet) sendToAddr(addr common.Address, amt uint64, maxFeeRate *big.
43934372
func (w *TokenWallet) sendToAddr(addr common.Address, amt uint64, maxFeeRate *big.Int) (tx *types.Transaction, err error) {
43944373
w.baseWallet.nonceSendMtx.Lock()
43954374
defer w.baseWallet.nonceSendMtx.Unlock()
4396-
g := w.gases(contractVersionERC20)
4375+
g := w.gases(dexeth.ContractVersionERC20)
43974376
if g == nil {
43984377
return nil, fmt.Errorf("no gas table")
43994378
}
44004379
txOpts, err := w.node.txOpts(w.ctx, 0, g.Transfer, nil, nil)
44014380
if err != nil {
44024381
return nil, err
44034382
}
4404-
return tx, w.withTokenContractor(w.assetID, contractVersionERC20, func(c tokenContractor) error {
4383+
return tx, w.withTokenContractor(w.assetID, dexeth.ContractVersionERC20, func(c tokenContractor) error {
44054384
tx, err = c.transfer(txOpts, addr, w.evmify(amt))
44064385
if err != nil {
44074386
c.voidUnusedNonce()
@@ -4524,7 +4503,7 @@ func (w *assetWallet) loadContractors() error {
45244503

45254504
// withContractor runs the provided function with the versioned contractor.
45264505
func (w *assetWallet) withContractor(contractVer uint32, f func(contractor) error) error {
4527-
if contractVer == contractVersionERC20 {
4506+
if contractVer == dexeth.ContractVersionERC20 {
45284507
// For ERC02 methods, use the most recent contractor version.
45294508
var bestVer uint32
45304509
var bestContractor contractor
@@ -4557,16 +4536,17 @@ func (w *assetWallet) withTokenContractor(assetID, ver uint32, f func(tokenContr
45574536
// estimateApproveGas estimates the gas required for a transaction approving a
45584537
// spender for an ERC20 contract.
45594538
func (w *assetWallet) estimateApproveGas(newGas *big.Int) (gas uint64, err error) {
4560-
return gas, w.withTokenContractor(w.assetID, contractVersionERC20, func(c tokenContractor) error {
4539+
return gas, w.withTokenContractor(w.assetID, dexeth.ContractVersionERC20, func(c tokenContractor) error {
45614540
gas, err = c.estimateApproveGas(w.ctx, newGas)
45624541
return err
45634542
})
45644543
}
45654544

45664545
// estimateTransferGas estimates the gas needed for a token transfer call to an
45674546
// ERC20 contract.
4547+
// TODO: Delete this and contractor methods. Unused.
45684548
func (w *assetWallet) estimateTransferGas(val uint64) (gas uint64, err error) {
4569-
return gas, w.withTokenContractor(w.assetID, contractVersionERC20, func(c tokenContractor) error {
4549+
return gas, w.withTokenContractor(w.assetID, dexeth.ContractVersionERC20, func(c tokenContractor) error {
45704550
gas, err = c.estimateTransferGas(w.ctx, w.evmify(val))
45714551
return err
45724552
})

client/asset/eth/eth_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,7 +2149,7 @@ func testSwap(t *testing.T, assetID uint32) {
21492149
testName, receipt.Coin().Value(), contract.Value)
21502150
}
21512151
contractData := receipt.Contract()
2152-
contractVer, locator, err := dexeth.DecodeLocator(contractData)
2152+
contractVer, locator, err := dexeth.DecodeContractData(contractData)
21532153
if err != nil {
21542154
t.Fatalf("failed to decode contract data: %v", err)
21552155
}
@@ -2725,7 +2725,7 @@ func testRedeem(t *testing.T, assetID uint32) {
27252725
// Check that value of output coin is as axpected
27262726
var totalSwapValue uint64
27272727
for _, redemption := range test.form.Redemptions {
2728-
_, locator, err := dexeth.DecodeLocator(redemption.Spends.Contract)
2728+
_, locator, err := dexeth.DecodeContractData(redemption.Spends.Contract)
27292729
if err != nil {
27302730
t.Fatalf("DecodeLocator: %v", err)
27312731
}
@@ -3178,7 +3178,7 @@ func testAuditContract(t *testing.T, assetID uint32) {
31783178
t.Fatalf(`"%v": expected contract %x != actual %x`, test.name, test.contract, auditInfo.Contract)
31793179
}
31803180

3181-
_, expectedSecretHash, err := dexeth.DecodeLocator(test.contract)
3181+
_, expectedSecretHash, err := dexeth.DecodeContractData(test.contract)
31823182
if err != nil {
31833183
t.Fatalf(`"%v": failed to decode versioned bytes: %v`, test.name, err)
31843184
}

client/asset/eth/nodeclient.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ func gases(parentID, assetID uint32, contractVer uint32, net dex.Network) *dexet
429429
return nil
430430
}
431431

432-
if contractVer != contractVersionERC20 {
432+
if contractVer != dexeth.ContractVersionERC20 {
433433
contract, found := netToken.SwapContracts[contractVer]
434434
if !found {
435435
return nil

dex/networks/eth/params.go

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package eth
55

66
import (
77
"encoding/binary"
8+
"encoding/hex"
89
"encoding/json"
910
"errors"
1011
"fmt"
@@ -124,8 +125,20 @@ func EncodeContractData(contractVersion uint32, locator []byte) []byte {
124125
return b
125126
}
126127

127-
// DecodeLocator unpacks the contract version and secret hash.
128-
func DecodeLocator(data []byte) (contractVersion uint32, locator []byte, err error) {
128+
func DecodeContractDataV0(data []byte) (secretHash [32]byte, err error) {
129+
contractVer, secretHashB, err := DecodeContractData(data)
130+
if err != nil {
131+
return secretHash, err
132+
}
133+
if contractVer != 0 {
134+
return secretHash, errors.New("not contract version 0")
135+
}
136+
copy(secretHash[:], secretHashB)
137+
return
138+
}
139+
140+
// DecodeContractData unpacks the contract version and the locator.
141+
func DecodeContractData(data []byte) (contractVersion uint32, locator []byte, err error) {
129142
if len(data) < 4 {
130143
err = errors.New("invalid short encoding")
131144
return
@@ -271,6 +284,17 @@ func (v *SwapVector) Locator() []byte {
271284
return locator
272285
}
273286

287+
func (v *SwapVector) String() string {
288+
return fmt.Sprintf("{ from = %s, to = %s, value = %d, secret hash = %s, locktime = %s }",
289+
v.From, v.To, v.Value, hex.EncodeToString(v.SecretHash[:]), time.UnixMilli(int64(v.LockTime)))
290+
}
291+
292+
func CompareVectors(v1, v2 *SwapVector) bool {
293+
// Check vector equivalence.
294+
return v1.Value == v2.Value && v1.To == v2.To && v1.From == v2.From &&
295+
v1.LockTime == v2.LockTime && v1.SecretHash == v2.SecretHash
296+
}
297+
274298
// SwapStatus is the contract data that specifies the current contract state.
275299
type SwapStatus struct {
276300
BlockHeight uint64
@@ -390,12 +414,37 @@ func ParseV1Locator(locator []byte) (v *SwapVector, err error) {
390414
return
391415
}
392416

393-
func SwapVectorToAbigen(c *SwapVector) swapv1.ETHSwapVector {
417+
func SwapVectorToAbigen(v *SwapVector) swapv1.ETHSwapVector {
394418
return swapv1.ETHSwapVector{
395-
SecretHash: c.SecretHash,
396-
Initiator: c.From,
397-
RefundTimestamp: c.LockTime,
398-
Participant: c.To,
399-
Value: c.Value,
419+
SecretHash: v.SecretHash,
420+
Initiator: v.From,
421+
RefundTimestamp: v.LockTime,
422+
Participant: v.To,
423+
Value: v.Value,
424+
}
425+
}
426+
427+
// ProtocolVersion assists in mapping the dex.Asset.Version to a contract
428+
// version.
429+
type ProtocolVersion uint32
430+
431+
const (
432+
ProtocolVersionZero ProtocolVersion = iota
433+
ProtocolVersionV1Contracts
434+
)
435+
436+
func (v ProtocolVersion) ContractVersion() uint32 {
437+
switch v {
438+
case ProtocolVersionZero:
439+
return 0
440+
case ProtocolVersionV1Contracts:
441+
return 1
442+
default:
443+
return ContractVersionUnknown
400444
}
401445
}
446+
447+
var (
448+
ContractVersionERC20 = ^uint32(0)
449+
ContractVersionUnknown = ContractVersionERC20 - 1
450+
)

0 commit comments

Comments
 (0)