The broadcastTransaction() function in @stacks/transactions should be able to broadcast to multiple nodes. This will help with nodes sometimes not relaying the transaction due to a previous pending/stuck transaction. One way this can be done is to fetch the list of peers of the node before broadcasting.
Sounds nice, but I am not sure that it should be high priority? I would also like to hear some evidence around "nodes not relaying the transaction" - is that true? Personally, I haven't seen it. I _have_ seen issues where POST /v2/transactions fails - but if that fails, who knows if you'll be able to fetch /v2/neighbors. On the other hand, if a wallet / exchange had a known list of node URLs, wouldn't it be easy to call broadcastTransaction() to each one in parallel?
This was an issue brought up during a meeting. I haven't been able to reproduce this problem. Maybe @kantai has more context.
The context around this is that currently the stacks-node mempool only really does a best-effort propagation of transactions. If, for whatever reason, the stacks-node that was first broadcasted to can't forward the transaction to its neighbors, the transaction may not propagate to a miner. Clients can mitigate this somewhat by broadcasting to multiple nodes.
On the other hand, if a wallet / exchange had a known list of node URLs, wouldn't it be easy to call broadcastTransaction() to each one in parallel?
Yes, that'd be a perfectly viable approach.
I would like to followup on this in terms of final thoughts around how we are envisioning the implementation. So currently broadcastTransaction only broadcast to single node based on network parameter passed to it.
export async function broadcastTransaction(
transaction: StacksTransaction,
network: StacksNetwork,
attachment?: Buffer
): Promise<TxBroadcastResult> {
const rawTx = transaction.serialize();
const url = network.getBroadcastApiUrl();
return broadcastRawTransaction(rawTx, url, attachment);
}
broadcastTransaction is calling network.getBroadcastApiUrl() to get the broadcast url. I would like to know in case we want to broadcast it to multiple nodes then where do i can get the multiple nodes urls because network instance has only one url. Is there any separate endpoint for that? broadcastRawTransaction in case of above sample code. Then which txid to return and that may also change or impact broadcastTransaction return type as currently its single object. Need thoughts on this as well.cc: @agraebe @kantai @yknl @asimm241
- So
broadcastTransactionis callingnetwork.getBroadcastApiUrl()to get the broadcast url. I would like to know in case we want to broadcast it to multiple nodes then where do i can get the multiple nodes urls because network instance has only one url. Is there any separate endpoint for that?
Note this whole issue is related to the discussion at https://github.com/blockstack/stacks.js/discussions/1038#discussioncomment-908641 where we're questioning whether this lib should even be doing its own network requests. Based on the current sentiment from that discussion, it sounds like we may be doing away with network handling at this layer, which would make this issue irrelevant.
Regardless of that, to answer your question specifically -- I think Hiro is only committed to maintaining a single public node instance / URL. So I don't think we could hardcode an array of nodes/URLs. There are the few seed/bootstrap nodes that Hiro maintains, but I'm not sure if we'd recommend clients to start using their RPC APIs (and I don't think we have the https and/or CORs configured for that anyway). /cc @CharlieC3 @kantai.
One alternative is to use the /v2/neighbors endpoint to grab a bunch of connected peers and attempt to broadcast transactions to them, but that's a heuristic that doesn't seem very effective IMO.
- Second question would be like in case if we are able to broadcast to multiple node then we will have multiple txid's in response to each
broadcastRawTransactionin case of above sample code. Then which txid to return and that may also change or impactbroadcastTransactionreturn type as currently its single object. Need thoughts on this as well.
Txid's are known by the client before broadcasting, it's essentially a hash of the transaction. Unless I'm misunderstanding something, nodes should never return different txid's for the same tx payload.
Most helpful comment
Note this whole issue is related to the discussion at https://github.com/blockstack/stacks.js/discussions/1038#discussioncomment-908641 where we're questioning whether this lib should even be doing its own network requests. Based on the current sentiment from that discussion, it sounds like we may be doing away with network handling at this layer, which would make this issue irrelevant.
Regardless of that, to answer your question specifically -- I think Hiro is only committed to maintaining a single public node instance / URL. So I don't think we could hardcode an array of nodes/URLs. There are the few seed/bootstrap nodes that Hiro maintains, but I'm not sure if we'd recommend clients to start using their RPC APIs (and I don't think we have the https and/or CORs configured for that anyway). /cc @CharlieC3 @kantai.
One alternative is to use the
/v2/neighborsendpoint to grab a bunch of connected peers and attempt to broadcast transactions to them, but that's a heuristic that doesn't seem very effective IMO.Txid's are known by the client before broadcasting, it's essentially a hash of the transaction. Unless I'm misunderstanding something, nodes should never return different txid's for the same tx payload.