Skip to content

Commit

Permalink
Take anchor block deeper to avoid "Anchor too new" error (#531)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bushstar authored Jun 23, 2021
1 parent 241558d commit 893217c
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 21 deletions.
4 changes: 4 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class CMainParams : public CChainParams {
consensus.mn.anchoringFrequency = 15;

consensus.mn.anchoringTimeDepth = 3 * 60 * 60; // 3 hours
consensus.mn.anchoringAdditionalTimeDepth = 1 * 60 * 60; // 1 hour
consensus.mn.anchoringTeamChange = 120; // Number of blocks

consensus.token.creationFee = 100 * COIN;
Expand Down Expand Up @@ -387,6 +388,7 @@ class CTestNetParams : public CChainParams {
consensus.mn.anchoringFrequency = 15;

consensus.mn.anchoringTimeDepth = 3 * 60 * 60; // 3 hours
consensus.mn.anchoringAdditionalTimeDepth = 1 * 60 * 60; // 1 hour
consensus.mn.anchoringTeamChange = 120; // Number of blocks

consensus.token.creationFee = 100 * COIN;
Expand Down Expand Up @@ -566,6 +568,7 @@ class CDevNetParams : public CChainParams {
consensus.mn.anchoringFrequency = 15;

consensus.mn.anchoringTimeDepth = 3 * 60 * 60; // 3 hours
consensus.mn.anchoringAdditionalTimeDepth = 1 * 60 * 60; // 1 hour
consensus.mn.anchoringTeamChange = 120; // Number of blocks

consensus.token.creationFee = 100 * COIN;
Expand Down Expand Up @@ -739,6 +742,7 @@ class CRegTestParams : public CChainParams {
consensus.mn.anchoringFrequency = 15;

consensus.mn.anchoringTimeDepth = 3 * 60 * 60;
consensus.mn.anchoringAdditionalTimeDepth = 15 * 60; // 15 minutes
consensus.mn.anchoringTeamChange = 15; // Number of blocks

consensus.token.creationFee = 1 * COIN;
Expand Down
1 change: 1 addition & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ struct Params {
int anchoringFrequency; // create every Nth block

int anchoringTimeDepth; // Min age of anchored blocks
int anchoringAdditionalTimeDepth; // Additional min age of anchored blocks
int anchoringTeamChange; // How many blocks before team is changed
};
MnParams mn;
Expand Down
17 changes: 15 additions & 2 deletions src/masternodes/anchors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -865,11 +865,24 @@ bool ContextualValidateAnchor(const CAnchorData &anchor, CBlockIndex& anchorBloc
__func__, HexStr(*prefix), HexStr(hashPrefix), anchorCreationHeight);
}

// Recreate the creation height of the anchor
// Get start anchor height
int anchorHeight = static_cast<int>(anchorCreationHeight) - Params().GetConsensus().mn.anchoringFrequency;
while (anchorHeight > 0 && ::ChainActive()[anchorHeight]->nTime + Params().GetConsensus().mn.anchoringTimeDepth > anchorCreationBlock->nTime) {

// Recreate the creation height of the anchor
int64_t timeDepth = Params().GetConsensus().mn.anchoringTimeDepth;
while (anchorHeight > 0 && ::ChainActive()[anchorHeight]->nTime + timeDepth > anchorCreationBlock->nTime) {
--anchorHeight;
}

// Recreate deeper anchor depth
if (anchorCreationHeight >= Params().GetConsensus().FortCanningHeight) {
timeDepth += Params().GetConsensus().mn.anchoringAdditionalTimeDepth;
while (anchorHeight > 0 && ::ChainActive()[anchorHeight]->nTime + timeDepth > anchorCreationBlock->nTime) {
--anchorHeight;
}
}

// Wind back further by anchoring frequency
while (anchorHeight > 0 && anchorHeight % Params().GetConsensus().mn.anchoringFrequency != 0) {
--anchorHeight;
}
Expand Down
12 changes: 11 additions & 1 deletion src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4735,13 +4735,23 @@ void ProcessAuthsIfTipChanged(CBlockIndex const * oldTip, CBlockIndex const * ti
continue;
}

// Get start anchor height
int anchorHeight = static_cast<int>(pindex->height) - consensus.mn.anchoringFrequency;

// Get anchor block from specified time depth
while (anchorHeight > 0 && ::ChainActive()[anchorHeight]->nTime + consensus.mn.anchoringTimeDepth > pindex->nTime) {
int64_t timeDepth = consensus.mn.anchoringTimeDepth;
while (anchorHeight > 0 && ::ChainActive()[anchorHeight]->nTime + timeDepth > pindex->nTime) {
--anchorHeight;
}

// Select a block further back to avoid Anchor too new error.
if (pindex->height >= consensus.FortCanningHeight) {
timeDepth += consensus.mn.anchoringAdditionalTimeDepth;
while (anchorHeight > 0 && ::ChainActive()[anchorHeight]->nTime + timeDepth > pindex->nTime) {
--anchorHeight;
}
}

// Rollback to height consistent with anchoringFrequency
while (anchorHeight > 0 && anchorHeight % consensus.mn.anchoringFrequency != 0) {
--anchorHeight;
Expand Down
16 changes: 9 additions & 7 deletions test/functional/feature_anchor_rewards.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class AnchorRewardsTest (DefiTestFramework):
def set_test_params(self):
self.num_nodes = 3
self.extra_args = [
[ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1"],
[ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1"],
[ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1"],
[ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"],
[ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"],
[ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"],
]
self.setup_clean_chain = True

Expand Down Expand Up @@ -88,20 +88,22 @@ def run_test(self):
anchorFrequency = 15

# Create multiple active MNs
self.initmasternodesforanchors(12, 2 * anchorFrequency)
self.initmasternodesforanchors(13, 1 * anchorFrequency)

wait_until(lambda: len(self.nodes[0].getanchorteams()['auth']) == 3 and len(self.nodes[0].getanchorteams()['confirm']) == 3, timeout=10)

# Mo anchors created yet as we need three hours depth in chain
assert_equal(len(self.nodes[0].spv_listanchorauths()), 0)

# Mine forward 3 hours, from 12 hours ago, 15 blocks an hour
# Mine forward 4 hours, from 12 hours ago, 5 blocks an hour
self.rotateandgenerate(3, 12, 5)

# Mine up to block 60
self.mine_diff(60)

# Anchor data
print(self.nodes[0].spv_listanchorauths())
print(self.nodes[0].getblockcount())
wait_until(lambda: len(self.nodes[0].spv_listanchorauths()) > 0 and self.nodes[0].spv_listanchorauths()[0]['signers'] == 3, timeout=10)

auth = self.nodes[0].spv_listanchorauths()
Expand Down Expand Up @@ -355,7 +357,7 @@ def run_test(self):
self.rotateandgenerate(6, 9, 5)

self.sync_all()
wait_until(lambda: self.authsquorum(75), timeout=10)
wait_until(lambda: self.authsquorum(60), timeout=10)

rewardAddress2 = self.nodes[0].getnewaddress("", "legacy")
txAnc2 = self.nodes[0].spv_createanchor([{
Expand All @@ -373,7 +375,7 @@ def run_test(self):
self.rotateandgenerate(3, 3, 15)

self.sync_all()
wait_until(lambda: self.authsquorum(75), timeout=10)
wait_until(lambda: self.authsquorum(60), timeout=10)

# for rollback. HERE, to deny cofirmations for node2
disconnect_nodes(self.nodes[1], 2)
Expand Down
23 changes: 12 additions & 11 deletions test/functional/feature_anchorauths_pruning.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class AnchorsAuthsPruningTest (DefiTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.extra_args = [
[ "-dummypos=1", "-spv=1", '-amkheight=0', "-dakotaheight=1"],
[ "-dummypos=1", "-spv=1", '-amkheight=0', "-dakotaheight=1", "-fortcanningheight=1"],
]
self.setup_clean_chain = True

Expand All @@ -35,7 +35,7 @@ def run_test(self):
assert_equal(len(self.nodes[0].spv_listanchors()), 0)

# Checking starting set
assert_equal(len(self.nodes[0].spv_listanchorauths()), 3) # 15,30,45
assert_equal(len(self.nodes[0].spv_listanchorauths()), 2) # 15,30

# Setting anchor
self.nodes[0].spv_setlastheight(1)
Expand All @@ -46,25 +46,26 @@ def run_test(self):
'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP"}],
"mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu")

assert_equal(txinfo['defiHash'], self.nodes[0].getblockhash(45))
assert_equal(txinfo['defiHeight'], 45)
assert_equal(txinfo['defiHash'], self.nodes[0].getblockhash(30))
assert_equal(txinfo['defiHeight'], 30)

# Still the same
assert_equal(len(self.nodes[0].spv_listanchorauths()), 3) # 15,30,45
assert_equal(len(self.nodes[0].spv_listanchorauths()), 2) # 15,30
self.genmocktime(int(time.time() + (12 * 60 * 60)), 6)

# Couple of auths added
assert_equal(len(self.nodes[0].spv_listanchorauths()), 5) # + 60,75
assert_equal(len(self.nodes[0].spv_listanchorauths()), 4) # + 45,60

# Nothing should change
self.nodes[0].spv_setlastheight(5)
assert_equal(len(self.nodes[0].spv_listanchorauths()), 5) # 15,30,45,60,75
assert_equal(len(self.nodes[0].spv_listanchorauths()), 4) # 15,30,45,60

# Pruning should accure
# Pruning should occur
self.nodes[0].spv_setlastheight(6)
auths = self.nodes[0].spv_listanchorauths() # 60,75 only
auths = self.nodes[0].spv_listanchorauths() # 45,60 only
assert_equal(len(auths), 2)
assert_equal(auths[0]['blockHeight'], 75)
assert_equal(auths[1]['blockHeight'], 60)
assert_equal(auths[0]['blockHeight'], 60)
assert_equal(auths[1]['blockHeight'], 45)

if __name__ == '__main__':
AnchorsAuthsPruningTest ().main ()

0 comments on commit 893217c

Please sign in to comment.