Skip to content

Transaction broadcast succeeded but was not included on-chain #6546

Open

Description

@jakamobiii

Software Versions

OS : Linux
JVM : Oracle Corporation 1.8.0_161 amd64
Version : 4.8.0

Expected behaviour

After a transaction is broadcast successfully, it should be packaged into a block and included on-chain normally.

Actual behaviour

An abnormal behavior was observed in a private network: transactions that were broadcast successfully were not included on-chain.

  • The private network consists of 1 SR node and 2 Fullnodes, all connected to each other.
  • The two Fullnodes were started at the same time and immediately began synchronizing blocks from the SR (both were in the block-catching-up state).
  • During the catch-up process, a transaction was broadcast to one of the Fullnodes:
    • The Fullnode returned a transaction broadcast success response.
    • However, the transaction never included on-chain, and it did not appear in any subsequent blocks.
  • Based on network logs alone, the transaction seemed to be received and propagated by the nodes during the catch-up period, but it was not selected by the SR for block production.

Once block syncing completed, the issue disappeared and the system returned to normal behaviour.

Frequency

This issue had not occurred previously. It was discovered during a recent private network deployment and testing.

Activity

  1. zeusoo001 commented on Feb 5, 2026

    @zeusoo001
    Contributor

    @jakamobiii Based on your description, after the two fullnodes start up, they quickly complete block synchronization and enter broadcast state because their block heights are very close. Transactions can be broadcast between the two fullnodes, but since the fullnodes and the SR are in a synchronization state, transactions cannot be broadcast to the SR. Therefore, although the transaction appears to have been successfully broadcast, it is not actually recorded on the chain. It's best to wait until the fullnodes have completed synchronization before broadcasting the transaction.

  2. 317787106 commented on Feb 5, 2026

    @317787106
    Collaborator

    @jakamobiii You should not broadcast any transaction through FullNode until it catched up the latest block.

  3. lxcmyf commented on Feb 5, 2026

    @lxcmyf
    Collaborator

    @jakamobiii
    In the node synchronization phase, although the transaction is broadcast, it does not flow to SR, so it is not linked.

  4. jakamobiii commented on Feb 5, 2026

    @jakamobiii
    Author

    Besides waiting for block synchronization to complete, are there other solutions?

  5. zeusoo001 commented on Feb 5, 2026

    @zeusoo001
    Contributor

    @jakamobiii It's also possible to broadcast through other nodes that have completed block synchronization.

  6. jakamobiii commented on Feb 5, 2026

    @jakamobiii
    Author

    @zeusoo001 Another question is whether the API interface needs optimization. It shows a successful broadcast, but the transaction isn't actually recorded on the blockchain.

  7. zeusoo001 commented on Feb 5, 2026

    @zeusoo001
    Contributor

    @jakamobiii Yes, that's a very good question. I think it's necessary to optimize it. You can follow the progress of this issue.

  8. zeusoo001 commented on Mar 19, 2026

    @zeusoo001
    Contributor

    This issue is included in the v4.8.2 release (ref: #6585). Development is currently in progress. We will continue to sync updates here as work advances. The fix is tentatively expected to be completed by April 2026.

  9. moved this to In Review in java-tronon Mar 31, 2026
  10. moved this from In Review to In Progress in java-tronon Mar 31, 2026
  11. moved this from In Progress to Backlog in java-tronon May 10, 2026
  12. xxo1shine commented on May 15, 2026

    @xxo1shine
    Collaborator

    Quick update: after reviewing the synchronization-state handling changes, we've decided to move this fix to the next release cycle instead of including it in v4.8.2.

    Reason: although the implementation itself is relatively contained, the change affects transaction broadcast semantics and API behavior during node catch-up. We'd prefer to finalize the synchronization-threshold configuration and compatibility behavior more carefully rather than introducing it late in the current release cycle.

    The fix direction has already been determined and implementation can continue in parallel for the next release window.

  13. xxo1shine commented on Sep 3, 2026

    @xxo1shine
    Collaborator

    Status update: This feature request is no longer planned for the next release. We are removing the status: next-release label and keeping the issue in the backlog for future consideration.

    Although the implementation itself is relatively contained, the change affects transaction broadcast semantics and API behavior during node catch-up. We'd prefer to finalize the synchronization-threshold configuration and compatibility behavior more carefully rather than introducing it late in the current release cycle.

    We will revisit this once the design is better defined and the release scope allows it.

  14. SeriousCoding789 commented on Sep 22, 2026

    @SeriousCoding789
    Contributor

    The catch-up explanation above is right; I won't repeat it. Worth adding is that it's one instance of a more general property, and that part of what was asked for already exists in the code.

    What SUCCESS actually attests. Wallet.broadcastTransaction returns SUCCESS once the transaction has a valid signature, passes the duplicate check, enters the local pending pool, and is relayed to at least one peer. That is a local acceptance and relay receipt — it says nothing about whether a producer will see it, select it, or keep it.

    Other cases where a successfully-broadcast transaction legitimately never lands, none involving a node being behind:

    1. Expiration. Manager.validateCommon rejects a transaction once expiration <= headBlockTime. Anything waiting in the pool past its expiration window is dropped — by design.
    2. Production budget. In generateBlock, once System.currentTimeMillis() > timeout the producer stops packing; the rest of the pending queue isn't in that block.
    3. Block size cap. A transaction that doesn't fit the remaining BLOCK_SIZE is postponed.
    4. Multi-sign cap. At most one multi-sign transaction per owner address goes into a given block.
    5. Fork switch. A transaction in a block that later gets orphaned returns to the re-push queue and may expire before it is packed again.

    In practice 2–5 combine with 1: a transaction is deferred for a few blocks, then dies of expiration. Inclusion was never guaranteed in the first place.

    What would be a defect. A fully synced node with healthy connections to a producing SR broadcasts a transaction well within its expiration window, not a duplicate, hitting none of the caps above — and it still never appears in any block across many production slots, while demonstrably present in the producer's pending pool. That is worth reporting. Everything above it is the protocol
    working as designed.

    The originally reported scenario therefore looks like expected behaviour. What's still genuinely open is the narrower question of whether SUCCESS should ever be returned by a node that knows it cannot reach a producer.

  15. xxo1shine commented on Sep 22, 2026

    @xxo1shine
    Collaborator

    @SeriousCoding789, I agree that SUCCESS means the node accepted the transaction; it does not guarantee on-chain inclusion. A transaction may still expire or be deferred by block production limits, so a successful broadcast that is never included is not, by itself, a bug. This issue focuses on broadcast feedback while a node is catching up: we want to identify cases where the transaction cannot be effectively propagated and reduce the chance of returning SUCCESS when it cannot reach a producing node. This improvement would not guarantee eventual inclusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic:netp2p net work, synchronization

    Type

    No type

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions