Progress pill
Element Federation

Block Signing

  • Block Signing
Elements supports a federated signing model, which allows you to specify the number of Strong Federation members that must sign a proposed block in order to produce a valid block.
Previously, and for ease of example, we have been creating blocks using the generate command, which hasn't had to satisfy a multisignature requirement in order for the blocks created to be accepted by the network as valid.
We'll be setting up our nodes to require 2-of-2 multisig block creation. This will be set up using the signblockscript parameter, which can be added to the config file or passed into the node on startup. To initialize a chain with this parameter, we first need to create a script that comprises the chain.
We'll do this by using some existing nodes, saving the data they output, and then wiping the chain so we can restart it using our signblockscript parameter. This is necessary because the script forms part of the network's consensus rules and must be set on-chain during the initialization process. It cannot be added to an existing chain at a later date.
We'll need access to two Elements nodes, which we will refer to as e1 and e2. The nodes have had their blockchains reset, and the default asset has been split between them.
Ensure that the con_max_block_sig_size parameter is set to a high value in your elements.conf file; otherwise, block signing will fail later on in this section. We have set con_max_block_sig_size to 2000 for this tutorial.
As we will be resetting our blockchain and wiping the wallets associated with e1 and e2, we will need to take a copy of the addresses, public keys, and private keys used to generate the block signing script, so we can use them later.
First, we need each of the block signing nodes to generate a new address, which you need to take a copy of.
e1-cli getnewaddress e2-cli getnewaddress
We then need to extract the public keys from the addresses and record them for later use.
e1-cli getaddressinfo <e1-address> e2-cli getaddressinfo <e2-address>
Then, extract the private keys, which we'll re-import later, so the nodes can sign the blocks after we re-initialize our blockchain and wallet data.
e1-cli dumpprivkey <e1-address> e2-cli dumpprivkey <e2-address>
Now we need to generate a redeem script with a 2-of-2 multi-signature requirement. We accomplish this by using the create-multisig command, passing the first parameter as 2, and then providing two public keys. It is these keys that ownership of needs proves later when the block is created.
Either node, e1 or e2, could generate the multisig.
e1-cli createmultisig 2 '["<e1-pubkey>", "<e2-pubkey>"]'
That gives us our redeem script, which you can copy for use later.
Now we need to wipe the existing blockchain and wallet data so we can start again with the new signblockscript as part of the chain's consensus rules. This is why we needed to take a copy of some of the data earlier, such as the private keys that will be used in the new chain to sign blocks. You must complete this step before proceeding.
With our existing wallet and chain data deleted, we can now start our nodes and have them initialize a new chain using the signblockscript parameter. Let's pass in -evbparams=dynafed:0::: to disable dynafed activation, because we don't need that advanced feature for this example.
e1-dae -signblockscript=<redeem-script> -evbparams=dynafed:0::: e2-dae -signblockscript=<redeem-script> -evbparams=dynafed:0:::
Now we need to import the private keys that we saved earlier so that our nodes can sign and help complete any proposed blocks.
e1-cli importprivkey <e1-priv-key> e2-cli importprivkey <e2-priv-key>
The use of the generate command should now error as it fails to meet the required block signing rules now enforced by our nodes.
e1-cli -generate 1
To propose a new block, either node can call the getnewblockhex command. This returns the hexadecimal representation of a new block that must be signed before it is accepted by any nodes on our network.
e1-cli getnewblockhex
Remember that the command just creates a proposed block; it doesn't generate one.
To confirm this, we can see that there are currently no blocks in our blockchain.
e1-cli getblockcount
If we try submitting the block hex without signing it first.
e1-cli submitblock <block-hex>
We receive a message indicating that the block proof is invalid. This is because it has not yet been signed by 2 of the required 2 parties.
So let's get e1 to sign the proposed block.
e1-cli signblock <block-hex>
Have e2 sign the hex.
e2-cli signblock <block-hex>
Notice that e2 does not sign the output created from e1 signing the proposed block. They both sign the proposed block hex independently of each other's results.
Now we need to combine the block signatures of e1 and e2. Either node can perform this action; all they need is the signed block hex from the other node.
e1-cli combineblocksigs <block-hex> '["<signed-hex-from-e1>", "<signed-hex-from-e2>"]'
You can see that the combineblocksigs command outputs the hex of the signed block, as well as a status of 'complete', indicating that the block hex is ready to be submitted.
Now, either node can submit the completed block hex. We'll have e1 do it.
e1-cli submitblock <combined-signed-hex>
Checking that the submission was a valid one.
e1-cli getblockcount e2-cli getblockcount
You can see that both e1 and e2 have accepted the block as valid and added it to the tip of their local copies of the blockchain.
To summarize the process. In this section, we have:
  • Proposed a block.
  • Had each node sign it.
  • Combined the signatures.
  • Checked that the signatures are valid and meet the chain's redeemscript threshold.
  • Submitted the block.
Each node on the network validated the block and added it to its local copy of the blockchain.

Block Signing

Although the process initially appears complex, the sequence of block signing in Elements is always the same, and the initial setup needs to be performed only once:
  1. Initial setup (performed once)
  2. A multisignature address is created called signblockscript using the public keys of Federated Block Signers.
  3. The redeem script from this is used to start a new blockchain.
  4. Block production (ongoing)
  5. Proposed blocks are generated and exchanged for signing.
Once a threshold number of signatories have signed the proposed block, it is combined and submitted to the network. If it meets the criteria of the chain's signblockscript, nodes accept it as a valid block.