Skip to content

Conversation

jnewbery
Copy link
Contributor

Fixes #9526

Nodes running in -blocksonly mode do not send and receive transactions
outside blocks. They do not have a mempool, so -maxmempool should be set
to 0.

Unused mempool memory can be used for the UTXO coincache (PR #8610) so
not setting -maxmempool to 0 can cause to coincache to grow larger than
expected.

If -blocksonly is set and -maxmempool is set to anything other than 0,
error and exit. If -blocksonly is set and -maxmempool is not set,
implicitly set -maxmempool to 0.

I've also added an additional comment around the nMempoolSizeMin check
in AppInitParameterInteraction() since it wasn't immediately obvious to me
what that check was doing.

Nodes running in -blocksonly mode do not send and receive transactions
outside blocks. They do not have a mempool, so -maxmempool should be set
to 0.

Unused mempool memory can be used for the UTXO coincache (PR bitcoin#8610) so
not setting -maxmempool to 0 can cause to coincache to grow larger than
expected.

If -blocksonly is set and -maxmempool is set to anything other than 0,
error and exit. If -blocksonly is set and -maxmempool is not set,
implicitly set -maxmempool to 0.
@jnewbery jnewbery force-pushed the blocksonlynomempoolsharing branch from 99daee0 to 2838d28 Compare January 17, 2017 20:08
@gmaxwell
Copy link
Contributor

gmaxwell commented Jan 17, 2017

Whitelisted peers can still relay transactions for blocksonly, I suspect this would break that. (FWIW I don't like that whitelisting does stuff like that, but its what it does and people depend on it)

@pstratem
Copy link
Contributor

pstratem commented Jan 18, 2017 via email

@sipa
Copy link
Member

sipa commented Jan 18, 2017 via email

@jnewbery
Copy link
Contributor Author

@gmaxwell @pstratem Thank you. I wasn't aware of this behaviour.

As far as I can tell, this can only happen to a -blocksonly node as follows:

  • the node connects to a peer and sends a version message. The 'relay' field is set to FALSE (see PushNodeVersion() in net_processing.cpp - bitcoin core always sets relay to FALSE if -blocksonly is set since the global fRelayTxes = !blocksonly).
  • the peer disregards the relay field. Note that bitcoin core respects the relay field that it receives (see ProcessMessage() in net_processing.cpp.
  • the peer sends INVs/TXs, which the node accepts because -whitelistrelay is set.

so this can only happen if the node is connecting to a non-bitcoin-core peer which is disregarding the semantics of the relay field in the version message.

@gmaxwell @pstratem can you give some use cases? Are people relying on this behaviour?

@pstratem
Copy link
Contributor

pstratem commented Jan 18, 2017 via email

@jnewbery
Copy link
Contributor Author

@pstratem Maybe I'm misunderstanding, but I would expect the only way for transactions to enter the node's mempool is for transactions to be relayed from peers. That can't happen if blocksonly is set, unless that peer is violating the relay field in our version message.

Of course, we can send transactions to peers. That's true without a mempool, and is unaffected by this PR.

You seem to understand this better than me - can you explain where I'm wrong.

@theuni
Copy link
Member

theuni commented Jan 19, 2017

Somewhat unrelated to the discussion here, but I've been meaning to get rid of the fRelayTxes global for a while. I just hacked this up, and I think it makes reasoning about this much easier: theuni@f196610 .

It was done quickly and probably isn't quite right, but I'll clean it up and PR separately if the approach is agreed upon.

@jnewbery
Copy link
Contributor Author

@theuni I agree that we should get rid of the global to make reasoning easier. I also think we need additional documentation here to make the intended behaviour more explicit (ie that blocksonly doesn't mean only blocks if you have some other setting!).

Please tag me when you have a PR for the relay/accept transactions split so I can review it. I've had a look at theuni@f196610 and the approach looks generally good.

@pstratem
Copy link
Contributor

pstratem commented Jan 21, 2017 via email

@jnewbery
Copy link
Contributor Author

Nodes which have whitelisted a blocks only peer will send them transactions.

I don't think this is true. When a blocksonly node connects to a peer, it sends the version header with the relay field set to false:

   connman.PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
            nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes));

(

connman.PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes));
)

The peer receives that version message and sets fRelayTxes to false for that CNode. Any whitelist settings are not considered here:

            if (!vRecv.empty())
                vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message

(

bitcoin/src/net_processing.cpp

Lines 1242 to 1243 in 727a798

if (!vRecv.empty())
vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message
).

When the peer is sending messages to the blocksonly node, it checks the fRelayTxes field and explicitly clears all txs from its INV messages:

    if (!pto->fRelayTxes) pto->setInventoryTxToSend.clear();

(

if (!pto->fRelayTxes) pto->setInventoryTxToSend.clear();
)

I've run some tests locally, and they seem to confirm that bitcoin nodes will not send transactions to blocksonly peers, regardless of whitelist settings.

Furthermore, setting -blocksonly soft sets -walletbroadcast to false, so the blocksonly node won't even broadcast transactions it originates (which is sensible behaviour - nodes that broadcasts just their own transactions are terrible for transaction privacy).

It seems to me that the only ways to get transactions into a blocksonly node's mempool are to:

  1. connect to it with a non-compliant node which ignores the relay field in the version message; or
  2. explicitly set walletbroadcast to true and give up any transaction privacy.

@sipa
Copy link
Member

sipa commented Jan 23, 2017

Maybe it's easier to just not add the unused mempool space to the available dbcache when blocksonly is set?

@jnewbery
Copy link
Contributor Author

@sipa - it's certainly true that what you're suggesting is possible. It's the approach that I started with, but changed tack later because it was a far smaller, cleaner code change to simply set mempool size to zero.

I'm happy to revert to my original approach, but at the very least we should understand and document the behaviour that @pstratem is talking about. From my testing and code-reading, it doesn't seem possible that blocksonly nodes would ever have anything in their mempool. I also don't understand the use-case.

@jnewbery
Copy link
Contributor Author

Pinging @pstratem @gmaxwell . Can you help me understand what the use case here, so we can either:

  • document the blocksonly/whitelist behaviour that you're talking about; or
  • move forward with this PR.

Thanks!

@gmaxwell
Copy link
Contributor

gmaxwell commented Jan 29, 2017

Whitelisting was originally added so that armory user's mandatory Bitcoin nodes would still be able to reliably relay transactions when the armory software, which ignores frelaytxes, behind them wanted the transactions relayed. I have been told that other commercial custom wallet code depend on this whitelist always relays behavior (which is too bad, because I dislike it and think we never should have done it that way).

The reason for this is because otherwise if your 'wallet' is implemented as [bitcoin core] - [custom stuff] there is no way for your custom stuff to implement a rebroadcast like functionality similar to that of the integrated wallet.

Blocksonly isn't even a document option yet, because it has no servicebits significance so nodes could avoid having all their automatic outbound peers be blocks only and ending up unable to relay transactions. It will be at least one BIP and two releases from being a documented option for that reason (unless the thinking changes), so I really don't think it matters how we handle its memory usage vs dbcache for now.

@laanwj
Copy link
Member

laanwj commented Jun 26, 2017

Looks like this is stuck/controversial. I think it's a good point that -blocksonly is an "undocumented" developer-only option, so interaction with other options isn't very important.
Should we close?

@jnewbery
Copy link
Contributor Author

Yes - closing for now. This should be revisited when blocksonly is made a non-debug option.

@jnewbery jnewbery closed this Jun 26, 2017
@jnewbery
Copy link
Contributor Author

jnewbery commented Jun 9, 2019

-blocksonly is no longer a hidden option (#15990)

@bitcoin bitcoin locked as resolved and limited conversation to collaborators Dec 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

-blocksonly should disable sharing of mempool with dbcache
7 participants