Mining algorithm

Mining in our system requires two real-time data fields, lastTokenId and lastTokenHash. The lastTokenId represents the total number of items mined in this collection, and the lastTokenHash refers to the hash recorded during the last mining event. The calculation for these is as follows:

bytes32 hash = keccak256(abi.encodePacked(msg.sender, collection.lastHash, nonce));
bytes32 newhash = keccak256(abi.encodePacked(hash, block.timestamp));

To compute the current mining difficulty based on the latest tokenId, our system evaluates the 'generation' of the token. The difficulty level increases with the number of tens in the exponential growth of the tokenId. Here's how we determine the generation of a token:

function generationOf(_tokenId: number): number {
    return Math.floor(Math.log10(_tokenId));
}

Once we get the token generation, then calculate the Difficulty:

function getDifficulty(tokenId: number, baseDifficulty: bigint, difficultyRamp: number): bigint {
    if (tokenId == 0) {
        return baseDifficulty
    }
    if (difficultyRamp == 0) {
        return baseDifficulty
    }
    const generation = generationOf(tokenId)

    return baseDifficulty / BigInt(Math.pow(difficultyRamp, generation))
}

After determining the Difficulty, the mining process is successful once a nonce is found that, when hashed, is less than this difficulty threshold. The hash is computed using the user's wallet address, the latest hash, and the nonce, as illustrated in the initial hashing process. This approach ensures a dynamic and scalable mining difficulty that adapts as more tokens are generated, thereby maintaining the system's balance and fairness.

const hash = ethers.solidityPackedKeccak256(["address","bytes32","uint"],[address,prev,nonce])
function compare(address: string, prev_hash: string, nonce: number, difficulty: bigint) {
    const hash = BigInt(Hash(address, prev_hash, nonce));
    return hash < difficulty;
}

Last updated