Skip to content

Conversation

TheBlueMatt
Copy link
Contributor

Yet another step towards splitting main.cpp. After this and #8930 (which I will rebase after this is merged to clean it up a ton), we're ready to do the big code moves :).

This PR focuses on mapBlockSource, removing references to it from ProcessNewBlock and moving it to callsites, cleaning up logic in the process.

Built on #9026 to avoid conflicts and simplify the backporting (#9048).

Copy link
Member

@sipa sipa left a comment

Choose a reason for hiding this comment

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

Concept ACK

@@ -2976,8 +2976,6 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL, txConflicted, txChanged)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
if (!state.CorruptionPossible())
Copy link
Member

Choose a reason for hiding this comment

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

This does not actually remove a duplicate. If there is a reorganization, and some block within it is invalid, InvalidChainFound will be called with the tip of the chain, rather than the block that failed. This may have an effect on the large fork detection logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Eek! Youre right. Just removed the commit...it wasnt important anyway.

forceProcessing |= MarkBlockAsReceived(hash);
// mapBlockSource is only used for sending reject messages and DoS scores,
// so the race between here and cs_main in ProcessNewBlock is fine.
if (!mapBlockSource.count(hash))
Copy link
Member

Choose a reason for hiding this comment

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

Nit: You can use std::map::emplace here to avoid two searches (the bool returned in the pair tells you whether an insert occurred or now). You could also remember the created iterator and pass it to mapBlockSource.erase below. (and likewise above)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

// out to be invalid.
ProcessNewBlock(state, chainparams, &block, true, NULL, &fNewBlock);
int nDoS;
if (state.IsInvalid(nDoS)) {
Copy link
Member

Choose a reason for hiding this comment

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

So glad to see this duplication go!

@TheBlueMatt TheBlueMatt force-pushed the net_processing_4 branch 2 times, most recently from 2e30cb4 to 9ab2086 Compare November 7, 2016 00:32
@sipa
Copy link
Member

sipa commented Nov 7, 2016

Needs rebase.

@TheBlueMatt
Copy link
Contributor Author

Rebased.

@@ -5914,22 +5910,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// updated, reject messages go out, etc.
MarkBlockAsReceived(resp.blockhash); // it is now an empty pointer
fBlockRead = true;
// mapBlockSource is only used for sending reject messages and DoS scores,
Copy link
Member

Choose a reason for hiding this comment

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

Stale comment? Or am I not seeing the race?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Race if multiple nodes send you something near the same time you might send the DoS/Reject to the "wrong" node, of course we dont really care because we'll get to them next time they send us a block (and someone will still get it).

Copy link
Member

Choose a reason for hiding this comment

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

I assumed this just referred to the fact that we drop the cs_main lock between here and the call to ProcessNewBlock below, so in theory mapBlockSource could be modified in between, and we'd lose the expected callbacks.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks. After discussion on IRC, I'm good with this. Though the comment could be a bit more descriptive, it makes the issue seem like more than it is.

This only returned information in the case of CheckBlock failure,
but breaks future changes.
This further decouples ProcessNewBlock from networking/peer logic.
@TheBlueMatt
Copy link
Contributor Author

As mentioned on IRC, this now reverts #9087, which conflicted, but no one registered any serious desire to maintain its functionality since it was realtively trivial.

@sipa
Copy link
Member

sipa commented Nov 11, 2016

utACK ae22357

@theuni
Copy link
Member

theuni commented Nov 11, 2016

utACK ae22357 other than the comment nit. Obviously not a blocker though.

state = sc.state;
}
return BIP22ValidationResult(state);
if (!sc.found)
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure why this shouldn't be if (fAccepted && !sc.found)

Copy link
Member

Choose a reason for hiding this comment

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

If it is not accepted, there will certainly have been a callback to signal what was invalid about it. Thus, not having had a signal implies it was accepted.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Technically this is a change in behavior...previously: if you got an error (disk space, etc) during connection you would print it in the BIP22 result function, after this patch (though, indeed, adding an fAccepted check wouldnt help) you will no longer print that, and your node will just exit (probably after retuning "success" from this function.

}

NotifyHeaderTip();

CValidationState state; // Only used to report errors, not invalidity - ignore it
Copy link
Contributor

Choose a reason for hiding this comment

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

you don't need to duplicate CValidationState state, you can move the first declaration out of the locked context.

Copy link
Member

Choose a reason for hiding this comment

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

Personally I like making it clear that this CValidationState is unrelated to the other one; it was confusing in the old code that validation errors from different blocks might get put in the same CValidationState (which would get cleared out in ActivateBestChainStep).

Copy link
Contributor

Choose a reason for hiding this comment

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

Not a big deal anyway.

@jtimon
Copy link
Contributor

jtimon commented Nov 17, 2016

ut ACK ae22357 apart from the couple of small nits.

@sdaftuar
Copy link
Member

utACK ae22357

@sipa sipa merged commit ae22357 into bitcoin:master Nov 17, 2016
sipa added a commit that referenced this pull request Nov 17, 2016
…ic (#3)

ae22357 Replace CValidationState param in ProcessNewBlock with BlockChecked (Matt Corallo)
7c98ce5 Remove pfrom parameter from ProcessNewBlock (Matt Corallo)
e2e069d Revert "RPC: Give more details when "generate" fails" (Matt Corallo)
@rebroad
Copy link
Contributor

rebroad commented Nov 21, 2016

Is this change part of a roadmap that is documented somewhere?

@jtimon
Copy link
Contributor

jtimon commented Nov 21, 2016

@rebroad It is part of a longer branch by @TheBlueMatt : https://github.com/TheBlueMatt/bitcoin/tree/net_processing_file which does enough decoupling to cleanly separate the p2p messages part out of main.o. But I think the PRs (and commits) stand on their own (I did less review on the previous steps). Perhaps @TheBlueMatt can give more details.

@rebroad
Copy link
Contributor

rebroad commented Nov 22, 2016

@jtimon thanks. I also meant to ask: why is this being done? Is it because main.cpp is considered to be too large?

@sipa
Copy link
Member

sipa commented Nov 23, 2016

@rebroad Splitting main into several files would be trivial to do, if we don't care much about clean separation between the resulting files. This PR is part of an ongoing effort to separate network processing (currently spread over net, protocol, and main) and block validation with clear interfaces between them. The end result is not only splitting main into two files, but splitting it into two files that each have clearly-separated responsibilities.

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

Successfully merging this pull request may close these issues.

7 participants