Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v1.0.3 #3179

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7e93e8a
mm/core: Fix multi trade funding error
martonp Nov 25, 2024
a1bbd10
binance: parse error responses (#3090)
buck54321 Nov 29, 2024
f0a3055
app: Avoid error on RunStatsNote (#3104)
martonp Dec 2, 2024
38a44f8
core: Populate the core.Exchange map fields even when not connected (…
martonp Dec 2, 2024
051e5ad
mm/binance: Use filters and withdraw multiple (#3093)
martonp Dec 2, 2024
b86ce71
dcr: Make tip an atomic. (#3087)
JoeGruffins Jan 14, 2025
dcd6120
client/btc: Store correct tx history refund hash. (#3142)
JoeGruffins Jan 14, 2025
bc6773a
Translation Update de (#3124)
karamble Jan 28, 2025
892d475
client/webserver: Update static chinese translations (#3071)
dev-warrior777 Jan 29, 2025
30ea8d7
libxc/binance: Better error message (#3106)
martonp Feb 3, 2025
079bff2
libxc/binance: Fix polygon symbol conversion (#3118)
martonp Feb 4, 2025
1304d33
mm: Fix balance handling for shared txs across matches (#3138)
martonp Feb 4, 2025
78f3189
cli: Update github action deps. (#3174)
JoeGruffins Jan 31, 2025
12eb6bf
mm: Account for mult split buffer when making MultiTrade (#3156)
martonp Feb 7, 2025
6f58a79
client: eth, fix user action resolution handling (#3178)
norwnd Feb 7, 2025
330a32f
libxc/binance: Handle invalid listen key error (#3139)
martonp Feb 10, 2025
377a4b3
wsconn: Ignore some connect errors. (#3182)
JoeGruffins Feb 12, 2025
5d29f50
Shorten systray tooltip (#3183)
peterzen Feb 13, 2025
e36e3ab
polygon: fix wallet connected/disconnected notifications show up cons…
norwnd Feb 13, 2025
6c06007
update feature-policy header (#3193)
buck54321 Feb 21, 2025
1d04726
deps: Update dcrwallet to 4.3.0. (#3197)
martonp Feb 24, 2025
d3cee0b
client: Add penalty comps message. (#3188)
JoeGruffins Feb 20, 2025
8e608ff
bump version numbers to 1.0.3
martonp Feb 24, 2025
958abfb
commit web assets
martonp Feb 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ jobs:
matrix:
go: ['1.22', '1.23']
steps:
- uses: awalsh128/cache-apt-pkgs-action@a6c3917cc929dd0345bfb2d3feaf9101823370ad #v1.4.2
- uses: awalsh128/cache-apt-pkgs-action@5902b33ae29014e6ca012c5d8025d4346556bd40 #v1.4.3
with:
packages: git-restore-mtime libgtk-3-dev libwebkit2gtk-4.0-dev
version: 1.0

- name: Set up Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 #v5.3.0
with:
go-version: ${{ matrix.go }}

- name: Check out source
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
with:
fetch-depth: 0
# Restore original file modification times for test cache reasons
Expand All @@ -30,7 +30,7 @@ jobs:
- name: Install Linters
run: "curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.60.2"
- name: Use test and module cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
with:
path: |
~/.cache/go-build
Expand All @@ -52,9 +52,9 @@ jobs:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
- name: Use nodejs ${{ matrix.node-version }}
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b #v4.0.3
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a #v4.2.0
with:
node-version: ${{ matrix.node-version }}
- name: npm clean-install
Expand All @@ -71,11 +71,10 @@ jobs:
name: Lint Markdown
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
- uses: DavidAnson/markdownlint-cli2-action@b4c9feab76d8025d1e83c653fa3990936df0e6c8 #v16.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
- uses: DavidAnson/markdownlint-cli2-action@05f32210e84442804257b2a6f20b273450ec8265 #v19.1.0
continue-on-error: true
with:
globs: |
*.md
docs/**/*.md

8 changes: 4 additions & 4 deletions .github/workflows/release-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ jobs:

steps:
- name: Login to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Checkout project
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c #v3.3.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2

- name: Set up QEMU
uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 #v2.1.0
uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a #v3.3.0

- name: Setup Docker buildx action
uses: docker/setup-buildx-action@f03ac48505955848960e80bbb68046aa35c7b9e7 #v2.4.1
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 #v3.8.0

- name: Build and Push Docker Image
run: |
Expand Down
2 changes: 1 addition & 1 deletion client/app/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var (
// and build metadata portions MUST only contain characters from
// semanticAlphabet.
// NOTE: The Version string is overridden on init.
Version = "1.0.2+release.local"
Version = "1.0.3+release.local"
)

func init() {
Expand Down
4 changes: 2 additions & 2 deletions client/asset/btc/btc.go
Original file line number Diff line number Diff line change
Expand Up @@ -4281,10 +4281,10 @@ func (btc *baseWallet) Refund(coinID, contract dex.Bytes, feeRate uint64) (dex.B
}
btc.addTxToHistory(&asset.WalletTransaction{
Type: asset.Refund,
ID: txHash.String(),
ID: refundHash.String(),
Amount: uint64(utxo.Value),
Fees: fee,
}, txHash, true)
}, refundHash, true)

return ToCoinID(refundHash, 0), nil
}
Expand Down
48 changes: 15 additions & 33 deletions client/asset/dcr/dcr.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,8 +643,8 @@ type ExchangeWallet struct {
oracleFees map[uint64]feeStamped // conf target => fee rate
oracleFailing bool

tipMtx sync.RWMutex
currentTip *block
handleTipMtx sync.Mutex
currentTip atomic.Value // *block

// Coins returned by Fund are cached for quick reference.
fundingMtx sync.RWMutex
Expand Down Expand Up @@ -1064,13 +1064,11 @@ func (dcr *ExchangeWallet) Connect(ctx context.Context) (*sync.WaitGroup, error)
}

// Initialize the best block.
dcr.tipMtx.Lock()
dcr.currentTip, err = dcr.getBestBlock(ctx)
tip := dcr.currentTip
dcr.tipMtx.Unlock()
tip, err := dcr.getBestBlock(ctx)
if err != nil {
return nil, fmt.Errorf("error initializing best block for DCR: %w", err)
}
dcr.currentTip.Store(tip)
dcr.startingBlocks.Store(uint64(tip.height))

dbCM, err := dcr.startTxHistoryDB(ctx)
Expand Down Expand Up @@ -3592,9 +3590,7 @@ func (dcr *ExchangeWallet) lookupTxOutput(ctx context.Context, txHash *chainhash
// LockTimeExpired returns true if the specified locktime has expired, making it
// possible to redeem the locked coins.
func (dcr *ExchangeWallet) LockTimeExpired(ctx context.Context, lockTime time.Time) (bool, error) {
dcr.tipMtx.RLock()
blockHash := dcr.currentTip.hash
dcr.tipMtx.RUnlock()
blockHash := dcr.cachedBestBlock().hash
hdr, err := dcr.wallet.GetBlockHeader(ctx, blockHash)
if err != nil {
return false, fmt.Errorf("unable to retrieve the block header: %w", err)
Expand Down Expand Up @@ -3657,9 +3653,7 @@ func (dcr *ExchangeWallet) FindRedemption(ctx context.Context, coinID, _ dex.Byt
if contractBlock == nil {
dcr.findRedemptionsInMempool([]outPoint{contractOutpoint})
} else {
dcr.tipMtx.RLock()
bestBlock := dcr.currentTip
dcr.tipMtx.RUnlock()
bestBlock := dcr.cachedBestBlock()
dcr.findRedemptionsInBlockRange(contractBlock.height, bestBlock.height, []outPoint{contractOutpoint})
}

Expand Down Expand Up @@ -4833,11 +4827,8 @@ func (dcr *ExchangeWallet) SyncStatus() (ss *asset.SyncStatus, err error) {
}

if wasSynced := dcr.previouslySynced.Swap(synced); synced && !wasSynced {
dcr.tipMtx.RLock()
tip := dcr.currentTip
dcr.tipMtx.RUnlock()

dcr.syncTxHistory(dcr.ctx, uint64(tip.height))
tip := dcr.cachedBestBlock()
go dcr.syncTxHistory(dcr.ctx, uint64(tip.height))
}
}()

Expand Down Expand Up @@ -6630,11 +6621,7 @@ func (dcr *ExchangeWallet) monitorBlocks(ctx context.Context) {
return
}

dcr.tipMtx.RLock()
sameTip := dcr.currentTip.hash.IsEqual(newTip.hash)
dcr.tipMtx.RUnlock()

if sameTip {
if dcr.cachedBestBlock().hash.IsEqual(newTip.hash) {
return
}

Expand Down Expand Up @@ -6682,9 +6669,7 @@ func (dcr *ExchangeWallet) monitorBlocks(ctx context.Context) {
// Mempool tx seen.
dcr.emitBalance()

dcr.tipMtx.RLock()
tip := dcr.currentTip
dcr.tipMtx.RUnlock()
tip := dcr.cachedBestBlock()
dcr.syncTxHistory(ctx, uint64(tip.height))
continue
}
Expand Down Expand Up @@ -6712,11 +6697,10 @@ func (dcr *ExchangeWallet) handleTipChange(ctx context.Context, newTipHash *chai
}

// Lock to avoid concurrent handleTipChange execution for simplicity.
dcr.tipMtx.Lock()
defer dcr.tipMtx.Unlock()
dcr.handleTipMtx.Lock()
defer dcr.handleTipMtx.Unlock()

prevTip := dcr.currentTip
dcr.currentTip = &block{newTipHeight, newTipHash}
prevTip := dcr.currentTip.Swap(&block{newTipHeight, newTipHash}).(*block)

dcr.log.Tracef("tip change: %d (%s) => %d (%s)", prevTip.height, prevTip.hash, newTipHeight, newTipHash)

Expand Down Expand Up @@ -6849,10 +6833,8 @@ func (dcr *ExchangeWallet) blockHeader(ctx context.Context, blockHash *chainhash
return blockHeader, true, validMainchain, nil
}

func (dcr *ExchangeWallet) cachedBestBlock() block {
dcr.tipMtx.RLock()
defer dcr.tipMtx.RUnlock()
return *dcr.currentTip
func (dcr *ExchangeWallet) cachedBestBlock() *block {
return dcr.currentTip.Load().(*block)
}

// wireBytes dumps the serialized transaction bytes.
Expand Down
12 changes: 5 additions & 7 deletions client/asset/dcr/dcr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,8 @@ func tNewWalletMonitorBlocks(monitorBlocks bool) (*ExchangeWallet, *tRPCClient,
wallet.ctx = walletCtx

// Initialize the best block.
wallet.tipMtx.Lock()
wallet.currentTip, _ = wallet.getBestBlock(walletCtx)
wallet.tipMtx.Unlock()
tip, _ := wallet.getBestBlock(walletCtx)
wallet.currentTip.Store(tip)

if monitorBlocks {
go wallet.monitorBlocks(walletCtx)
Expand Down Expand Up @@ -4232,9 +4231,8 @@ func TestConfirmRedemption(t *testing.T) {
spenderTx := makeRawTx(inputs, nil)
node.blockchain.addRawTx(2, spenderTx)

wallet.tipMtx.Lock()
wallet.currentTip, _ = wallet.getBestBlock(wallet.ctx)
wallet.tipMtx.Unlock()
tip, _ := wallet.getBestBlock(wallet.ctx)
wallet.currentTip.Store(tip)

txFn := func(doErr []bool) func() (*walletjson.GetTransactionResult, error) {
var i int
Expand Down Expand Up @@ -5007,7 +5005,7 @@ func TestRescanSync(t *testing.T) {
defer shutdown()

const tip = 1000
wallet.currentTip = &block{height: tip}
wallet.currentTip.Store(&block{height: tip})

node.rawRes[methodSyncStatus], node.rawErr[methodSyncStatus] = json.Marshal(&walletjson.SyncStatusResult{
Synced: true,
Expand Down
2 changes: 1 addition & 1 deletion client/asset/dcr/externaltx.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (dcr *ExchangeWallet) lookupTxOutWithBlockFilters(ctx context.Context, op o
tip, err := dcr.getBestBlock(ctx)
if err != nil {
dcr.log.Errorf("getbestblock error %v", err)
*tip = dcr.cachedBestBlock()
tip = dcr.cachedBestBlock()
}
var confs uint32
if tip.height >= outputBlock.height { // slight possibility that the cached tip height is behind the output's block height
Expand Down
4 changes: 1 addition & 3 deletions client/asset/dcr/native_wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,7 @@ func (w *NativeWallet) transferAccount(ctx context.Context, toAcct string, fromA
// birthdayBlockHeight performs a binary search for the last block with a
// timestamp lower than the provided birthday.
func (w *NativeWallet) birthdayBlockHeight(ctx context.Context, bday uint64) int32 {
w.tipMtx.RLock()
tipHeight := w.currentTip.height
w.tipMtx.RUnlock()
tipHeight := w.cachedBestBlock().height
var err error
firstBlockAfterBday := sort.Search(int(tipHeight), func(blockHeightI int) bool {
if err != nil { // if we see any errors, just give up.
Expand Down
12 changes: 6 additions & 6 deletions client/asset/dcr/spv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -956,12 +956,12 @@ func TestBirthdayBlockHeight(t *testing.T) {
dcrw.makeBlocks(0, tipHeight)
w := &NativeWallet{
ExchangeWallet: &ExchangeWallet{
wallet: spvw,
log: dex.StdOutLogger("T", dex.LevelInfo),
currentTip: &block{height: tipHeight},
wallet: spvw,
log: dex.StdOutLogger("T", dex.LevelInfo),
},
spvw: spvw,
}
w.currentTip.Store(&block{height: tipHeight})

if h := w.birthdayBlockHeight(tCtx, 5); h != 4 {
t.Fatalf("expected block 4, got %d", h)
Expand All @@ -982,12 +982,12 @@ func TestRescan(t *testing.T) {
spvw, dcrw := tNewSpvWallet()
w := &NativeWallet{
ExchangeWallet: &ExchangeWallet{
wallet: spvw,
log: dex.StdOutLogger("T", dex.LevelInfo),
currentTip: &block{height: tipHeight},
wallet: spvw,
log: dex.StdOutLogger("T", dex.LevelInfo),
},
spvw: spvw,
}
w.currentTip.Store(&block{height: tipHeight})

dcrw.makeBlocks(0, tipHeight)

Expand Down
34 changes: 25 additions & 9 deletions client/asset/eth/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,12 @@ const (

providersKey = "providers"

// confCheckTimeout is the amount of time allowed to check for
// confirmations. Testing on testnet has shown spikes up to 2.5
// seconds. This value may need to be adjusted in the future.
confCheckTimeout = 4 * time.Second
// onChainDataFetchTimeout is the max amount of time allocated to fetching
// on-chain data. Testing on testnet has shown spikes up to 2.5 seconds
// (but on internet, with Tor, it could actually take up to 30 seconds easily).
// Setting it to 10 seconds for now until https://github.com/decred/dcrdex/issues/3184
// is resolved.
onChainDataFetchTimeout = 10 * time.Second

// coinIDTakerFoundMakerRedemption is a prefix to identify one of CoinID formats,
// see DecodeCoinID func for details.
Expand Down Expand Up @@ -3347,7 +3349,7 @@ func (w *assetWallet) SwapConfirmations(ctx context.Context, coinID dex.Bytes, c
return 0, false, err
}

ctx, cancel := context.WithTimeout(ctx, confCheckTimeout)
ctx, cancel := context.WithTimeout(ctx, onChainDataFetchTimeout)
defer cancel()

swapData, err := w.swap(ctx, secretHash, contractVer)
Expand Down Expand Up @@ -3700,7 +3702,7 @@ func (eth *ETHWallet) monitorBlocks(ctx context.Context) {
// tipChange callback function is invoked and a goroutine is started to check
// if any contracts in the findRedemptionQueue are redeemed in the new blocks.
func (eth *ETHWallet) checkForNewBlocks(ctx context.Context) {
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
ctx, cancel := context.WithTimeout(ctx, onChainDataFetchTimeout)
defer cancel()
bestHdr, err := eth.node.bestHeader(ctx)
if err != nil {
Expand Down Expand Up @@ -4683,7 +4685,7 @@ func (w *baseWallet) checkPendingTxs() {
// on it, cancel that request.
if pendingTx.actionRequested {
pendingTx.actionRequested = false
w.requestAction(asset.ActionResolved, pendingTx.ID, nil, pendingTx.TokenID)
w.resolveAction(pendingTx.ID, pendingTx.TokenID)
}
}
}
Expand Down Expand Up @@ -5044,8 +5046,8 @@ func (w *assetWallet) userActionRecoverNonces(actionB []byte) error {
return nil
}

// requestAction sends a ActionRequired or ActionResolved notification up the
// chain of command. nonceMtx must be locked.
// requestAction sends a ActionRequired notification up the chain of command.
// nonceMtx must be locked.
func (w *baseWallet) requestAction(actionID, uniqueID string, req *TransactionActionNote, tokenID *uint32) {
assetID := w.baseChainID
if tokenID != nil {
Expand All @@ -5058,6 +5060,20 @@ func (w *baseWallet) requestAction(actionID, uniqueID string, req *TransactionAc
aw.emit.ActionRequired(uniqueID, actionID, req)
}

// resolveAction sends a ActionResolved notification up the chain of command.
// nonceMtx must be locked.
func (w *baseWallet) resolveAction(uniqueID string, tokenID *uint32) {
assetID := w.baseChainID
if tokenID != nil {
assetID = *tokenID
}
aw := w.wallet(assetID)
if aw == nil { // sanity
return
}
aw.emit.ActionResolved(uniqueID)
}

// TakeAction satisfies asset.ActionTaker. This handles responses from the
// user for an ActionRequired request, usually for a stuck tx or otherwise
// abnormal condition.
Expand Down
6 changes: 1 addition & 5 deletions client/asset/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ type Wallet interface {
// FundMultiOrder funds multiple orders at once. The return values will
// be in the same order as the passed orders. If less values are returned
// than the number of orders, then the orders at the end of the list were
// not about to be funded.
// not able to be funded.
FundMultiOrder(ord *MultiOrder, maxLock uint64) (coins []Coins, redeemScripts [][]dex.Bytes, fundingFees uint64, err error)
// MaxFundingFees returns the max fees that could be paid for funding a swap.
MaxFundingFees(numTrades uint32, feeRate uint64, options map[string]string) uint64
Expand Down Expand Up @@ -1537,10 +1537,6 @@ type ActionRequiredNote struct {
ActionID string `json:"actionID"`
}

// ActionResolved is sent by wallets when action is no longer required for a
// unique ID.
const ActionResolved = "actionResolved"

type ActionResolvedNote struct {
baseWalletNotification
UniqueID string `json:"uniqueID"`
Expand Down
Loading
Loading