Skip to content

Commit

Permalink
Merge pull request #13 from ProjectIxian/development
Browse files Browse the repository at this point in the history
xdc-0.9.3f
  • Loading branch information
IxiAngel authored Jan 30, 2025
2 parents c4d20a1 + b12a99e commit 0c96854
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 52 deletions.
60 changes: 43 additions & 17 deletions IxianDLT/Block/BlockChain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class BlockChain
private int blockCount = 0;

private ulong cachedRequiredSignerDifficultyBlockNum = 0;
private int cachedRequiredSignerDifficultyVersion = 0;
private IxiNumber cachedRequiredSignerDifficulty = 0;

public long Count
Expand Down Expand Up @@ -640,11 +641,16 @@ public int getRequiredConsensusFromStorage(ulong block_num, bool adjusted_to_rat
}
}

public IxiNumber getRequiredSignerDifficulty(ulong blockNum, bool adjustToRatio, long curBlockTimestamp)
public IxiNumber getRequiredSignerDifficulty(ulong blockNum, bool adjustToRatio, int curBlockVersion = 0, long curBlockTimestamp = 0)
{
if (blockNum > lastBlockNum && blockNum % ConsensusConfig.superblockInterval == 0)
{
return calculateRequiredSignerDifficulty(adjustToRatio, lastBlockVersion, curBlockTimestamp);
if (curBlockVersion == 0 || curBlockTimestamp == 0)
{
throw new Exception("Error calculating required signer difficulty, curBlockVersion or curBlockTimestamp is 0.");
}

return calculateRequiredSignerDifficulty(adjustToRatio, curBlockVersion, curBlockTimestamp);
}
else
{
Expand Down Expand Up @@ -700,7 +706,7 @@ public ulong getRequiredSignerBits(ulong blockNum)
}
if (blockNum < lastSuperBlock.blockNum)
{
var sb = getBlock((blockNum / ConsensusConfig.superblockInterval) * ConsensusConfig.superblockInterval);
var sb = getBlock((blockNum / ConsensusConfig.superblockInterval) * ConsensusConfig.superblockInterval, true);
if(sb == null || sb.signerBits == 0)
{
return SignerPowSolution.difficultyToBits(ConsensusConfig.minBlockSignerPowDifficulty);
Expand All @@ -720,6 +726,7 @@ public void clearCachedRequiredSignerDifficulty()
lock (blocks)
{
cachedRequiredSignerDifficultyBlockNum = 0;
cachedRequiredSignerDifficultyVersion = 0;
cachedRequiredSignerDifficulty = 0;
}
}
Expand All @@ -733,6 +740,7 @@ public IxiNumber calculateRequiredSignerDifficulty(bool adjustToRatio, int block
if (blockNum < blockOffset + 1) return ConsensusConfig.minBlockSignerPowDifficulty; // special case for first X blocks - since sigFreeze happens n-5 blocks

if (cachedRequiredSignerDifficultyBlockNum == blockNum
&& cachedRequiredSignerDifficultyVersion == blockVersion
&& cachedRequiredSignerDifficulty != 0)
{
if (adjustToRatio)
Expand All @@ -744,13 +752,14 @@ public IxiNumber calculateRequiredSignerDifficulty(bool adjustToRatio, int block
}

IxiNumber newDifficulty;
if (blockVersion < BlockVer.v12)
if (getLastBlockVersion() == BlockVer.v11
|| blockVersion < BlockVer.v12)
{
newDifficulty = calculateRequiredSignerDifficulty_v1(blockVersion);
}
else
{
newDifficulty = calculateRequiredSignerDifficulty_v2(curBlockTimestamp);
newDifficulty = calculateRequiredSignerDifficulty_v2(blockVersion, curBlockTimestamp);
}

// Limit to max *2, /2
Expand All @@ -777,6 +786,7 @@ public IxiNumber calculateRequiredSignerDifficulty(bool adjustToRatio, int block
}

cachedRequiredSignerDifficultyBlockNum = blockNum;
cachedRequiredSignerDifficultyVersion = blockVersion;
cachedRequiredSignerDifficulty = newDifficulty;

if (adjustToRatio)
Expand Down Expand Up @@ -843,7 +853,7 @@ private IxiNumber calculateRequiredSignerDifficulty_v1(int blockVersion)
return newDifficulty;
}

private Block findLastDifficultyChangedSuperBlock(ulong blockNum)
private Block findLastDifficultyChangedSuperBlock(ulong blockNum, int blockVersion)
{
// Make sure that it's a superblock
if (blockNum % ConsensusConfig.superblockInterval != 0)
Expand All @@ -861,32 +871,40 @@ private Block findLastDifficultyChangedSuperBlock(ulong blockNum)
IxiNumber diff = getRequiredSignerDifficulty(sb, false);
while (sb.lastSuperBlockNum != 0)
{
if (diff != getRequiredSignerDifficulty(sb.lastSuperBlockNum, false, Clock.getNetworkTimestamp()))
if (diff != getRequiredSignerDifficulty(sb.lastSuperBlockNum, false))
{
Logging.warn("DAA: Found diff block #{0}", sb.blockNum);
Logging.trace("DAA: Found diff block #{0}", sb.blockNum);
return sb;
}
if (blockVersion <= BlockVer.v12)
{
// regression fix, which searched only last 11000 blocks
if (blockNum - sb.blockNum == 11000)
{
return sb;
}
}
sb = getSuperBlock(sb.lastSuperBlockNum);
}
return sb;
}

// Time-based DAA
private IxiNumber calculateRequiredSignerDifficulty_v2(long curBlockTimestamp)
private IxiNumber calculateRequiredSignerDifficulty_v2(int blockVersion, long curBlockTimestamp)
{
ulong blockNum = getLastBlockNum() + 1;
Logging.trace("DAA: Calculating diff for block #{0}", blockNum);
Block lastDiffChangeSuperblock = findLastDifficultyChangedSuperBlock(blockNum);
Logging.info("DAA: Calculating diff for block #{0}", blockNum);
Block lastDiffChangeSuperblock = findLastDifficultyChangedSuperBlock(blockNum, blockVersion);
if (curBlockTimestamp - lastDiffChangeSuperblock.timestamp < ConsensusConfig.difficultyAdjustmentTimeInterval)
{
Logging.trace("DAA: Not enough time has passed to do the calculation, using same difficulty as on previous block.");
Logging.info("DAA: Not enough time has passed to do the calculation, using same difficulty as on previous block.");
// Edge case for initial blocks
if (blockNum == ConsensusConfig.superblockInterval)
{
return getRequiredSignerDifficulty(1, false, Clock.getNetworkTimestamp());
return getRequiredSignerDifficulty(1, false);
}

return getRequiredSignerDifficulty(blockNum - ConsensusConfig.superblockInterval, false, Clock.getNetworkTimestamp());
return getRequiredSignerDifficulty(blockNum - ConsensusConfig.superblockInterval, false);
}

ulong blockOffset = 7;
Expand All @@ -909,6 +927,7 @@ private IxiNumber calculateRequiredSignerDifficulty_v2(long curBlockTimestamp)
{
break;
}
Logging.trace("DAA: Using block #{0} with diff {1} for DAA calculation", consensusBlockNum, blockTotalSignerDifficulty);

// Smooth-out difficulty spikes
if (maxSingleBlockDifficulty != null
Expand All @@ -920,7 +939,7 @@ private IxiNumber calculateRequiredSignerDifficulty_v2(long curBlockTimestamp)
blockCount++;
}

Logging.trace("DAA: Used {0} blocks for DAA calculation, expected {1}", blockCount, blocksToUseForDifficultyCalculation);
Logging.info("DAA: Used {0} blocks for DAA calculation, expected {1}", blockCount, blocksToUseForDifficultyCalculation);
if (lastDiffChangeSuperblock.blockNum != 1 && blockCount != blocksToUseForDifficultyCalculation)
{
if ((blockNum - blockOffset) != blockCount)
Expand Down Expand Up @@ -1397,6 +1416,13 @@ public bool revertLastBlock(bool blacklist = true, bool legacy_dual_revert = tru
Node.stop();
return false;
}
clearCachedRequiredSignerDifficulty();

var itemsToRemove = blockHashCache.FindAll(x => x.Value.blockNum == block_num_to_revert);
foreach (var item in itemsToRemove)
{
blockHashCache.Remove(item);
}
}

return true;
Expand Down Expand Up @@ -1462,15 +1488,15 @@ public void decreaseSolvedBlocksCount()
}
}

public IxiNumber getMinSignerPowDifficulty(ulong blockNum, long curBlockTimestamp)
public IxiNumber getMinSignerPowDifficulty(ulong blockNum, int curBlockVersion, long curBlockTimestamp)
{
if (Count < 8)
{
return ConsensusConfig.minBlockSignerPowDifficulty;
}
uint minDiffRatio = 7;
ulong frozenSignatureCount = (ulong)ConsensusConfig.maximumBlockSigners;
var difficulty = getRequiredSignerDifficulty(blockNum, true, curBlockTimestamp) / (frozenSignatureCount * minDiffRatio);
var difficulty = getRequiredSignerDifficulty(blockNum, true, curBlockVersion, curBlockTimestamp) / (frozenSignatureCount * minDiffRatio);
if (difficulty < ConsensusConfig.minBlockSignerPowDifficulty)
{
difficulty = ConsensusConfig.minBlockSignerPowDifficulty;
Expand Down
54 changes: 28 additions & 26 deletions IxianDLT/Block/BlockProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ class BlockProcessor

int blockGenerationInterval = ConsensusConfig.blockGenerationInterval;

long averageBlockGenerationInterval = ConsensusConfig.blockGenerationInterval;

public bool firstBlockAfterSync;

private SortedList<ulong, long> fetchingTxForBlocks = new SortedList<ulong, long>();
Expand Down Expand Up @@ -169,7 +167,8 @@ public void onUpdate()
int block_version = Node.blockChain.getLastBlockVersion();

if (block_version < Config.maxBlockVersionToGenerate
&& (last_block_num + 1) % ConsensusConfig.superblockInterval == 0)
&& (last_block_num + 1) % ConsensusConfig.superblockInterval == 0
&& (IxianHandler.isTestNet || last_block_num >= Config.upgradeBlockHeight))
{
block_version = Config.maxBlockVersionToGenerate;
}
Expand Down Expand Up @@ -229,7 +228,9 @@ public void onUpdate()
//Logging.info(String.Format("Waiting for {0} to generate the next block #{1}. offset {2}", Node.blockChain.getLastElectedNodePubKey(getElectedNodeOffset()), Node.blockChain.getLastBlockNum()+1, getElectedNodeOffset()));
if (generateNextBlock)
{
if (lastUpgradeTry > 0 && Clock.getTimestamp() - lastUpgradeTry < blockGenerationInterval * 120)
if (!Config.forceUpgradeAtBlockHeight
&& lastUpgradeTry > 0
&& Clock.getTimestamp() - lastUpgradeTry < blockGenerationInterval * 120)
{
block_version = Node.blockChain.getLastBlockVersion();
}
Expand Down Expand Up @@ -767,15 +768,19 @@ public void onBlockReceived(Block b, RemoteEndpoint endpoint = null)

public BlockVerifyStatus verifyBlockBasic(Block b, bool verify_sig = true, RemoteEndpoint endpoint = null)
{
// TODO omega remove bottom if section after v12 upgrade
if (!IxianHandler.isTestNet)
{
// upgrade to v12 at exactly block 4650000
if (b.blockNum < 4650000 && b.version >= BlockVer.v12)
// prevent upgrade under a certain block height
if (b.blockNum < Config.upgradeBlockHeight
&& b.version >= Config.maxBlockVersionToGenerate)
{
return BlockVerifyStatus.Invalid;
}
if (b.blockNum >= 4650000 && b.version < BlockVer.v12)

// force upgrade if configured
if (Config.forceUpgradeAtBlockHeight
&& b.blockNum >= Config.upgradeBlockHeight
&& b.version < Config.maxBlockVersionToGenerate)
{
return BlockVerifyStatus.Invalid;
}
Expand Down Expand Up @@ -806,10 +811,20 @@ public BlockVerifyStatus verifyBlockBasic(Block b, bool verify_sig = true, Remot
if (b.version >= BlockVer.v7)
{
// if received block's timestamp is lower than previous block's timestamp + 20 seconds
if (b.timestamp < prevBlock.timestamp + ConsensusConfig.minBlockTimeDifference)
if (b.version <= BlockVer.v12)
{
Logging.warn("Received block #{0} with invalid timestamp {1}, expecting at least {2}!", b.blockNum, b.timestamp, prevBlock.timestamp + ConsensusConfig.minBlockTimeDifference);
return BlockVerifyStatus.Invalid;
if (b.timestamp < prevBlock.timestamp + 20)
{
Logging.warn("Received block #{0} with invalid timestamp {1}, expecting at least {2}!", b.blockNum, b.timestamp, prevBlock.timestamp + 20);
return BlockVerifyStatus.Invalid;
}
} else // >= BlockVer.v13
{
if (b.timestamp < prevBlock.timestamp + ConsensusConfig.minBlockTimeDifference)
{
Logging.warn("Received block #{0} with invalid timestamp {1}, expecting at least {2}!", b.blockNum, b.timestamp, prevBlock.timestamp + ConsensusConfig.minBlockTimeDifference);
return BlockVerifyStatus.Invalid;
}
}
// if received block's timestamp is higher than network time + 60 seconds
if (b.timestamp > Clock.getNetworkTimestamp() + ConsensusConfig.maxBlockNetworkTimeDifference)
Expand Down Expand Up @@ -2089,7 +2104,7 @@ private bool handleBlockchainRecoveryMode(Block curBlock, int requiredSignatureC

if (missingSigs > 0)
{
if (totalSignerDifficulty < recoveryRequiredSignerDifficulty + (missingSigs * IxianHandler.getMinSignerPowDifficulty(curBlock.blockNum, curBlock.timestamp)) * ConsensusConfig.blockChainRecoveryMissingSignerMultiplier)
if (totalSignerDifficulty < recoveryRequiredSignerDifficulty + (missingSigs * IxianHandler.getMinSignerPowDifficulty(curBlock.blockNum, curBlock.version, curBlock.timestamp)) * ConsensusConfig.blockChainRecoveryMissingSignerMultiplier)
{
return false;
}
Expand Down Expand Up @@ -2307,19 +2322,6 @@ public bool acceptLocalNewBlock()

// Adjust block generation time to get close to the block generation interval target
Block tmp_prev_block = Node.blockChain.getBlock(current_block.blockNum - 1);
if (tmp_prev_block != null)
{
averageBlockGenerationInterval = (averageBlockGenerationInterval + (current_block.timestamp - tmp_prev_block.timestamp)) / 2;

if (averageBlockGenerationInterval > ConsensusConfig.blockGenerationInterval + 1)
{
blockGenerationInterval = ConsensusConfig.minBlockTimeDifference + 1;
}
else if (averageBlockGenerationInterval + 1 < ConsensusConfig.blockGenerationInterval)
{
blockGenerationInterval = ConsensusConfig.blockGenerationInterval;
}
}

if (Node.miner.searchMode == BlockSearchMode.latestBlock)
{
Expand Down Expand Up @@ -4123,7 +4125,7 @@ public ulong determineHighestNetworkBlockNum()
return netBh;
}

ulong maxBlocksGenerated = (ulong)(Clock.getNetworkTimestamp() - lastBlock.timestamp) / (ulong)ConsensusConfig.minBlockTimeDifference;
ulong maxBlocksGenerated = (ulong)(Clock.getNetworkTimestamp() - lastBlock.timestamp) / (ulong)ConsensusConfig.blockGenerationInterval;
ulong maxBlockHeight = lastBlock.blockNum + maxBlocksGenerated;
if (maxBlockHeight < netBh)
{
Expand Down
6 changes: 4 additions & 2 deletions IxianDLT/Meta/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public static string dataFolderBlocks
public static ulong forceSyncToBlock = 0;

// Read-only values
public static readonly string version = "xdc-0.9.3e"; // DLT Node version
public static readonly string version = "xdc-0.9.3f"; // DLT Node version

public static readonly string checkVersionUrl = "https://www.ixian.io/update.txt";
public static readonly int checkVersionSeconds = 6 * 60 * 60; // 6 hours
Expand Down Expand Up @@ -131,7 +131,9 @@ public static string dataFolderBlocks
// internal
public static bool changePass = false;

public static int maxBlockVersionToGenerate = BlockVer.v12;
public static int maxBlockVersionToGenerate = BlockVer.v13;
public static ulong upgradeBlockHeight = 4695000;
public static bool forceUpgradeAtBlockHeight = true;

/// <summary>
/// Command to execute when a new block is accepted.
Expand Down
4 changes: 2 additions & 2 deletions IxianDLT/Meta/Node.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1168,9 +1168,9 @@ private void devInsertFromJson()
storage.insertBlock(b);
}

public override IxiNumber getMinSignerPowDifficulty(ulong blockNum, long curBlockTimestamp)
public override IxiNumber getMinSignerPowDifficulty(ulong blockNum, int curBlockVersion, long curBlockTimestamp)
{
return blockChain.getMinSignerPowDifficulty(blockNum, curBlockTimestamp);
return blockChain.getMinSignerPowDifficulty(blockNum, curBlockVersion, curBlockTimestamp);
}

public override RegisteredNameRecord getRegName(byte[] name, bool useAbsoluteId = true)
Expand Down
4 changes: 2 additions & 2 deletions IxianDLT/Miner/SignerPowMiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ private void searchForBlock()
return;
}

solvingDifficulty = Node.blockChain.getMinSignerPowDifficulty(IxianHandler.getLastBlockHeight() + 1, Clock.getNetworkTimestamp());
solvingDifficulty = Node.blockChain.getMinSignerPowDifficulty(IxianHandler.getLastBlockHeight() + 1, IxianHandler.getLastBlockVersion(), Clock.getNetworkTimestamp());

if (solvingDifficulty < 0)
{
Expand Down Expand Up @@ -375,7 +375,7 @@ private void sendFoundSolution()
{
if (newSolution.difficulty <= solution.difficulty
&& solution.blockNum + ConsensusConfig.getPlPowBlocksValidity(IxianHandler.getLastBlockVersion()) - 1 > IxianHandler.getHighestKnownNetworkBlockHeight()
&& solution.difficulty > Node.blockChain.getMinSignerPowDifficulty(IxianHandler.getLastBlockHeight() + 1, Clock.getNetworkTimestamp()))
&& solution.difficulty > Node.blockChain.getMinSignerPowDifficulty(IxianHandler.getLastBlockHeight() + 1, IxianHandler.getLastBlockVersion(), Clock.getNetworkTimestamp()))
{
// If the new solution has a lower difficulty than the previously submitted solution and the previously submitted solution is still valid

Expand Down
Loading

0 comments on commit 0c96854

Please sign in to comment.