Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for verifychain #634

Merged
merged 48 commits into from Dec 11, 2019
Merged

Fix for verifychain #634

merged 48 commits into from Dec 11, 2019

Conversation

aguycalled
Copy link
Member

@aguycalled aguycalled commented Nov 18, 2019

Fixes #630

See issue for more details.

Changes introduced

  • New RPC command getcfunddbstatehash covered by functional test cfunddb-statehash.py
  • New state for payment requests 6 when those are paid.
  • The payment request parameter paidOnBlock is substituted by stateChangedOnBlock when state is 6
  • New structure for storing the state history of CFundDB entries. Those are stored in a map associating blockhash and state, allowing to directly revert state transitions when reorganizations are seen.
  • verifychain now checks for the consistency of the CFundDB state hash when level 4 is specified.

Important

This set of changes will require older clients to reindex on launch, keeping the node offline for some hours at best. In order to reduce downtime, node operators can proceed as follows if needed:

  • Close node with old version.
  • mkdir /tmp/reindexdata; cp -rf <data_folder>/blocks /tmp/reindexdata/; cp -rf <data_folder>/chainstate /tmp/reindexdata/
  • Reopen node with old version. It will be again online
  • Launch in parallel a second instance of the node, this time using the new version with the parameters -reindex -datadir=/tmp/reindexdata/
  • Once the reindex finishes, close both nodes and copy back the reindexed data.
  • rm -rf <data_folder>/blocks <data_folder>/chainstate; cp -rf /tmp/reindexdata/* <data_folder>
  • Relaunch new version of the node.

What to test

  • Launch a wallet with an old copy of the blockchain. It should show that the database is corrupted and that reindex is needed. Test both gui and headless
  • Launch a fully synced wallet and execute verifychain 4 0. This should return true.
  • Partial runs of verifychain 4 n return true (being n an arbitrary value between 1 and the length of the chain).
  • Wallet should be able to sync correctly

@navbuilder
Copy link

A new build of 91e731d has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@navbuilder
Copy link

A new build of 70a96a7 has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@aguycalled
Copy link
Member Author

aguycalled commented Nov 18, 2019

Tested locally and fixed with fcc66d1, ready for review

@navbuilder
Copy link

A new build of fcc66d1 has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@navbuilder
Copy link

A new build of ceb4a5e has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@aguycalled
Copy link
Member Author

aguycalled commented Nov 20, 2019

Although verifychain 4 0 is returning true in all my systems, partial runs of the check are returning false in certain conditions. As an explanation of its function, verifychain disconnects the amount of blocks specified in the second parameter, and connects them again. If 0 is specified as second parameter the whole chain is disconnected and reconnected again. Partial runs can be done passing an amount different from 0 (up to the current height).

I've initially found that partial runs were failing in mainnet, but each run of verifychain was taking too long. So I've tried to reproduce this is in a private devnet to get a smaller context which would allow me to test quicker.

Archive.zip

verifychain 4 10 returns false using the above attached chain data. I've chosen 10 randomly, but I was curious to see exactly what was failing, so I wrote a bash script to automate the search.

datadir=/Users/alex/navcoin-core/data
navcli="/Users/alex/navcoin-core/src/navcoin-cli -devnet -datadir=$datadir"
blocks=`$navcli getinfo|jq .blocks`

for i in $(seq 1 $blocks);
do
   verifyoutput=`$navcli verifychain 4 $i`
   if [[ "$verifyoutput" == "false" ]]; 
   then
       verifyoutput+=`echo ' - ' && echo failed at $(grep 'ERROR: VerifyDB()' $datadir/devnet/debug.log |tail -1|sed 's/.*block at \(\d*\)/\1/')`
   fi
   echo Rewinding to \
   $(bc <<< $blocks-$i) \
   - reconnecting up to $blocks \
   - verifychain 4 $i -> $verifyoutput;
done

Running this script would be very useful against a mainnet fully synced node, as it would give us certainty about how well the cfunddb behaves with long reorganizations. But it would take an immense amount of time. How to efficiently run this test in mainnet is an open question. A possible solution would be to run it against an stressed testnet, which could even give a richer context than mainnet (due to an elevated count of injected proposals and payment requests). Any other ideas?

Coming back to the script output, I was able to find it was failing disconnecting down to the following ranges:

Disconnected down to any block in the range Failed when reconnecting Reason
330-363 363 IsValidPaymentRequest: Could not find parent proposal dd01134fe270e00b79d6685b4f2b49ba19750227fdad0efeb4b99f2fc1c100d6 for payment request 39c8d0c451bf1b52bce3d60f022f53541d6a51ce4abffa1567c514baf6ab9de5 CProposal(hash=dd01134fe270e00b79d6685b4f2b49ba19750227fdad0efeb4b99f2fc1c100d6, nVersion=2, nAmount=10.000000, available=10.000000, nFee=0.000100, address=mtVZbCiSuBW7pE7zUeFTPscTE1dZd616t1, nDeadline=100000, nVotesYes=0, nVotesNo=0, nVotingCycle=2, fState=pending, strDZeel=test, blockhash=0000000000)
364-419 426 CheckBlock() : cant find payment request block 0000000000000000000000000000000000000000000000000000000000000000
511-579 579 IsValidPaymentRequest: Could not find parent proposal 5ca639ac2c0da9a47cdfd40a59f2c2ccd2d29a07e969c95131e33cb0ccba5b36 for payment request 860e07e6a36f16f53579cf96ebc9f37bc2841905c055703ebc3e04a3d3f8a0be CProposal(hash=5ca639ac2c0da9a47cdfd40a59f2c2ccd2d29a07e969c95131e33cb0ccba5b36, nVersion=2, nAmount=1.000000, available=1.000000, nFee=0.000100, address=mu39oWSRd1TKa7zsxS52BjHczd4fYwBpuE, nDeadline=100, nVotesYes=0, nVotesNo=0, nVotingCycle=3, fState=pending, strDZeel=test, blockhash=0000000000)
580-629 636 CheckBlock() : cant find payment request block 0000000000000000000000000000000000000000000000000000000000000000

In devnet, voting cycles last 30 blocks. Blocks cycle from 0 to 29 as in height%30 to determine the position inside of a cycle. The cycle number is determined by int(height/30). Payouts happen in the 7th block of a voting cycle after a payment request has been accepted.

Let's see when there's been votes in the chain:

Entry Vote When
Proposal 1 Yes 303-329
Payment request 1 Yes 385-389
Payment request 1 Yes 396-419
Proposal 2 Yes 486-509
Payment request 2 Yes 610-629

Having a closer look at what happened in the critical blocks:

Height What
329 Proposal 1 is accepted
330 Nothing of interest in the block, voting cycle 11, first block with proposal 1 accepted
363 Payment request 1 is created
364 Nothing of interest besides being the first block of payment request 1
419 Last block of the voting cycle 13, payment request 1 is accepted, proposal 1 expires
426 Payment request 1
509 Proposal 2 is accepted
511 Nothing of interest in the block, voting cycle 17
579 Payment request 2 is created
580 Nothing of interest besides being the first block of payment request 2
629 Last block of the voting cycle 20, payment request 2 is accepted
636 Payout of payment request 2

363 and 579 are both seeing the creation of new payment requests. The creation fails because the parent proposal is not accepted. 426 and 636 see the payouts of the payment requests. Those fail because the node can't validate if the block when the payment request was accepted is in the main chain.

Why?

When we disconnect a block, the state of all the entries which had an update in that block is reseted. This is a wrong design of the cfunddb, because it assumes the entry state will be correctly calculated in the next reorganization, which does not happen all the time.

For example, when we disconnect 419, proposal 1 and payment request 1 will transition like this:

Proposal 1:

  • State: 3 (expired) -> 0 (nil)
  • Blockhash: 0x6c504bb8ae6a80bc7b118450dd40e52976951701684cdf86345973faf27263dd -> 0x0

Payment request 1:

  • State: 1 (accepted) -> 0 (nil)
  • Blockhash: 0x6c504bb8ae6a80bc7b118450dd40e52976951701684cdf86345973faf27263dd -> 0x0

Now we can stop disconnecting and reconnect 419 and higher blocks, or keep disconnecting lower blocks to reconnect them later. Whatever we do, the votes in the ranges 385-389 and 396-419 won't be counted, because the parent proposal has not the accepted state anymore. If the votes are not counted, the payment request is never accepted, the block hash is never set again and the payout is rejected.

This situation happens unless we reorganise lower than 363. Then we find a different situation when we reconnect 363. We will see an error when the payment request is created, because the proposal is not in an accepted state. For this we would need reorganise lower than 330, so 329 is reconnected and proposal 1 recovers its accepted state.

I have an idea on how to fix this, but would need every wallet to reindex/resync.

I'll leave it here waiting for feedback from others.

@aguycalled
Copy link
Member Author

aguycalled commented Nov 20, 2019

I've committed a fix in 29f404d for the previously described issue.

This will require every node to reindex the first time it's opened. Verified with the aforementioned script, verifychain now passes for partial runs.

With the new patch, the whole history of states is stored in a map. Every time the state changes it is stored and associated with the hash of the black where the transition happened. When an entry is reorganised the state associated with the hash of the disconnected block is erased. The new state will be that one associated with the block with higher height part of the active chain. This completely substitutes the previous reorganisation method.

@navbuilder
Copy link

A new build of 29f404d has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@mxaddict
Copy link
Contributor

mxaddict commented Nov 21, 2019

This PR is failing the test_navcoin binary with:

../../src/test/cfunddb_tests.cpp(431): error: in "coins_tests/cfunddb_state": check prequest == it.second has failed

@aguycalled
Copy link
Member Author

aguycalled commented Nov 21, 2019

It is fixed in 2eee7d5 @mxaddict

@navbuilder
Copy link

A new build of 2eee7d5 has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@mxaddict
Copy link
Contributor

@aguycalled the cfunddb-fork-reorg-* tests seem to be failing in this build.

@navbuilder
Copy link

A new build of 1bd70c8 has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@navbuilder
Copy link

A new build of 475cf7b has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@proletesseract
Copy link
Member

compiles, running tests. Will review the diff in the morning.

@proletesseract
Copy link
Member

RPC test suite passes, except getting some error with it not being able to find the file stakeimmaturebalance.py which definitely exists in the file system and has the same permissions as the other files. Travis passes, so I will move on.

@proletesseract
Copy link
Member

Reindex initiated on OSX both testnet & mainnet

Copy link
Member

@proletesseract proletesseract left a comment

Choose a reason for hiding this comment

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

RPC test suite reviewed.

@@ -16,6 +16,7 @@ class CfundForkReorgProposal(NavCoinTestFramework):
def __init__(self):
super().__init__()
self.setup_clean_chain = True
self.node_args = [['-debug=dao'], ['-debug=dao']]
Copy link
Member

Choose a reason for hiding this comment

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

Should this node initialisation done the same way as it is done in cfund-fork-reorg-preq.py consistency?

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -96,7 +97,7 @@ def run_test(self):
assert_equal(self.nodes[0].getblock(self.nodes[0].getproposal(proposalHash0)["blockHash"]), self.nodes[1].getblock(self.nodes[1].getproposal(proposalHash0)["blockHash"]))
assert_equal(self.nodes[0].getproposal(proposalHash0), self.nodes[1].getproposal(proposalHash0))

# End cycle 2
# End cycle 2
Copy link
Member

Choose a reason for hiding this comment

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

lots of whitespace diffs, i wonder if we should commit some code linter, or auto formatter config to the repo to help make this more consistent?

Copy link
Member Author

Choose a reason for hiding this comment

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

sure

@@ -169,36 +167,30 @@ def run_test(self):
for x in range(self.num_nodes):
assert(self.nodes[x].getbestblockhash() == bestBlockHash)
assert(self.nodes[x].getpaymentrequest(paymentReq)["state"] == 1)
assert(self.nodes[x].getpaymentrequest(paymentReq)["paidOnBlock"] == "0000000000000000000000000000000000000000000000000000000000000000")
assert(self.nodes[x].getpaymentrequest(paymentReq)["stateChangedOnBlock"] != "0000000000000000000000000000000000000000000000000000000000000000")
Copy link
Member

Choose a reason for hiding this comment

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

why has this assertion been inverted?

Copy link
Member Author

Choose a reason for hiding this comment

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

paidOnBlock does not exist anymore, but stateChangedOnBlock is used combined with state==6 to show in which block a payment request has been paid. line 172 checks the payment request is not null


# disconnect the nodes and generate the payout on each node
url = urllib.parse.urlparse(self.nodes[1].url)
self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))

time.sleep(1)

while self.nodes[0].getpaymentrequest(paymentReq)["paidOnBlock"] == "0000000000000000000000000000000000000000000000000000000000000000":
while self.nodes[0].getpaymentrequest(paymentReq)["state"] == 6:
Copy link
Member

Choose a reason for hiding this comment

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

isn't state 6 the final state of paid? Or will it move from this to something else eventually? The diff says the while condition was previously paidonblock == "000.." which i thought meant loop until it has been paid, but now the while runs until the state is no longer paid? I must be misinterpreting this, the test passes.

Copy link
Member Author

Choose a reason for hiding this comment

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

d3e786f

$ qa/rpc-tests/cfund-paymentrequest-payout.py 
Initializing test directory /var/folders/qh/7_l8lmqx2sb5ncxgtzzyb51r0000gn/T/testfn5g4cou/27872
Stopping nodes
Cleaning up
Tests successful

@@ -150,7 +151,7 @@ def run_test(self):
self.nodes[0].paymentrequestvote(paymentrequestid0, "remove")

assert(self.nodes[0].getpaymentrequest(paymentrequestid0)["state"] == 0)
assert(self.nodes[0].getpaymentrequest(paymentrequestid0)["status"] == "accepted waiting for end of voting period")
assert_equal(self.nodes[0].getpaymentrequest(paymentrequestid0)["status"], "accepted waiting for end of voting period")
Copy link
Member

Choose a reason for hiding this comment

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

any benefit changing from assert with the string comparison to assert_equal? or just for consistency?

Copy link
Member Author

Choose a reason for hiding this comment

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

just for debug reasons


self.sync_all()

assert_equal(self.nodes[0].getbestblockhash(), self.nodes[1].getbestblockhash())
Copy link
Member

Choose a reason for hiding this comment

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

should we again check that the cfundstatehash matches on each node after they are reconnected? or is it implied they will match because their bestblockhash is the same?

Copy link
Member Author

Choose a reason for hiding this comment

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

7ffee61

$ qa/rpc-tests/cfunddb-statehash.py 
Initializing test directory /var/folders/qh/7_l8lmqx2sb5ncxgtzzyb51r0000gn/T/testivmhhxdf/28317
Stopping nodes
Cleaning up
Tests successful

Copy link
Member

@proletesseract proletesseract left a comment

Choose a reason for hiding this comment

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

some more review added

{
if (!it.second.IsNull())
{
writer << it.second;
Copy link
Member

Choose a reason for hiding this comment

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

Would it be enough to only concatenate the proposal hashes and payment request hashes here since we can already assume those are hashes of the contents of the objects? Or should we be completely verbose and concatenate the whole object like this to be sure? What was the benchmarking results?

Copy link
Member Author

Choose a reason for hiding this comment

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

the proposal and payment hashes are the hash of the transaction where they were created and do not change with the objects, hence we need to serialize and hash them

@@ -310,7 +310,7 @@ struct CCacheEntry
typedef CCacheEntry<CCoins> CCoinsCacheEntry;
typedef boost::unordered_map<uint256, CCoinsCacheEntry, SaltedTxidHasher> CCoinsMap;
typedef std::map<uint256, CProposal> CProposalMap;
typedef boost::unordered_map<uint256, CPaymentRequest, SaltedTxidHasher> CPaymentRequestMap;
typedef std::map<uint256, CPaymentRequest> CPaymentRequestMap;
Copy link
Member

Choose a reason for hiding this comment

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

what is SaltedTxidHasher and why is it removed?

Copy link
Member Author

Choose a reason for hiding this comment

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

https://en.cppreference.com/w/cpp/container/unordered_map

what i would say here, is that in std::map the order is guaranteed while boost::unordered_map does not guarantee it. guaranteed order is needed for cfunddbstate hash consistency. SaltedTxidHasher is removed because now we use std::map

@@ -221,28 +221,95 @@ bool CFund::IsValidPaymentRequest(CTransaction tx, CCoinsViewCache& coins, int n

}

flags CFund::CPaymentRequest::GetLastState() const {
Copy link
Member

Choose a reason for hiding this comment

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

As i understand it we're storing the block height of each state change into a <blockhash,state> map against the payment request (and proposal) now correct? How was this done previously? Was it not needed? Did we just kept the last state and the last blockhash?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, we store a map of block hash and states (the whole state history, so its easy to roll back).
before we just stored the last state and blockhash, which was the main source of issues related to reorganizations (how to recover previous state)

if (fState == ACCEPTED && mapBlockIndex.count(blockhash) > 0) {
CBlockIndex* pBlockIndex = mapBlockIndex[blockhash];
ret.pushKV("expiresOn", pBlockIndex->GetBlockTime() + (uint64_t)nDeadline);
if ((fState == ACCEPTED || fState == PAID) && pblockindex) {
Copy link
Member

Choose a reason for hiding this comment

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

won't pblockindex always evaluate true unless the proposal has not got any state at all? Is that what you're supposed to be checking in this condition? Or should we be using GetLastStateBlockIndexForState() to check a particular state has been correctly achieved?

Copy link
Member Author

Choose a reason for hiding this comment

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

it's true that (fState == ACCEPTED || fState == PAID) can't give us a null pointer in pblockindex, but i think the check does not hurt for sanity

@@ -767,94 +887,97 @@ void CFund::CFundStep(const CValidationState& state, CBlockIndex *pindexNew, con

CBlockIndex* pblockindex = mapBlockIndex[prequest->txblockhash];

CProposal proposal;

if (!view.GetProposal(prequest->proposalhash, proposal))
Copy link
Member

Choose a reason for hiding this comment

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

why don't we need this check anymore?

Copy link
Member Author

Choose a reason for hiding this comment

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

CFundStep has been rewritten a bit

if((pindexNew->nHeight + 1) % Params().GetConsensus().nBlocksPerVotingCycle == 0)
CProposal proposal;

if (!view.GetProposal(prequest->proposalhash, proposal))
Copy link
Member

Choose a reason for hiding this comment

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

i can see it's moved here. what was the motive of moving it here? so we get the logging?

Copy link
Member Author

Choose a reason for hiding this comment

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

CFundStep has been rewritten a bit, i'm not sure if this check would make more sense earlier. it's less likely a payment request has no parent proposal than a payment request being out of chain (previous checks)

CProposal tmp;
CProposal oldproposal = CProposal();

if (fLog)
Copy link
Member

Choose a reason for hiding this comment

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

why was this also moved further down?

Copy link
Member Author

Choose a reason for hiding this comment

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

CFundStep has been rewritten a bit to accomodate the changes of this pull request. this moved some parts of the code

@navbuilder
Copy link

A new build of f630567 has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@navbuilder
Copy link

A new build of 561339d has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

@proletesseract
Copy link
Member

The RPC tests are failing in travis now. For me, either cfund-fork-reorg-preq.py or getstakereport.py seem to be non-deterministically timing out

Copy link
Member

@proletesseract proletesseract left a comment

Choose a reason for hiding this comment

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

all reviewed except diff on main.cpp

return nAmount == b.nAmount
&& fState == b.fState
&& thisMapState == bMapState
&& hash == b.hash
Copy link
Member

Choose a reason for hiding this comment

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

Just confirming how these operator overloads work. In this context hash is the hash property of the CPaymentRequest on the left side of the operator and b.hash is the hash property of the CPaymentRequest on the right side of the operator? Or should we be explicitly defining both objects in parenthesis as lhs and rhs like in the spec?

inline bool operator==(const X& lhs, const X& rhs){ /* do actual comparison */ }
inline bool operator!=(const X& lhs, const X& rhs){ return !(lhs == rhs); }

https://en.cppreference.com/w/cpp/language/operators

Either way is fine if it works, i just don't want to make assumptions on my side about how this functions exactly.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes thats how it works

ui->labelPrequestPaymentHashTitle->setVisible(false);
ui->labelPrequestPaymentHash->setVisible(false);
}
ui->labelPrequestPaymentHashTitle->setVisible(false);
Copy link
Member

Choose a reason for hiding this comment

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

should this still be wrapped in the if condition?

Copy link
Member Author

Choose a reason for hiding this comment

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

paymenthash does not exist anymore, so it makes sense to hide it always

src/rpc/blockchain.cpp Show resolved Hide resolved
src/wallet/rpcwallet.cpp Show resolved Hide resolved
alex v added 2 commits December 10, 2019 11:10
@navbuilder
Copy link

A new build of 3b9d623 has completed succesfully!
Binaries available at https://build.nav.community/binaries/verifychain-view

Copy link
Contributor

@chasingkirkjufell chasingkirkjufell left a comment

Choose a reason for hiding this comment

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

did stress testing with the script https://gist.github.com/aguycalled/13f362c29ea9c38624e8dd4593bc37f8 on ubuntu 18.10 and 19.04 for a week and no problem was found besides some scripting issues.

@@ -829,9 +829,9 @@ void CFund::CFundStep(const CValidationState& state, CBlockIndex *pindexNew, con
CProposalModifier proposal = view.ModifyProposal(it->first);
proposal->nVotesYes = it->second.first;
proposal->nVotesNo = it->second.second;
proposal->fDirty = true;
Copy link
Member

Choose a reason for hiding this comment

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

what is the purpose of moving this assignment to inside the if statements?

@@ -3911,6 +3881,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
int64_t nTime3;
int64_t nTime4;
LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
uint256 statehash;
{
Copy link
Member

Choose a reason for hiding this comment

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

as a bit of a side note, what is the purpose of these curly braces which don't appear to be enclosing any conditional, loop or function definition? Is it some notation for a constructor or some way of encapsulating the contents?

Copy link
Contributor

Choose a reason for hiding this comment

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

@proletesseract I think that is for scoping, IIRC any variables declared in the curlies will be destroyed once the code passes the closing curly.

@mxaddict
Copy link
Contributor

mxaddict commented Dec 11, 2019

I'm still running the scenarios:

  • verifychain 4 0
  • verifychain 4 10
  • verifychain 4 100
  • verifychain 4 1000
  • verifychain 4 10000
  • verifychain 4 100000
  • verifychain 4 1000000

Ubuntu 19.10 self compiled using depends dir.

@mxaddict
Copy link
Contributor

I've also verified that running this branch on an old datadir forces a reindex.

Copy link
Contributor

@mxaddict mxaddict left a comment

Choose a reason for hiding this comment

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

I think we need a linter like @proletesseract suggested, I'm not sure how to go about implementing it though.

@aguycalled aguycalled merged commit 049978e into navcoin:master Dec 11, 2019
@proletesseract proletesseract mentioned this pull request Dec 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

verifychain fails
5 participants