FAQ: Everything About FastFinality

Background

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.

FAQs

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:

# the 2 flags for votekey edit on beacon chain client
--side-vote-addr <your vote key,48 Bytes>
--bls-wallet /<path>/bls/wallet
  • c. To update the vote key, repeat the above two steps(step a&b).
  • d.If you are using a hardware wallet, like ledger, you may encounter sign failure, like
ERROR: {"codespace":1, "code":4, "abci_code": 65540, "message": "signature verification failed"}

The root cause is still unknown, but add this argument would help:

# replace <anyword> with any word you like, if fail again, pls retry with a new word, it could succeed with a few try
--memo <anyword>

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.

  • e.To import vote key based on a private BLS key
# will prompt to ask you to set the wallet password
./bsc bls account import --datadir ./ --private-key <privateBLSKeyFile>

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

  • bls/wallet: All account private keys that are imported are encrypted into a single file using the wallet password.

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, 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?

a.Get The 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

b.Get The Block Header/Body

// int64 probabilisticFinalized, should be in range [2,21], then the block header with number `max(fastFinalized, latest-probabilisticFinalized)` will be returned
eth_getFinalizedHeader(int64 probabilisticFinalized)

// int64 probabilisticFinalized, should be in range [2,21],  then the block with number `max(fastFinalized, latest-probabilisticFinalized)` will be returned
// bool fullTx, When fullTx is true all transactions in the block are returned, otherwise, only the transaction hash is returned.
eth_getFinalizedBlock(int64 probabilisticFinalized, bool fullTx)

c.trace latest finalized blocks: eth_newFinalizedHeaderFilter

Here are two APIs that can help you trace latest finalized blocks:

  1. Create a finalized header filter:
curl -X POST "http://localhost:8545" -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_newFinalizedHeaderFilter","params":[],"id":1}'

This will return an rpc.ID which will expire in 5 minutes, then you can get another:

{"jsonrpc":"2.0","id":1,"result":"0xcbdc7c21459e2cfbf72e2028f15a98c"}
  1. Get latest finalized blocks using above rpc.ID. You can call it many times until rpc.ID expired:
curl -X POST "http://localhost:8545" -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0xcbdc7c21459e2cfbf72e2028f15a98c"],"id":1}'

This will return block hashes:

{"jsonrpc":"2.0","id":1,"result":["0x4b52061726b9f15905217699fd5dab8ff9bb704b3b16d27c34541cb15752a91f","0x2b984b80b25f0dddc92ba11290a3d250fc8a3ec6a09bd485c21dbbb8155d2f90"]}
  1. To get belonged blockHash
# for example, your transaction hash is "0x88b5b22ca40a4b90e955b932b2b17707e4212d85eaf5ac49693d7971eabcee29"
curl -X POST "http://localhost:8545" -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x88b5b22ca40a4b90e955b932b2b17707e4212d85eaf5ac49693d7971eabcee29"],"id":1}'

This will return data including blockHash and blockNumber:

{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0xdfe6b0974f4d645efd4ae2cb78f1a3991e2cc58e6610e84f1a0636555c6cd4af","blockNumber":"0x9858","from":"0x22615f4a0dce864cf20f95d6c2587b0d08b38157","gas":"0x7fffffffffffffff","gasPrice":"0x0","hash":"0x88b5b22ca40a4b90e955b932b2b17707e4212d85eaf5ac49693d7971eabcee29","input":"0x300c3567000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000..."}}
  1. To confirm your transaction
    BSC chain will finalize blocks continuously, so you can just check whether the blockHash of your transaction is in the finalized blockHash set. If many block intervals passed, but the blockHash not found in the finalized blockHash set, you can back to use probabilistic finality again, such as just waiting 15 blocks.

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: To Get Vote Information From Header.Extra

After Luban upgrade, we introduced vote attestation into the header’s extra field, so the Header.Extra format has been changed.
Here is the description of its layout and how users can parse the extra field to get the vote information.
a.Layout Of The Extra Field

# Before Luban Upgrade
extraVanity    32B // Fixed number of extra-data prefix bytes reserved for signer vanity
validatorList  (ValidatorSize * 20B) // only on Epoch height, e.g. 29853200
extraSeal      65B // Fixed number of extra-data suffix bytes reserved for signer seal
# After Luban Upgrade
extraVanity        32B // Fixed number of extra-data prefix bytes reserved for signer vanity
ValidatorSize      1B  // option, only on Epoch height
validatorVoteList  (ValidatorSize*(20B+48B)) // option, only on Epoch height, array of validator address(20B) and its vote address(48B)
VotesAttestation   (RLPEncoded, varies size) // optional, only when enough votes are collected
extraSeal          65B // Fixed number of extra-data suffix bytes reserved for signer seal

b.About VotesAttestation
It is the structure that contains the vote message.

// 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.
}

c.Try It
The explorer already support parsing the extra field, may refer:

And we also provided a tool to parse it, you may refer: bsc/cmd/extradump/main.go at master · bnb-chain/bsc · GitHub.
To try the tool:

git clone https://github.com/bnb-chain/bsc.git
cd bsc/cmd/extradump
go build .
./extradump <extraHexData>

more to be collected…