Forging Algorithm

From ArdorDocs
(Redirected from Forging (f))
Jump to: navigation, search
This page contains changes which are not marked for translation.
Other languages:

Features of the Algorithm

There are two conditions that an account needs to satisfy before it can start forging:

  • The account needs to have an effective balance of at least 1000 ARDR. That is, it needs to have had a balance of 1000 ARDR(or more) over the last 1440 blocks / 24 hours.
This is needed because the forging algorithm depends on the stake of the user.
  • The account needs to have at least one outgoing transaction, also confirmed 1440 times.
The passphrase is the account's private key, a public key is obtained only after at least one outgoing transaction is executed and confirmed. This can be done in several ways, notably by sending 1 ARDR to your own account (or someone else's), by sending a message using the arbitrary message feature or by registering an alias

When these two conditions are met, a 1000 ARDR effective balance and public key published, the account is eligible to forge. Note that forging will stop if the effective balance drops below 1000 ARDR.

The forging algorithm employed by ARDR revolves around two variables: Hit and Target.

Hit

Each forger generates one 'hit' value between 0 and 2^64 - 1 for each new block. While hit is deterministic, it's produced through hashing inputs, so it can be regarded as a uniform random variable.

From the code, hit is defined as:

BigInteger hit = getHit(publicKey, lastBlock);

Two arguments are given to the getHit function: the forger's public key and the previous block. The implementation of this function can be seen below.

private static BigInteger getHit(byte[] publicKey, Block block){
   [...]
   MessageDigest digest = Crypto.sha256();
   digest.update(block.getGenerationSignature());
   byte[] generationSignatureHash = digest.digest(publicKey);
   return new BigInteger(1, new byte[] {generationSignatureHash[7], 
                                        generationSignatureHash[6], 
                                        generationSignatureHash[5], 
                                        generationSignatureHash[4], 
                                        generationSignatureHash[3], 
                                        generationSignatureHash[2], 
                                        generationSignatureHash[1], 
                                        generationSignatureHash[0]});
}

Taken from ardor/ src / java / nxt / Generator.java

Each block has a 64 bytes generationSignature parameter. A forger signs the previous block using its own public key. This same generationSignature is successively hashed using SHA256. The hit value is obtained by taking the first 8 bytes of the resulting hash.

Target

The target is an ever-increasing valor. This is its implementation

BigInteger target = BigInteger.valueOf(lastBlock.getBaseTarget())
                    .multiply(BigInteger.valueOf(effectiveBalance))
                    .multiply(BigInteger.valueOf(elapsedTime));

Taken from nxt / src / java / nxt / Generator.java

In other words, we have that

Target = BaseTarget * EffectiveBalance * TimeSinceLastBlock

Where:

  • BaseTarget
This parameter is the same for everybody. It gets adjusted from block to block to obtain, roughly, a generation time between blocks of 60s. If two successive blocks get generated too quickly, the new BaseTarget gets reduced. If instead, they take too long, the value gets increased. This adjustment is capped, it can go up at most twice as much (2 * currentBaseTarget) and down at most by half (0.5 * currentBaseTarget).
  • EffectiveBalance
This is your stake in ARDR. Only the amount of ARDR that has been confirmed at least 1440 times counts towards this balance. The reason the effective balance is used is to avoid shuffling attacks.
  • TimeSinceLastBlock
How long, in seconds, since the last block has been generated. This parameter is also the same for everybody.

The block forger

The way who gets to generate the next block is chosen, is done by using the condition:

if (hits.get(accountId).compareTo(target) < 0){
   BlockchainProcessorImpl.getInstance().generateBlock(secretPhrase);
}

Taken from ardor / src / java / nxt / Generator.java

This says, essentially, that if the condition Hit < Target is satisfied, you get to generate the next block.

Now that we know the forging algorithm, there are some considerations we can make:

  • All the parameters except the effective balance are the same for everybody.
  • The hit parameter is static, what changes during the forging process is the target. Every forger has its own target (even though it depends on parameters equal for everybody) and it reflects the forger's stake. Every second that no block gets generated, the target increases until someone's hit, on the network, manages to be smaller than their own target. The consequence is clear: bigger is your stake, higher will be your target (and more rapidly it will grow) making it easier for you to satisfy the condition. In a practical sense, this entails you will get to generate a block more often.
  • TimeSinceLastBlock is the parameter that gives target its increasing nature. The longer it takes to generate a block, the higher becomes the target.
  • The situation where multiple forgers satisfy the forging condition at the same time is tangible, the network handles this situation accordingly.