Skip to content

Fix HTTP sends, epicbox address port, chain type and balance total - #92

Open
sneurlax wants to merge 9 commits into
mainfrom
fix/epic-send-and-address
Open

sneurlax wants to merge 9 commits into
mainfrom
fix/epic-send-and-address

Conversation

@sneurlax

@sneurlax sneurlax commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

Fixes found while testing Stack Wallet's Epic Cash wallet against a private UserTesting chain. Based on d5cfb76, the commit Stack Wallet pins. It merges cleanly onto GitHub main.

  • e70ffd9 and bc8a6ad: pass the node's sync state to HTTP sends.
    • epic-wallet 4.0 turned the third argument of Owner::new and Owner::init_send_tx into is_node_synced.
    • tx_send_http still passed an is_stopped flag set to false, so every HTTP send failed with "Node not synchronized" (since dc3a268).
    • It now asks the node for get_status and treats it as synced on no_sync, the same rule epic-wallet's CLI uses. If the node cannot be asked, that error is returned instead of "Node not synchronized".
    • tx_create (epicbox and slate sends) keeps the false flag. There it only reaches the subscriber that an epicbox send opens on the wallet's own address. e70ffd9 had set it, and bc8a6ad takes that back: with the flag set, the subscriber held the socket while waiting for the relay, so each send waited for the relay's next message, and it handled incoming slates next to the app's own listener.
  • 22e61ca: include a non-default epicbox port in the wallet address.
    • get_wallet_address returned pubkey@domain even when the relay was not on 443, so senders delivered to 443 and the slate was lost.
    • Addresses on 443 are unchanged.
  • 9cc723a: apply the configured chain type to epic_core's global. A no-op for mainnet wallets.
  • 168e749: leave locked outputs out of the balance total.
    • epic-wallet's retrieve_info counts locked outputs in total, unlike grin-wallet and mwc-wallet.
    • So a caller that adds amount_awaiting_finalization showed 54.992 instead of 24.992 after sending 5 from a 30 output.
    • The record shape is unchanged.
  • 6ae4730: run the node tests as mainnet wallets. The ignored tests use a mainnet node and mainnet address vectors but had chain "floonet" in their config. Once 9cc723a applied the chain type, the address vector test produced a floonet address.

Tests:

  • cargo test --release --locked: 18 passed. The 14 ignored tests need a mainnet node.
  • cargo test --release --locked -- --include-ignored: 32 passed.
  • cargo build --release --locked: passes.
  • flutter test: 38 passed, including the new test/balance_data_test.dart (run on 168e749; no Dart changes since).

On the local chain:

  • The fixed library's address includes :43420.
  • An epicbox receive and two HTTP sends confirmed (on 168e749).
  • Two epicbox sends from the library confirmed on bc8a6ad. Each rust_create_tx call took 0.13 s. On 168e749 the same call took 3.6 s against a relay with a 5 s challenge interval (the relay's default is 60 s).
  • With the node stopped, an HTTP send returns "Could not get the node's sync status: ...".
  • The unpatched library fails the HTTP send and omits the port.
  • In the Stack Wallet app built against 168e749, the address shows the port and an HTTP send confirmed.

Release note: Stack Wallet uses the prebuilt native-0.3.0-1 artifacts, so it needs a tagged release with prebuilts before it can repin.

epic-wallet 4.0 turned the third argument of Owner::new and
Owner::init_send_tx into is_node_synced. tx_send_http and tx_create still
passed an is_stopped flag set to false, so every HTTP send failed with
"Node not synchronized", and the subscriber that an epicbox send opens
stayed paused.

Ask the node for its status before a send, the way the epic-wallet CLI
does: synced only when get_status answers with sync_status "no_sync".
get_wallet_address returned pubkey@domain even when the relay was not on
443. Senders take a missing port to mean 443, so slates sent to that address
went to the wrong port and were lost. Append :port when the configured port
is not 443. Addresses on 443 keep their current form, which is also how
epic-wallet's EpicboxAddress displays them, and epic-wallet's address parser
already accepts @host:port.
epic_core keeps the chain type in a process-wide global that defaults to
Mainnet, and nothing in the plugin set it, so a wallet configured for
floonet or usertesting still ran with mainnet rules: coinbase maturity,
header version in new slates, tx weight limits, epicbox address version
bytes. Set it from the wallet config in get_wallet(), which opening,
creating and recovering a wallet all go through.

No-op for mainnet wallets, since Mainnet is already the default.
epic-wallet's retrieve_info reports total as unspent + immature + locked +
unspent unconfirmed, so an output locked by an unconfirmed send still counts.
grin-wallet and mwc-wallet leave locked outputs out. The send's change is
already in amount_awaiting_finalization, so a caller that adds the two shows
the spent input as well: 54.992 instead of 24.992 after sending 5 from a 30
output.

BalanceData.fromJson now reports total minus amount_locked, clamped at 0 and
computed in nano-EPIC. The record shape is unchanged.
@sneurlax sneurlax changed the title Fix/epic send and address Fix HTTP sends, epicbox address port, chain type and balance total Nov 11, 2026
@sneurlax

sneurlax commented Nov 11, 2026 •

Copy link
Copy Markdown
Member Author

We should also update re: cypherstack/epic-wallet#3 once that is merged

…rors

e70ffd9 passed the node's sync state to both send paths. For an epicbox
send that flag goes to the subscriber epic-wallet opens on the wallet's own
address. With it set, the subscriber reads the socket while holding the
lock that publishing needs, so tx_create waited for the relay's next
message (3.6 s per send against a relay with a 5 s challenge interval,
0.13 s with the subscriber paused), and it handled incoming slates next to
the app's own listener. tx_create goes back to a false flag, as before
e70ffd9, and no longer asks the node for its status.

For an HTTP send, a get_status call that failed was treated as "not
synced", so the caller saw "Node not synchronized" for a node that could
not be asked. That error is now returned as it is.
The ignored tests use a mainnet node and mainnet address vectors with
chain "floonet" in their config. That was harmless while the chain type was
never applied. Since 9cc723a it is, so the address vector test produced a
floonet address, and running the ignored tests switched the process-wide
chain type under the address tests that run by default.

Use "mainnet" in the test configs and say so in the ignore reason. All 32
tests pass with --include-ignored.
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.

1 participant