Skip to content

fix: address multi-agent review findings from testnet4 deployment PR (#3932)#3949

Merged
lionakhnazarov merged 13 commits intofeat/testnet4-deployment-supportfrom
fix/testnet4-review-followup
May 5, 2026
Merged

fix: address multi-agent review findings from testnet4 deployment PR (#3932)#3949
lionakhnazarov merged 13 commits intofeat/testnet4-deployment-supportfrom
fix/testnet4-review-followup

Conversation

@piotr-roslaniec
Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #3932 (feat/testnet4-deployment-support) addressing all valid findings from the multi-agent review. Each fix is a separate commit for bisectability.

  • F1 fix(ethereum): Replace context.Background() with 30-min timeout in waitDeployBackendTransactionMined to prevent indefinite blocking on stuck transactions
  • F2 docs(local_v1): Document lazy watcher cleanup and add defer ticker.Stop() in localBlockCounter.count()
  • F3 fix(electrum): Gate static fee fallback on non-mainnet; add network bitcoin.Network param to Connect (compiler-enforced, not config struct drift)
  • F4 fix(electrum): Replace string-based -32603 detection with typed feeOracleFailure sentinel (errors.As); fix ticker leak in keepAlive
  • F5 fix(ecdsa): Add CodeAt preflight before ABI calls in ecdsaWalletGroupParametersFromValidator to fail fast on wrong/undeployed address
  • F6 refactor(tbtc): Extract named groupParametersProvider interface (was anonymous inline)
  • F7 fix(btcdiff): Escalate idle log from Infof to Errorf after 20 consecutive idle ticks; reset counter on proven epoch
  • F8 fix(ecdsa): Add groupQuorum >= honestThreshold invariant check after existing range checks
  • F9 fix(deploy): Log warning when EcdsaDkgValidator is redeployed on non-mainnet (WalletRegistry must be updated to point to new address)
  • F10 fix(deploy): Remove unreachable try/catch in 07_approve_wallet_registry.ts; the ifaceHasFunction ABI guard is the authoritative check

Test plan

  • Go unit tests pass: go test ./pkg/...
  • TypeScript compiles: cd solidity/ecdsa && npx hardhat compile
  • CI green on all required checks
  • Electrum callers compile with updated Connect signature (network param added)

🤖 Generated with Claude Code

Validate that activeThreshold/groupQuorum is not less than
groupThreshold/honestThreshold when reading group parameters from
EcdsaDkgValidator. Malformed on-chain data could otherwise produce
contradictory protocol parameters that pass the individual range checks
while being internally inconsistent.
The Sepolia/Developer branch already logs the parameters it chooses.
Add the same log in the default (mainnet) branch so operators can verify
the group sizing on startup regardless of network.
Replace the inline anonymous interface assertion with a named package-level
interface. This makes the contract explicit, enables jump-to-definition, and
follows standard Go interface naming conventions.
Cleanup of cancelled watchers happens on the next block broadcast, not
immediately on context cancellation. Document this so callers understand
why channels may remain open after cancellation in no-block scenarios.

Also add defer ticker.Stop() for hygiene (count runs as a long-lived
goroutine, but the deferred stop is correct and silences the linter).
…Alive

1. Replace string-based -32603 detection with a typed feeOracleFailure
   sentinel. getFeeBtcPerKbOnce classifies oracle failures at the source;
   isElectrumFeeOracleFailure uses errors.As for type-safe detection.

2. Stop the previous ticker before reassigning in keepAlive. Each successful
   ping resets the interval by creating a new ticker; without Stop() the old
   ticker's goroutine and timer resource leaked until GC.
Add network bitcoin.Network parameter to Connect so the connection knows
which network it is operating on. EstimateSatPerVByteFee now returns an
error instead of the 2 sat/vByte static fallback when all fee oracle
queries fail on mainnet. The fallback remains active on testnet4 and
other non-mainnet networks where quiet mempools are expected.

All call sites updated to pass the bitcoin network from config.
…ined

Using context.Background() blocked indefinitely if a retarget transaction
was never mined (e.g. network congestion, dropped mempool). Replace with
a 30-minute deadline so the maintainer goroutine can detect a stuck
transaction and return an error instead of blocking shutdown.
Before calling the hand-maintained ABI getters on EcdsaDkgValidator,
verify that the target address actually contains contract code. Without
this check, an EOA address or a wrong deployment address causes a cryptic
ABI decode failure instead of an actionable error message.
When IdleOnPreflightFailure is true, the maintainer silently idles on
min-difficulty epochs with no signal for operators monitoring health.
Track consecutive idle ticks and emit Errorf after 20 ticks (~20 minutes
with default IdleBackOffTime=60s) so the LightRelay falling behind the
Bitcoin chain surfaces in monitoring. Reset the counter when an epoch
is successfully proven.
…pdate needed

On non-mainnet networks, EcdsaDkgValidator is redeployed whenever bytecode
changes (e.g. groupSize 100→3). Emit a log warning that includes the old
address so operators know to update the WalletRegistry to point at the
new validator before the system is used.
…ript

The ABI check (ifaceHasFunction) is the authoritative guard for whether
approveApplication exists on TokenStaking. The subsequent try/catch for
'No method named approveApplication' is unreachable given the guard and
could silently swallow genuine revert errors. Remove it to make error
handling deterministic.
- gofmt: electrum_test.go, tbtc.go, bitcoin_difficulty_test.go
- eslint: replace bare template literal with double-quoted string
  in 02_deploy_dkg_validator.ts (line 29, no substitution)
@piotr-roslaniec piotr-roslaniec changed the base branch from main to feat/testnet4-deployment-support May 5, 2026 14:41
…and DKG validator parameters

Extract recordIdleTick/resetIdleTicks from proveEpochs loop for deterministic
counter testing. Narrow internal ecdsa_dkg_validator_chain functions to
bind.ContractCaller (2 methods) to enable a lightweight mock. Extract
feeOracleFallback from EstimateSatPerVByteFee for direct testability.

Tests added:
- btcdiff: idle counter increments to threshold, resets, and re-escalates
- ecdsa_dkg_validator_chain: zero address, no-code preflight, quorum<threshold
  invariant, and happy-path parameter extraction
- electrum: isElectrumFeeOracleFailure unwrapping, mainnet refusal, and
  non-mainnet static fallback
Copy link
Copy Markdown
Collaborator

@lionakhnazarov lionakhnazarov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did not find correctness regressions in the reviewed changes. No blocking issues found in the follow-up delta.

Looks good to me

@lionakhnazarov lionakhnazarov merged commit 53009af into feat/testnet4-deployment-support May 5, 2026
22 of 23 checks passed
@lionakhnazarov lionakhnazarov deleted the fix/testnet4-review-followup branch May 5, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants