FAQ: Everything About FastFinality


FastFinality is quite a big feature, which brings lots changes to the BNB Chain, both BC & BSC.
As we delivered the 1st part of FastFinality in Luban Upgrade, many of the BNB ecosystem partners, developers, user may have questions about this feature, so we open this post to collect the questions and to answer it.

Anyone can reply this post with your question, if you have not registered the forum yet, you are also welcomed to create an issue on BSC repo. Just let us know what puzzles you.


Q1: How To Set Up The Vote Key

The vote key is a BLS key with a public key length of 48 bytes.
To create or update the vote key, follow these steps:

a. Set up a new vote key locally as described in BNB Smart Chain Testnet: Luban Upgrade Announcement.
b. Use bsc-edit-validator to add or change the vote key. After the breathe block, the key will be transferred from the BC chain to the BSC chain, and the new vote key will be enabled.
c. To update the vote key, repeat the above two steps.

Q2: What If Validator Does Not Enable Voting?

Initially, validators will not be punished if they do not enable voting. However, they will miss the opportunity to receive the voting reward.

Once 2/3 or more validators cast the same valid vote, a vote attestation will be formed and added to the block header. The validators who participated in the vote will receive a reward.

Q3: Where Does The Vote Reward Come From?

BNB Smart Chain (BSC) already has a reward mechanism in place. This is the SystemRewardContract (https://bsctrace.com/address/0x0000000000000000000000000000000000001002), a system contract used to incentivize certain platform-level activities, such as cross-chain communication by relayers (https://github.com/bnb-chain/BEPs/blob/master/BEP86.md).

The vote reward will also use this reward mechanism, so it will come from the SystemRewardContract.

You may be wondering how the SystemRewardContract is funded. Well, it is actually funded through transaction gas fees. When the balance of the SystemRewardContract falls below 100 BNB, 1/16 of the block transaction fee is sent to it to ensure it has sufficient balance to carry out its reward job.

For vote rewards, 50% of the system contract balance increment in each epoch will be used as fast finality voting rewards. This ratio can be adjusted; 50% is the initial ratio, and we need to leave some reward for other functions.

Q4: How To Check If Vote Works?

Validators can check if their vote works in their own nodes by viewing metrics. For others, they can check whether the justified block number is increasing. If the voting of 2/3+ validators works correctly, the justified block number should increase after the Luban upgrade. To check it, use eth_getblockbynumber with the parameter safe.

Q5: Why Not Just Use Validator’s Consensus Key To Vote?

BLS signatures can be aggregated, greatly reducing the size of vote attestations that need to be stored in the block header. However, secp256k1 signatures cannot be aggregated.

Q6: The Usage Of WalletKey & AccountKey

  • bls/wallet: All account private keys that are imported are encrypted into a single file using the wallet password.
  • bls/keystore: Each account’s private key is also encrypted using its own account password and is stored in separate files.

Q7: Why Only Wallet Password In Config.toml, No Account Password?

BSC simply uses the wallet password to decrypt private keys in the bls/wallet directory and uses the first one.

If you create a new wallet and wish to import an existing account by specifying a file, you will need to provide the corresponding account password.

Therefore, in config.toml, the account password is no longer needed.

Q8: Relative Or Absolute Path In Config.toml?

Both are supported, but v1.2.1 has a bug, which will be fixed in the next release.

You need to specify the wallet path by: --blswallet /<path>/bls/wallet

Q9: Which Account Will Be Used If There Are Multiple?

As mentioned in: BNB Smart Chain Testnet: Luban Upgrade AnnouncementYou can run: ./geth bls account list --datadir <path>, the first one listed here will be used as the voting key, other keys are not used right now.

Q10: Can Validator Change Its Vote Key And How To Do It?

Has already been answered in Q8.

Q11: What Is Validator Lost The Vote Key?

Keeping your vote key secure is of utmost importance!

If someone gains access to your file in bls/wallet and knows the password of your wallet, or if they can access your file in bls/keystore and know the password of your account, then they can sign forged votes that violate voting rules. If evidence of such behavior is submitted to system contracts, validators will be fined 10000 BNBs now, but the amount can be governed and could be changed in the future.

If a validator has lost their vote key, they should immediately change it using bsc-edit-validator. However, if someone uses the old vote key to vote maliciously within two days, the validator will still be fined.

Q12: How To Get The Newest Justified or Finalized Block Number?

Just use the RPC API eth_getblockbynumber as in the Ethereum client.

  • HEX String - an integer block number
  • String “earliest” for the earliest/genesis block
  • String “latest” - for the latest mined block
  • String “safe” - for the latest safe(justified) head block
  • String “finalized” - for the latest finalized block
  • String “pending” - for the pending state/transactions

Q13: What Is The Difference With Ethereum 2.0 Gasper

They are similar, since both are based on the Casper FFG design. But BSC has faster finalize time, since it is block based finality, while Ethereum 2.0 is check point based. Besides of it, there are some implementation difference, such as the liveness design, economy mechanism etc. For detail, you may refer: BEP-126: Introduce Fast Finality Mechanism

Q14: Would This Feature Bring Extra Risks?

There do have extra risks:

  1. Liveness: if insufficient validators vote, e.g. less then 2/3 validators vote, then the fast finality would not work, the network will roll back to the previous probabilistic finality. So Dapps should not rely on the block height to check the finality, instead, they need to query the latest finalized block height through RPC call: eth_getblockbynumber(“finalized”, false)
  2. Collusion: validators collusion could rollback already finalized block, but they will face a huge penalty.
  3. Others: there could have some unknown risks, as it is a big feature, it needs time to verify.

Q15: Changes For ExtraData in block header

The validators bytes would be contained only in the epoch block’s header, and its each validator bytes length is fixed.
On Luban fork, we introduce vote attestation into the header’s extra field, so extra format is different from before.
Before Luban fork: |—Extra Vanity—|—Validators Bytes (or Empty)—|—Extra Seal—|
After Luban fork: |—Extra Vanity—|—Validators Number and Validators Bytes (or Empty)—|—Vote Attestation (or Empty)—|—Extra Seal—|

b.Extra without vote attestation

extraVanity      = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
nextForkHashSize = 4  // Fixed number of extra-data suffix bytes reserved for nextForkHash. It holds last 4 bytes of extraVanity
validatorNumberSize = 1 // Fixed number of extra prefix bytes reserved for validator number after Luban
validatorBytesLengthBeforeLuban = common.AddressLength // It is length of one validator, total length multiply number of validators
validatorBytesLength            = common.AddressLength + types.BLSPublicKeyLength // It is length of one validator, total length multiply number of validators
extraSeal        = 65 // Fixed number of extra-data suffix bytes reserved for signer seal

c.Vote Attestation related

// length of Vote Attestation is not fixed, rlp encoded of VoteAttestation is stored
type VoteAttestation struct {
	VoteAddressSet ValidatorsBitSet // The bitset marks the voted validators. 
	AggSignature   BLSSignature     // The aggregated BLS signature of the voted validators' signatures.
	Data           *VoteData        // The vote data for fast finality.
	Extra          []byte           // Reserved for future usage.


	BLSPublicKeyLength = 48
	AddressLength = 20,
	type ValidatorsBitSet uint64
	BLSSignatureLength = 96
	type BLSSignature [BLSSignatureLength]byte 
	type VoteData struct {
		SourceNumber uint64      // The source block number should be the latest justified block number.
		SourceHash   common.Hash // The block hash of the source block.
		TargetNumber uint64      // The target block number which the validator wants to vote for.
		TargetHash   common.Hash // The block hash of the target block.

more to be collected…