diff --git a/client/asset/eth/eth.go b/client/asset/eth/eth.go index 88aca6b09b..381b05aab1 100644 --- a/client/asset/eth/eth.go +++ b/client/asset/eth/eth.go @@ -26,7 +26,6 @@ import ( "decred.org/dcrdex/dex/keygen" dexeth "decred.org/dcrdex/dex/networks/eth" "decred.org/dcrdex/dex/networks/eth/swap" - srveth "decred.org/dcrdex/server/asset/eth" "github.com/decred/dcrd/dcrutil/v4" "github.com/decred/dcrd/hdkeychain/v3" "github.com/ethereum/go-ethereum" @@ -113,7 +112,7 @@ func (d *Driver) Open(cfg *asset.WalletConfig, logger dex.Logger, network dex.Ne // DecodeCoinID creates a human-readable representation of a coin ID for Ethereum. func (d *Driver) DecodeCoinID(coinID []byte) (string, error) { - id, err := srveth.DecodeCoinID(coinID) + id, err := dexeth.DecodeCoinID(coinID) if err != nil { return "", nil } @@ -360,7 +359,7 @@ func (eth *ExchangeWallet) balanceImpl() (*asset.Balance, error) { if err != nil { return nil, err } - gweiBal, err := srveth.ToGwei(bigBal) + gweiBal, err := dexeth.ToGwei(bigBal) if err != nil { return nil, err } @@ -509,7 +508,7 @@ func (*ExchangeWallet) PreRedeem(req *asset.PreRedeemForm) (*asset.PreRedeem, er // coin implements the asset.Coin interface for ETH type coin struct { - id srveth.AmountCoinID + id dexeth.AmountCoinID } // ID is the ETH coins ID. It includes the address the coins came from (20 bytes) @@ -534,12 +533,12 @@ var _ asset.Coin = (*coin)(nil) // decodeCoinID decodes a coin id into a coin object. The coin id // must contain an AmountCoinID. func decodeCoinID(coinID []byte) (*coin, error) { - id, err := srveth.DecodeCoinID(coinID) + id, err := dexeth.DecodeCoinID(coinID) if err != nil { return nil, err } - amountCoinID, ok := id.(*srveth.AmountCoinID) + amountCoinID, ok := id.(*dexeth.AmountCoinID) if !ok { return nil, fmt.Errorf("coinID is expected to be an amount coin id") @@ -565,7 +564,7 @@ func (eth *ExchangeWallet) FundOrder(ord *asset.Order) (asset.Coins, []dex.Bytes var address [20]byte copy(address[:], eth.acct.Address.Bytes()) coin := coin{ - id: srveth.AmountCoinID{ + id: dexeth.AmountCoinID{ Address: address, Amount: fundsNeeded, Nonce: nonce, @@ -811,7 +810,7 @@ func (eth *ExchangeWallet) sendToAddr(addr common.Address, amt, gasPrice *big.In // TODO: Subtract fees from the value. func (eth *ExchangeWallet) Withdraw(addr string, value, feeSuggestion uint64) (asset.Coin, error) { bigVal := big.NewInt(0).SetUint64(value) - gweiFactorBig := big.NewInt(srveth.GweiFactor) + gweiFactorBig := big.NewInt(dexeth.GweiFactor) _, err := eth.sendToAddr(common.HexToAddress(addr), bigVal.Mul(bigVal, gweiFactorBig), big.NewInt(0).SetUint64(defaultGasFee)) if err != nil { @@ -835,7 +834,7 @@ func (*ExchangeWallet) Confirmations(ctx context.Context, id dex.Bytes) (confs u func (eth *ExchangeWallet) SyncStatus() (bool, float32, error) { // node.SyncProgress will return nil both before syncing has begun and // after it has finished. In order to discern when syncing has begun, - // check that the best header came in under srveth.MaxBlockInterval. + // check that the best header came in under dexeth.MaxBlockInterval. sp, err := eth.node.syncProgress(eth.ctx) if err != nil { return false, 0, err @@ -855,7 +854,7 @@ func (eth *ExchangeWallet) SyncStatus() (bool, float32, error) { nowInSecs := time.Now().Unix() / 1000 timeDiff := nowInSecs - int64(bh.Time) var progress float32 - if timeDiff < srveth.MaxBlockInterval { + if timeDiff < dexeth.MaxBlockInterval { progress = 1 } return progress == 1, progress, nil diff --git a/client/asset/eth/eth_test.go b/client/asset/eth/eth_test.go index 1a2e78f7a8..3571d8a835 100644 --- a/client/asset/eth/eth_test.go +++ b/client/asset/eth/eth_test.go @@ -17,8 +17,8 @@ import ( "decred.org/dcrdex/client/asset" "decred.org/dcrdex/dex" "decred.org/dcrdex/dex/encode" + dexeth "decred.org/dcrdex/dex/networks/eth" "decred.org/dcrdex/dex/networks/eth/swap" - dexeth "decred.org/dcrdex/server/asset/eth" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" diff --git a/client/asset/eth/rpcclient_harness_test.go b/client/asset/eth/rpcclient_harness_test.go index b6574fcd8b..8676c75d1e 100644 --- a/client/asset/eth/rpcclient_harness_test.go +++ b/client/asset/eth/rpcclient_harness_test.go @@ -42,9 +42,9 @@ import ( "decred.org/dcrdex/client/asset" "decred.org/dcrdex/dex" "decred.org/dcrdex/dex/encode" + dexeth "decred.org/dcrdex/dex/networks/eth" "decred.org/dcrdex/dex/networks/eth/swap" "decred.org/dcrdex/internal/eth/reentryattack" - srveth "decred.org/dcrdex/server/asset/eth" "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" @@ -446,10 +446,10 @@ func TestInitiateGas(t *testing.T) { var expectedGas uint64 var actualGas uint64 if i == 1 { - expectedGas = srveth.InitGas + expectedGas = dexeth.InitGas actualGas = gas } else { - expectedGas = srveth.AdditionalInitGas + expectedGas = dexeth.AdditionalInitGas actualGas = gas - previousGas } if actualGas > expectedGas || actualGas < expectedGas/100*95 { @@ -478,9 +478,9 @@ func TestInitiate(t *testing.T) { if err != nil { t.Fatal("unable to get swap state") } - state := srveth.SwapState(swap.State) - if state != srveth.SSNone { - t.Fatalf("unexpected swap state: want %s got %s", srveth.SSNone, state) + state := dexeth.SwapState(swap.State) + if state != dexeth.SSNone { + t.Fatalf("unexpected swap state: want %s got %s", dexeth.SSNone, state) } } @@ -639,13 +639,13 @@ func TestInitiate(t *testing.T) { t.Fatalf("unexpected error for test %v: %v", test.name, err) } - originalStates := make(map[string]srveth.SwapState) + originalStates := make(map[string]dexeth.SwapState) for _, testSwap := range test.swaps { swap, err := ethClient.swap(ctx, simnetAcct, testSwap.SecretHash) if err != nil { t.Fatalf("unexpected error for test %v: %v", test.name, err) } - originalStates[hex.EncodeToString(testSwap.SecretHash[:])] = srveth.SwapState(swap.State) + originalStates[hex.EncodeToString(testSwap.SecretHash[:])] = dexeth.SwapState(swap.State) } txOpts := newTxOpts(ctx, &simnetAddr, test.txValue) @@ -688,9 +688,9 @@ func TestInitiate(t *testing.T) { if err != nil { t.Fatalf("unexpected error for test %v: %v", test.name, err) } - state := srveth.SwapState(swap.State) - if test.success && state != srveth.SSInitiated { - t.Fatalf("unexpected swap state for test %v: want %s got %s", test.name, srveth.SSInitiated, state) + state := dexeth.SwapState(swap.State) + if test.success && state != dexeth.SSInitiated { + t.Fatalf("unexpected swap state for test %v: want %s got %s", test.name, dexeth.SSInitiated, state) } originalState := originalStates[hex.EncodeToString(testSwap.SecretHash[:])] @@ -761,33 +761,33 @@ func TestRedeem(t *testing.T) { sleep time.Duration redeemerClient *rpcclient redeemer *accounts.Account - finalState srveth.SwapState + finalState dexeth.SwapState addAmt, badSecret bool }{{ name: "ok before locktime", sleep: time.Second * 8, redeemerClient: participantEthClient, redeemer: participantAcct, - finalState: srveth.SSRedeemed, + finalState: dexeth.SSRedeemed, addAmt: true, }, { name: "ok after locktime", sleep: time.Second * 16, redeemerClient: participantEthClient, redeemer: participantAcct, - finalState: srveth.SSRedeemed, + finalState: dexeth.SSRedeemed, addAmt: true, }, { name: "bad secret", sleep: time.Second * 8, redeemerClient: participantEthClient, redeemer: participantAcct, - finalState: srveth.SSInitiated, + finalState: dexeth.SSInitiated, badSecret: true, }, { name: "wrong redeemer", sleep: time.Second * 8, - finalState: srveth.SSInitiated, + finalState: dexeth.SSInitiated, redeemerClient: ethClient, redeemer: simnetAcct, }} @@ -810,9 +810,9 @@ func TestRedeem(t *testing.T) { if err != nil { t.Fatal("unable to get swap state") } - state := srveth.SwapState(swp.State) - if state != srveth.SSNone { - t.Fatalf("unexpected swap state for test %v: want %s got %s", test.name, srveth.SSNone, state) + state := dexeth.SwapState(swp.State) + if state != dexeth.SSNone { + t.Fatalf("unexpected swap state for test %v: want %s got %s", test.name, dexeth.SSNone, state) } // Create a secret that doesn't has to secretHash. @@ -878,7 +878,7 @@ func TestRedeem(t *testing.T) { if err != nil { t.Fatalf("unexpected error for test %v: %v", test.name, err) } - state = srveth.SwapState(swp.State) + state = dexeth.SwapState(swp.State) if state != test.finalState { t.Fatalf("unexpected swap state for test %v: want %s got %s", test.name, test.finalState, state) } @@ -893,7 +893,7 @@ func TestRefund(t *testing.T) { sleep time.Duration refunder *accounts.Account refunderClient *rpcclient - finalState srveth.SwapState + finalState dexeth.SwapState addAmt, redeem bool }{{ name: "ok", @@ -901,26 +901,26 @@ func TestRefund(t *testing.T) { refunderClient: ethClient, refunder: simnetAcct, addAmt: true, - finalState: srveth.SSRefunded, + finalState: dexeth.SSRefunded, }, { name: "before locktime", sleep: time.Second * 8, refunderClient: ethClient, refunder: simnetAcct, - finalState: srveth.SSInitiated, + finalState: dexeth.SSInitiated, }, { name: "wrong refunder", sleep: time.Second * 16, refunderClient: participantEthClient, refunder: participantAcct, - finalState: srveth.SSInitiated, + finalState: dexeth.SSInitiated, }, { name: "already redeemed", sleep: time.Second * 16, refunderClient: ethClient, refunder: simnetAcct, redeem: true, - finalState: srveth.SSRedeemed, + finalState: dexeth.SSRedeemed, }} for _, test := range tests { @@ -941,9 +941,9 @@ func TestRefund(t *testing.T) { if err != nil { t.Fatal("unable to get swap state") } - state := srveth.SwapState(swp.State) - if state != srveth.SSNone { - t.Fatalf("unexpected swap state for test %v: want %s got %s", test.name, srveth.SSNone, state) + state := dexeth.SwapState(swp.State) + if state != dexeth.SSNone { + t.Fatalf("unexpected swap state for test %v: want %s got %s", test.name, dexeth.SSNone, state) } inLocktime := time.Now().Add(locktime).Unix() @@ -1018,7 +1018,7 @@ func TestRefund(t *testing.T) { if err != nil { t.Fatalf("unexpected error for test %v: %v", test.name, err) } - state = srveth.SwapState(swp.State) + state = dexeth.SwapState(swp.State) if state != test.finalState { t.Fatalf("unexpected swap state for test %v: want %s got %s", test.name, test.finalState, state) } @@ -1152,9 +1152,9 @@ func TestReplayAttack(t *testing.T) { if err != nil { t.Fatal(err) } - state := srveth.SwapState(swap.State) - if state != srveth.SSNone { - t.Fatalf("unexpected swap state: want %s got %s", srveth.SSNone, state) + state := dexeth.SwapState(swap.State) + if state != dexeth.SSNone { + t.Fatalf("unexpected swap state: want %s got %s", dexeth.SSNone, state) } // The contract should hold four more ether because initiation of one diff --git a/server/asset/eth/common.go b/dex/networks/eth/common.go similarity index 100% rename from server/asset/eth/common.go rename to dex/networks/eth/common.go diff --git a/dex/networks/eth/common_test.go b/dex/networks/eth/common_test.go new file mode 100644 index 0000000000..5ad9bce23c --- /dev/null +++ b/dex/networks/eth/common_test.go @@ -0,0 +1,119 @@ +//go:build lgpl +// +build lgpl + +package eth + +import ( + "bytes" + "encoding/binary" + "testing" + + "decred.org/dcrdex/dex/encode" +) + +func TestCoinIDs(t *testing.T) { + // Decode and encode TxCoinID + var txID [32]byte + copy(txID[:], encode.RandomBytes(32)) + originalTxCoin := TxCoinID{ + TxID: txID, + } + encodedTxCoin := originalTxCoin.Encode() + decodedCoin, err := DecodeCoinID(encodedTxCoin) + if err != nil { + t.Fatalf("unexpected error decoding tx coin: %v", err) + } + decodedTxCoin, ok := decodedCoin.(*TxCoinID) + if !ok { + t.Fatalf("expected coin to be a TxCoin") + } + if !bytes.Equal(originalTxCoin.TxID[:], decodedTxCoin.TxID[:]) { + t.Fatalf("expected txIds to be equal before and after decoding") + } + + // Decode tx coin id with incorrect length + txCoinID := make([]byte, 33) + binary.BigEndian.PutUint16(txCoinID[:2], uint16(CIDTxID)) + copy(txCoinID[2:], encode.RandomBytes(30)) + if _, err := DecodeCoinID(txCoinID); err == nil { + t.Fatalf("expected error decoding tx coin ID with incorrect length") + } + + // Decode and encode SwapCoinID + var contractAddress [20]byte + var secretHash [32]byte + copy(contractAddress[:], encode.RandomBytes(20)) + copy(secretHash[:], encode.RandomBytes(32)) + originalSwapCoin := SwapCoinID{ + ContractAddress: contractAddress, + SecretHash: secretHash, + } + encodedSwapCoin := originalSwapCoin.Encode() + decodedCoin, err = DecodeCoinID(encodedSwapCoin) + if err != nil { + t.Fatalf("unexpected error decoding swap coin: %v", err) + } + decodedSwapCoin, ok := decodedCoin.(*SwapCoinID) + if !ok { + t.Fatalf("expected coin to be a SwapCoinID") + } + if !bytes.Equal(originalSwapCoin.ContractAddress[:], decodedSwapCoin.ContractAddress[:]) { + t.Fatalf("expected contract address to be equal before and after decoding") + } + if !bytes.Equal(originalSwapCoin.SecretHash[:], decodedSwapCoin.SecretHash[:]) { + t.Fatalf("expected secret hash to be equal before and after decoding") + } + + // Decode swap coin id with incorrect length + swapCoinID := make([]byte, 53) + binary.BigEndian.PutUint16(swapCoinID[:2], uint16(CIDSwap)) + copy(swapCoinID[2:], encode.RandomBytes(50)) + if _, err := DecodeCoinID(swapCoinID); err == nil { + t.Fatalf("expected error decoding swap coin ID with incorrect length") + } + + // Decode and encode AmountCoinID + var address [20]byte + var nonce [8]byte + copy(address[:], encode.RandomBytes(20)) + copy(nonce[:], encode.RandomBytes(8)) + originalAmountCoin := AmountCoinID{ + Address: address, + Amount: 100, + Nonce: nonce, + } + encodedAmountCoin := originalAmountCoin.Encode() + decodedCoin, err = DecodeCoinID(encodedAmountCoin) + if err != nil { + t.Fatalf("unexpected error decoding swap coin: %v", err) + } + decodedAmountCoin, ok := decodedCoin.(*AmountCoinID) + if !ok { + t.Fatalf("expected coin to be a AmounCoinID") + } + if !bytes.Equal(originalAmountCoin.Address[:], decodedAmountCoin.Address[:]) { + t.Fatalf("expected address to be equal before and after decoding") + } + if !bytes.Equal(originalAmountCoin.Nonce[:], decodedAmountCoin.Nonce[:]) { + t.Fatalf("expected nonce to be equal before and after decoding") + } + if originalAmountCoin.Amount != decodedAmountCoin.Amount { + t.Fatalf("expected amount to be equal before and after decoding") + } + + // Decode amount coin id with incorrect length + amountCoinId := make([]byte, 37) + binary.BigEndian.PutUint16(amountCoinId[:2], uint16(CIDAmount)) + copy(amountCoinId[2:], encode.RandomBytes(35)) + if _, err := DecodeCoinID(amountCoinId); err == nil { + t.Fatalf("expected error decoding amount coin ID with incorrect length") + } + + // Decode coin id with non existant flag + nonExistantCoinID := make([]byte, 37) + binary.BigEndian.PutUint16(nonExistantCoinID[:2], uint16(5)) + copy(nonExistantCoinID, encode.RandomBytes(35)) + if _, err := DecodeCoinID(nonExistantCoinID); err == nil { + t.Fatalf("expected error decoding coin id with non existant flag") + } +} diff --git a/server/asset/eth/coiner.go b/server/asset/eth/coiner.go index ae90e4dce3..9966f99185 100644 --- a/server/asset/eth/coiner.go +++ b/server/asset/eth/coiner.go @@ -57,11 +57,11 @@ func (backend *Backend) newSwapCoin(coinID []byte, sct swapCoinType) (*swapCoin, return nil, fmt.Errorf("unknown swapCoin type: %d", sct) } - cID, err := DecodeCoinID(coinID) + cID, err := dexeth.DecodeCoinID(coinID) if err != nil { return nil, err } - txCoinID, ok := cID.(*TxCoinID) + txCoinID, ok := cID.(*dexeth.TxCoinID) if !ok { return nil, errors.New("coin ID not a txid") } @@ -117,13 +117,13 @@ func (backend *Backend) newSwapCoin(coinID []byte, sct swapCoinType) (*swapCoin, // initialization transaction could take a long time to be mined. A // transaction with a very low gas price may need to be resent with a // higher price. - gasPrice, err := ToGwei(tx.GasPrice()) + gasPrice, err := dexeth.ToGwei(tx.GasPrice()) if err != nil { return nil, fmt.Errorf("unable to convert gas price: %v", err) } // Value is stored in the swap with the initialization transaction. - value, err := ToGwei(tx.Value()) + value, err := dexeth.ToGwei(tx.Value()) if err != nil { return nil, fmt.Errorf("unable to convert value: %v", err) } @@ -153,11 +153,11 @@ func (c *swapCoin) validateRedeem(contractID []byte) error { if c.sct != sctRedeem { return errors.New("can only validate redeem") } - cID, err := DecodeCoinID(contractID) + cID, err := dexeth.DecodeCoinID(contractID) if err != nil { return err } - scID, ok := cID.(*SwapCoinID) + scID, ok := cID.(*dexeth.SwapCoinID) if !ok { return errors.New("contract ID not a swap") } @@ -195,8 +195,8 @@ func (c *swapCoin) Confirmations(_ context.Context) (int64, error) { // is the expected address and value was also as expected. Also // not validating the locktime, as the swap is redeemed and // locktime no longer relevant. - ss := SwapState(swap.State) - if ss == SSRedeemed { + ss := dexeth.SwapState(swap.State) + if ss == dexeth.SSRedeemed { // While not completely accurate, we know that if the // swap is redeemed the redemption has at least one // confirmation. @@ -204,7 +204,7 @@ func (c *swapCoin) Confirmations(_ context.Context) (int64, error) { } // If swap is in the Initiated state, the transaction may be // unmined. - if ss == SSInitiated { + if ss == dexeth.SSInitiated { // Assume the tx still has a chance of being mined. return 0, nil } @@ -219,7 +219,7 @@ func (c *swapCoin) Confirmations(_ context.Context) (int64, error) { // It is important to only trust confirmations according to the // swap contract. Until there are confirmations we cannot be sure // that initiation happened successfuly. - if SwapState(swap.State) == SSNone { + if dexeth.SwapState(swap.State) == dexeth.SSNone { // Assume the tx still has a chance of being mined. return 0, nil } @@ -230,7 +230,7 @@ func (c *swapCoin) Confirmations(_ context.Context) (int64, error) { // confirmations, and we are sure the secret hash belongs to // this swap. Assert that the value, reciever, and locktime are // as expected. - value, err := ToGwei(big.NewInt(0).Set(swap.Value)) + value, err := dexeth.ToGwei(big.NewInt(0).Set(swap.Value)) if err != nil { return -1, fmt.Errorf("unable to convert value: %v", err) } @@ -263,7 +263,7 @@ func (c *swapCoin) Confirmations(_ context.Context) (int64, error) { // ID is the swap's coin ID. func (c *swapCoin) ID() []byte { - sc := &SwapCoinID{ + sc := &dexeth.SwapCoinID{ ContractAddress: c.contractAddr, SecretHash: c.secretHash, } @@ -277,7 +277,7 @@ func (c *swapCoin) TxID() string { // String is a human readable representation of the swap coin. func (c *swapCoin) String() string { - sc := &SwapCoinID{ + sc := &dexeth.SwapCoinID{ ContractAddress: c.contractAddr, SecretHash: c.secretHash, } diff --git a/server/asset/eth/coiner_test.go b/server/asset/eth/coiner_test.go index c56ccdc1f6..9fef672a34 100644 --- a/server/asset/eth/coiner_test.go +++ b/server/asset/eth/coiner_test.go @@ -12,6 +12,7 @@ import ( "testing" "decred.org/dcrdex/dex/encode" + dexeth "decred.org/dcrdex/dex/networks/eth" "decred.org/dcrdex/dex/networks/eth/swap" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -20,7 +21,7 @@ import ( func overMaxWei() *big.Int { maxInt := ^uint64(0) maxWei := new(big.Int).SetUint64(maxInt) - gweiFactorBig := big.NewInt(GweiFactor) + gweiFactorBig := big.NewInt(dexeth.GweiFactor) maxWei.Mul(maxWei, gweiFactorBig) overMaxWei := new(big.Int).Set(maxWei) return overMaxWei.Add(overMaxWei, gweiFactorBig) @@ -38,23 +39,23 @@ func TestNewSwapCoin(t *testing.T) { copy(txHash[:], encode.RandomBytes(32)) copy(secret[:], secretSlice) copy(secretHash[:], secretHashSlice) - txCoinIDBytes := (&TxCoinID{ + txCoinIDBytes := (&dexeth.TxCoinID{ TxID: txHash, Index: 1, }).Encode() - txCoinIDIndex2Bytes := (&TxCoinID{ + txCoinIDIndex2Bytes := (&dexeth.TxCoinID{ TxID: txHash, Index: 2, }).Encode() - sc := SwapCoinID{} + sc := dexeth.SwapCoinID{} swapCoinIDBytes := sc.Encode() gasPrice := big.NewInt(3e10) value := big.NewInt(5e18) - wantGas, err := ToGwei(big.NewInt(3e10)) + wantGas, err := dexeth.ToGwei(big.NewInt(3e10)) if err != nil { t.Fatal(err) } - wantVal, err := ToGwei(big.NewInt(5e18)) + wantVal, err := dexeth.ToGwei(big.NewInt(5e18)) if err != nil { t.Fatal(err) } @@ -201,7 +202,7 @@ func TestConfirmations(t *testing.T) { secretHash, txHash := [32]byte{}, [32]byte{} copy(txHash[:], encode.RandomBytes(32)) copy(secretHash[:], secretHashSlice) - tc := TxCoinID{ + tc := dexeth.TxCoinID{ TxID: txHash, } txCoinIDBytes := tc.Encode() @@ -223,24 +224,24 @@ func TestConfirmations(t *testing.T) { }{{ name: "ok has confs value not verified", bn: 100, - swap: tSwap(97, locktime, value, SSInitiated, &initParticipantAddr), + swap: tSwap(97, locktime, value, dexeth.SSInitiated, &initParticipantAddr), value: value, ct: sctInit, wantConfs: 3, }, { name: "ok no confs", - swap: tSwap(0, bigO, bigO, SSNone, nullAddr), + swap: tSwap(0, bigO, bigO, dexeth.SSNone, nullAddr), value: value, ct: sctInit, }, { name: "ok redeem swap status redeemed", - swap: tSwap(97, locktime, value, SSRedeemed, &initParticipantAddr), + swap: tSwap(97, locktime, value, dexeth.SSRedeemed, &initParticipantAddr), value: bigO, ct: sctRedeem, wantConfs: 1, }, { name: "ok redeem swap status initiated", - swap: tSwap(97, locktime, value, SSInitiated, &initParticipantAddr), + swap: tSwap(97, locktime, value, dexeth.SSInitiated, &initParticipantAddr), value: bigO, ct: sctRedeem, }, { @@ -250,7 +251,7 @@ func TestConfirmations(t *testing.T) { wantErr: true, }, { name: "redeem bad swap state None", - swap: tSwap(0, bigO, bigO, SSNone, nullAddr), + swap: tSwap(0, bigO, bigO, dexeth.SSNone, nullAddr), value: bigO, ct: sctRedeem, wantErr: true, @@ -261,38 +262,38 @@ func TestConfirmations(t *testing.T) { ct: sctInit, wantErr: true, }, { - name: "swap value causes ToGwei error", - swap: tSwap(99, locktime, overMaxWei(), SSInitiated, &initParticipantAddr), + name: "swap value causes dexeth.ToGwei error", + swap: tSwap(99, locktime, overMaxWei(), dexeth.SSInitiated, &initParticipantAddr), value: value, ct: sctInit, wantErr: true, }, { name: "value differs from initial transaction", - swap: tSwap(99, locktime, oneGweiMore, SSInitiated, &initParticipantAddr), + swap: tSwap(99, locktime, oneGweiMore, dexeth.SSInitiated, &initParticipantAddr), value: value, ct: sctInit, wantErr: true, }, { name: "participant differs from initial transaction", - swap: tSwap(99, locktime, value, SSInitiated, nullAddr), + swap: tSwap(99, locktime, value, dexeth.SSInitiated, nullAddr), value: value, ct: sctInit, wantErr: true, }, { name: "locktime not an int64", - swap: tSwap(99, new(big.Int).SetUint64(^uint64(0)), value, SSInitiated, &initParticipantAddr), + swap: tSwap(99, new(big.Int).SetUint64(^uint64(0)), value, dexeth.SSInitiated, &initParticipantAddr), value: value, ct: sctInit, wantErr: true, }, { name: "locktime differs from initial transaction", - swap: tSwap(99, bigO, value, SSInitiated, &initParticipantAddr), + swap: tSwap(99, bigO, value, dexeth.SSInitiated, &initParticipantAddr), value: value, ct: sctInit, wantErr: true, }, { name: "block number error", - swap: tSwap(97, locktime, value, SSInitiated, &initParticipantAddr), + swap: tSwap(97, locktime, value, dexeth.SSInitiated, &initParticipantAddr), value: value, ct: sctInit, bnErr: errors.New(""), @@ -348,7 +349,7 @@ func TestValidateRedeem(t *testing.T) { copy(contractAddr[:], encode.RandomBytes(20)) secretHash, nullHash := [32]byte{}, [32]byte{} copy(secretHash[:], encode.RandomBytes(20)) - scID := SwapCoinID{ + scID := dexeth.SwapCoinID{ ContractAddress: *contractAddr, SecretHash: secretHash, } @@ -383,13 +384,13 @@ func TestValidateRedeem(t *testing.T) { }, { name: "contract ID is not a swap", sc: scRedeem, - contractID: new(TxCoinID).Encode(), + contractID: new(dexeth.TxCoinID).Encode(), wantErr: true, }, { name: "mismatched contract ID contract address", sc: scRedeem, contractID: func() []byte { - badAddr := SwapCoinID{ + badAddr := dexeth.SwapCoinID{ ContractAddress: *nullAddr, SecretHash: secretHash, } @@ -400,7 +401,7 @@ func TestValidateRedeem(t *testing.T) { name: "mismatched contract ID secret hash", sc: scRedeem, contractID: func() []byte { - badHash := SwapCoinID{ + badHash := dexeth.SwapCoinID{ ContractAddress: *contractAddr, SecretHash: nullHash, } diff --git a/server/asset/eth/eth.go b/server/asset/eth/eth.go index b41924049e..6a2d1837cd 100644 --- a/server/asset/eth/eth.go +++ b/server/asset/eth/eth.go @@ -66,7 +66,7 @@ func (d *Driver) Setup(configPath string, logger dex.Logger, network dex.Network // DecodeCoinID creates a human-readable representation of a coin ID for Ethereum. func (d *Driver) DecodeCoinID(coinID []byte) (string, error) { - coinId, err := DecodeCoinID(coinID) + coinId, err := dexeth.DecodeCoinID(coinID) if err != nil { return "", err } @@ -208,11 +208,11 @@ func (eth *Backend) Connect(ctx context.Context) (*sync.WaitGroup, error) { // TxData fetches the raw transaction data. func (eth *Backend) TxData(coinID []byte) ([]byte, error) { - cnr, err := DecodeCoinID(coinID) + cnr, err := dexeth.DecodeCoinID(coinID) if err != nil { return nil, fmt.Errorf("coin ID decoding error: %v", err) } - c, is := cnr.(*TxCoinID) + c, is := cnr.(*dexeth.TxCoinID) if !is { return nil, fmt.Errorf("wrong type of coin ID, %v", cnr) } @@ -231,7 +231,7 @@ func (eth *Backend) TxData(coinID []byte) ([]byte, error) { // cannot be ascertained from it. Multiplying the required gas by the gas price // will give us the actual fee needed, so returning gas here. func (eth *Backend) InitTxSize() uint32 { - return InitGas + return dexeth.InitGas } // InitTxSizeBase is used in fee.go in a fee calculation. Currently we are @@ -248,7 +248,7 @@ func (eth *Backend) FeeRate(ctx context.Context) (uint64, error) { if err != nil { return 0, err } - return ToGwei(bigGP) + return dexeth.ToGwei(bigGP) } // BlockChannel creates and returns a new channel on which to receive block @@ -292,7 +292,7 @@ func (eth *Backend) ValidateSecret(secret, secretHash []byte) bool { func (eth *Backend) Synced() (bool, error) { // node.SyncProgress will return nil both before syncing has begun and // after it has finished. In order to discern when syncing has begun, - // check that the best header came in under MaxBlockInterval. + // check that the best header came in under dexeth.MaxBlockInterval. sp, err := eth.node.syncProgress(eth.rpcCtx) if err != nil { return false, err @@ -307,7 +307,7 @@ func (eth *Backend) Synced() (bool, error) { // Time in the header is in seconds. nowInSecs := time.Now().Unix() / 1000 timeDiff := nowInSecs - int64(bh.Time) - return timeDiff < MaxBlockInterval, nil + return timeDiff < dexeth.MaxBlockInterval, nil } // Redemption returns a coin that represents a contract redemption. redeemCoinID @@ -339,7 +339,7 @@ func (eth *Backend) FundingCoin(ctx context.Context, coinID []byte, redeemScript // ValidateCoinID attempts to decode the coinID. func (eth *Backend) ValidateCoinID(coinID []byte) (string, error) { - coinId, err := DecodeCoinID(coinID) + coinId, err := dexeth.DecodeCoinID(coinID) if err != nil { return "", err } @@ -348,8 +348,9 @@ func (eth *Backend) ValidateCoinID(coinID []byte) (string, error) { // ValidateContract ensures that the secret hash is the correct length. func (eth *Backend) ValidateContract(secretHash []byte) error { - if len(secretHash) != SecretHashSize { - return fmt.Errorf("secret hash is wrong size: want %d but got %d", SecretHashSize, len(secretHash)) + if len(secretHash) != dexeth.SecretHashSize { + return fmt.Errorf("secret hash is wrong size: want %d but got %d", + dexeth.SecretHashSize, len(secretHash)) } return nil } diff --git a/server/asset/eth/eth_test.go b/server/asset/eth/eth_test.go index 28539d1935..1a2f7a6c44 100644 --- a/server/asset/eth/eth_test.go +++ b/server/asset/eth/eth_test.go @@ -9,7 +9,6 @@ import ( "bytes" "context" "crypto/sha256" - "encoding/binary" "encoding/hex" "errors" "math/big" @@ -19,6 +18,7 @@ import ( "decred.org/dcrdex/dex" "decred.org/dcrdex/dex/calc" "decred.org/dcrdex/dex/encode" + dexeth "decred.org/dcrdex/dex/networks/eth" "decred.org/dcrdex/dex/networks/eth/swap" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -121,7 +121,7 @@ func (n *testNode) transaction(ctx context.Context, hash common.Hash) (tx *types return n.tx, n.txIsMempool, n.txErr } -func tSwap(bn int64, locktime, value *big.Int, state SwapState, participantAddr *common.Address) *swap.ETHSwapSwap { +func tSwap(bn int64, locktime, value *big.Int, state dexeth.SwapState, participantAddr *common.Address) *swap.ETHSwapSwap { return &swap.ETHSwapSwap{ InitBlockNumber: big.NewInt(bn), RefundBlockTimestamp: locktime, @@ -171,113 +171,6 @@ func TestLoad(t *testing.T) { } } -func TestCoinIDs(t *testing.T) { - // Decode and encode TxCoinID - var txID [32]byte - copy(txID[:], encode.RandomBytes(32)) - originalTxCoin := TxCoinID{ - TxID: txID, - } - encodedTxCoin := originalTxCoin.Encode() - decodedCoin, err := DecodeCoinID(encodedTxCoin) - if err != nil { - t.Fatalf("unexpected error decoding tx coin: %v", err) - } - decodedTxCoin, ok := decodedCoin.(*TxCoinID) - if !ok { - t.Fatalf("expected coin to be a TxCoin") - } - if !bytes.Equal(originalTxCoin.TxID[:], decodedTxCoin.TxID[:]) { - t.Fatalf("expected txIds to be equal before and after decoding") - } - - // Decode tx coin id with incorrect length - txCoinID := make([]byte, 33) - binary.BigEndian.PutUint16(txCoinID[:2], uint16(CIDTxID)) - copy(txCoinID[2:], encode.RandomBytes(30)) - if _, err := DecodeCoinID(txCoinID); err == nil { - t.Fatalf("expected error decoding tx coin ID with incorrect length") - } - - // Decode and encode SwapCoinID - var contractAddress [20]byte - var secretHash [32]byte - copy(contractAddress[:], encode.RandomBytes(20)) - copy(secretHash[:], encode.RandomBytes(32)) - originalSwapCoin := SwapCoinID{ - ContractAddress: contractAddress, - SecretHash: secretHash, - } - encodedSwapCoin := originalSwapCoin.Encode() - decodedCoin, err = DecodeCoinID(encodedSwapCoin) - if err != nil { - t.Fatalf("unexpected error decoding swap coin: %v", err) - } - decodedSwapCoin, ok := decodedCoin.(*SwapCoinID) - if !ok { - t.Fatalf("expected coin to be a SwapCoinID") - } - if !bytes.Equal(originalSwapCoin.ContractAddress[:], decodedSwapCoin.ContractAddress[:]) { - t.Fatalf("expected contract address to be equal before and after decoding") - } - if !bytes.Equal(originalSwapCoin.SecretHash[:], decodedSwapCoin.SecretHash[:]) { - t.Fatalf("expected secret hash to be equal before and after decoding") - } - - // Decode swap coin id with incorrect length - swapCoinID := make([]byte, 53) - binary.BigEndian.PutUint16(swapCoinID[:2], uint16(CIDSwap)) - copy(swapCoinID[2:], encode.RandomBytes(50)) - if _, err := DecodeCoinID(swapCoinID); err == nil { - t.Fatalf("expected error decoding swap coin ID with incorrect length") - } - - // Decode and encode AmountCoinID - var address [20]byte - var nonce [8]byte - copy(address[:], encode.RandomBytes(20)) - copy(nonce[:], encode.RandomBytes(8)) - originalAmountCoin := AmountCoinID{ - Address: address, - Amount: 100, - Nonce: nonce, - } - encodedAmountCoin := originalAmountCoin.Encode() - decodedCoin, err = DecodeCoinID(encodedAmountCoin) - if err != nil { - t.Fatalf("unexpected error decoding swap coin: %v", err) - } - decodedAmountCoin, ok := decodedCoin.(*AmountCoinID) - if !ok { - t.Fatalf("expected coin to be a AmounCoinID") - } - if !bytes.Equal(originalAmountCoin.Address[:], decodedAmountCoin.Address[:]) { - t.Fatalf("expected address to be equal before and after decoding") - } - if !bytes.Equal(originalAmountCoin.Nonce[:], decodedAmountCoin.Nonce[:]) { - t.Fatalf("expected nonce to be equal before and after decoding") - } - if originalAmountCoin.Amount != decodedAmountCoin.Amount { - t.Fatalf("expected amount to be equal before and after decoding") - } - - // Decode amount coin id with incorrect length - amountCoinId := make([]byte, 37) - binary.BigEndian.PutUint16(amountCoinId[:2], uint16(CIDAmount)) - copy(amountCoinId[2:], encode.RandomBytes(35)) - if _, err := DecodeCoinID(amountCoinId); err == nil { - t.Fatalf("expected error decoding amount coin ID with incorrect length") - } - - // Decode coin id with non existant flag - nonExistantCoinID := make([]byte, 37) - binary.BigEndian.PutUint16(nonExistantCoinID[:2], uint16(5)) - copy(nonExistantCoinID, encode.RandomBytes(35)) - if _, err := DecodeCoinID(nonExistantCoinID); err == nil { - t.Fatalf("expected error decoding coin id with non existant flag") - } -} - func TestRun(t *testing.T) { // TODO: Test all paths. ctx, cancel := context.WithCancel(context.Background()) @@ -309,7 +202,7 @@ func TestRun(t *testing.T) { func TestFeeRate(t *testing.T) { maxInt := ^uint64(0) maxWei := new(big.Int).SetUint64(maxInt) - gweiFactorBig := big.NewInt(GweiFactor) + gweiFactorBig := big.NewInt(dexeth.GweiFactor) maxWei.Mul(maxWei, gweiFactorBig) overMaxWei := new(big.Int).Set(maxWei) overMaxWei.Add(overMaxWei, gweiFactorBig) @@ -325,11 +218,11 @@ func TestFeeRate(t *testing.T) { wantFee: 0, }, { name: "ok rounded down", - gas: big.NewInt(GweiFactor - 1), + gas: big.NewInt(dexeth.GweiFactor - 1), wantFee: 0, }, { name: "ok one", - gas: big.NewInt(GweiFactor), + gas: big.NewInt(dexeth.GweiFactor), wantFee: 1, }, { name: "ok max int", @@ -389,7 +282,7 @@ func TestSynced(t *testing.T) { syncProg: new(ethereum.SyncProgress), }, { name: "ok header too old", - subSecs: MaxBlockInterval, + subSecs: dexeth.MaxBlockInterval, }, { name: "best header error", bestHdrErr: errors.New(""), @@ -473,11 +366,11 @@ func TestContract(t *testing.T) { copy(txHash[:], encode.RandomBytes(32)) gasPrice := big.NewInt(3e10) value := big.NewInt(5e18) - tc := TxCoinID{ + tc := dexeth.TxCoinID{ TxID: txHash, } txCoinIDBytes := tc.Encode() - sc := SwapCoinID{} + sc := dexeth.SwapCoinID{} swapCoinIDBytes := sc.Encode() locktime := big.NewInt(initLocktime) tests := []struct { @@ -490,12 +383,12 @@ func TestContract(t *testing.T) { }{{ name: "ok", tx: tTx(gasPrice, value, contractAddr, initCalldata), - swap: tSwap(97, locktime, value, SSInitiated, &initParticipantAddr), + swap: tSwap(97, locktime, value, dexeth.SSInitiated, &initParticipantAddr), coinID: txCoinIDBytes, }, { name: "new coiner error, wrong tx type", tx: tTx(gasPrice, value, contractAddr, initCalldata), - swap: tSwap(97, locktime, value, SSInitiated, &initParticipantAddr), + swap: tSwap(97, locktime, value, dexeth.SSInitiated, &initParticipantAddr), coinID: swapCoinIDBytes, wantErr: true, }, { @@ -570,7 +463,7 @@ func TestRedemption(t *testing.T) { copy(txHash[:], encode.RandomBytes(32)) gasPrice := big.NewInt(3e10) bigO := big.NewInt(0) - ccID := &SwapCoinID{ + ccID := &dexeth.SwapCoinID{ SecretHash: secretHash, ContractAddress: *contractAddr, } @@ -586,27 +479,27 @@ func TestRedemption(t *testing.T) { name: "ok", tx: tTx(gasPrice, bigO, contractAddr, redeemCalldata), contractID: ccID.Encode(), - coinID: new(TxCoinID).Encode(), - swp: tSwap(0, bigO, bigO, SSRedeemed, receiverAddr), + coinID: new(dexeth.TxCoinID).Encode(), + swp: tSwap(0, bigO, bigO, dexeth.SSRedeemed, receiverAddr), }, { name: "new coiner error, wrong tx type", tx: tTx(gasPrice, bigO, contractAddr, redeemCalldata), contractID: ccID.Encode(), - coinID: new(SwapCoinID).Encode(), + coinID: new(dexeth.SwapCoinID).Encode(), wantErr: true, }, { name: "confirmations error, swap wrong state", tx: tTx(gasPrice, bigO, contractAddr, redeemCalldata), contractID: ccID.Encode(), - swp: tSwap(0, bigO, bigO, SSRefunded, receiverAddr), - coinID: new(TxCoinID).Encode(), + swp: tSwap(0, bigO, bigO, dexeth.SSRefunded, receiverAddr), + coinID: new(dexeth.TxCoinID).Encode(), wantErr: true, }, { name: "validate redeem error", tx: tTx(gasPrice, bigO, contractAddr, redeemCalldata), - contractID: new(SwapCoinID).Encode(), - coinID: new(TxCoinID).Encode(), - swp: tSwap(0, bigO, bigO, SSRedeemed, receiverAddr), + contractID: new(dexeth.SwapCoinID).Encode(), + coinID: new(dexeth.TxCoinID).Encode(), + swp: tSwap(0, bigO, bigO, dexeth.SSRedeemed, receiverAddr), wantErr: true, }} for _, test := range tests { @@ -645,7 +538,7 @@ func TestTxData(t *testing.T) { addr := randomAddress() data := encode.RandomBytes(5) tx := tTx(gasPrice, value, addr, data) - goodCoinID := (&TxCoinID{TxID: tx.Hash()}).Encode() + goodCoinID := (&dexeth.TxCoinID{TxID: tx.Hash()}).Encode() node.tx = tx // initial success @@ -666,7 +559,7 @@ func TestTxData(t *testing.T) { } // Wrong type of coin ID - coinID = (&SwapCoinID{}).Encode() + coinID = (&dexeth.SwapCoinID{}).Encode() _, err = eth.TxData(coinID) if err == nil { t.Fatalf("no error for wrong coin type")