Difference between revisions of "Signet"

From Bitcoin Wiki
Jump to: navigation, search
(Switch to proposed changes in https://github.com/bitcoin/bips/pull/900)
m (Faucets: add alt.signetfaucet)
(38 intermediate revisions by 8 users not shown)
Line 1: Line 1:
Signet ([[BIP 0325]]) is a proposed new test network for the Bitcoin [[block chain]] which adds an additional signature requirement to block validation. Signet is similar in nature to [[testnet]], but more reliable and centrally controlled. There is a default signet network ("Signet Global Test Net IV" as of this writing), but anyone can run their own signet network at their whim.
+
'''Signet''' ([[BIP 0325]]) is a new test network for Bitcoin which adds an additional signature requirement to block validation. Signet is similar in nature to [[testnet]], but more reliable and centrally controlled. There is a default signet network ("Signet Global Test Net VI" as of this writing), but anyone can run their own signet network at their whim.
  
Run bitcoind with the <code>-signet</code> flag to use the default global signet (or put <code>signet=1</code> in the <code>bitcoin.conf</code> file). If you wish to use a [[#Custom Signet|custom signet]], you need to provide the block challenge (aka the block script) using <code>-signet_blockscript=<hex></code> and the genesis nonce using <code>-signet_genesisnonce=<number></code>, and preferably also at least one seed node using <code>-signet_seednode=<host>[:<port>]</code>.
+
Run bitcoind with the <code>-signet</code> flag to use the default global signet (or put <code>signet=1</code> in the <code>bitcoin.conf</code> file). If you wish to use a [[#Custom Signet|custom signet]], you need to provide the block challenge (aka the block script) using <code>-signetchallenge=<hex></code>, and preferably also at least one seed node using <code>-signetseednode=<host>[:<port>]</code>.
  
 
==Differences==
 
==Differences==
Line 7: Line 7:
 
* Default Bitcoin network protocol listen port is 38333 (instead of 8333)
 
* Default Bitcoin network protocol listen port is 38333 (instead of 8333)
 
* Default RPC connection port is 38332 (instead of 8332)
 
* Default RPC connection port is 38332 (instead of 8332)
* Address prefixes are different: pubkey=<code>0x7D</code> (125), p2sh=<code>0x57</code> (87), privkey=<code>0xD9</code> (217)
+
* A different value of ADDRESSVERSION field ensures no signet Bitcoin addresses will work on the production network. (0x6F rather than 0x00)
* The protocol message header bytes are <code>0xF0C7706A</code> (instead of <code>0xF9BEB4D9</code>)  
+
* The protocol message header bytes are *dynamically generated* based on the block challenge, i.e. every signet is different; the header for the current default signet is <code>0x0A03CF40</code> (that is reversed e.g. in Rust variables) (instead of <code>0xF9BEB4D9</code>), but see [[#Genesis_Block_and_Message_Header]]
* Genesis block has timestamp 1534313275, nonce 100123, and difficulty 0x1e2adc28.
+
* Genesis block has timestamp 1598918400, nonce 52613770, and difficulty 0x1e0377ae.
 
* Segwit is always enabled
 
* Segwit is always enabled
 
* Additional consensus requirement that the coinbase witness commitment contains an extended signet commitment, which is a script satisfying the block script (usually a k-of-n multisig)
 
* Additional consensus requirement that the coinbase witness commitment contains an extended signet commitment, which is a script satisfying the block script (usually a k-of-n multisig)
Line 21: Line 21:
 
* You want an easy way to test double spends (signet plans to include support for automated double spends, where you provide two conflicting transactions and they are mined in order, with a reorg happening between them).
 
* You want an easy way to test double spends (signet plans to include support for automated double spends, where you provide two conflicting transactions and they are mined in order, with a reorg happening between them).
  
==Genesis Block and Message Start==
+
==Genesis Block and Message Header==
  
All signet networks share the same genesis block, but have a different message start. The message start is the 4 first bytes of the sha256d-hash of the block challenge, as a single script push operation. I.e. if the block challenge is 37 bytes, the message start would be sha256d(0x25 || challenge)[0..3].
+
All signet networks share the same genesis block, but have a different message header. The message header is the 4 first bytes of the sha256d-hash of the block challenge, as a single script push operation. I.e. if the block challenge is 37 bytes, the message start would be sha256d(0x25 || challenge)[0..3].
  
 
==Getting Started==
 
==Getting Started==
 +
 +
NOTE: signet (IV) was merged into the master branch of Bitcoin Core as of https://github.com/bitcoin/bitcoin/pull/18267
  
 
===Fetch and compile signet===
 
===Fetch and compile signet===
  
 
<pre>
 
<pre>
$ git clone https://github.com/kallewoof/bitcoin.git signet
+
$ git clone https://github.com/bitcoin/bitcoin
$ cd signet
+
$ cd bitcoin
$ git checkout signet-0.19
 
 
$ ./autogen.sh
 
$ ./autogen.sh
 
$ ./configure
 
$ ./configure
Line 106: Line 107:
 
==External links==
 
==External links==
  
* [https://github.com/bitcoin/bitcoin/pull/16411 Pull request #16411 to Bitcoin Core]
+
* [https://github.com/bitcoin/bips/blob/master/bip-0325.mediawiki BIP-325]
* [https://github.com/rust-bitcoin/rust-bitcoin/pull/291 Pull request #291 to Rust-Bitcoin]
 
* [https://gist.github.com/kallewoof/98b6d8dbe126d2b6f47da0ddccd2aa5a Github gist explaining how to get started]
 
  
 
===Faucets===
 
===Faucets===
  
* https://signet.bc-2.jp/
+
* https://signetfaucet.com/
 +
* https://alt.signetfaucet.com (the same [https://signetfaucet.bublina.eu.org here])
  
 
Can also ping @kallewoof on IRC (freenode)/Twitter.
 
Can also ping @kallewoof on IRC (freenode)/Twitter.
Line 120: Line 120:
 
* https://github.com/kallewoof/bitcoin-faucet.git (node.js and mongodb)
 
* https://github.com/kallewoof/bitcoin-faucet.git (node.js and mongodb)
 
* https://github.com/stepansnigirev/tinyfaucet.git (python)
 
* https://github.com/stepansnigirev/tinyfaucet.git (python)
 +
* https://github.com/jsarenik/bitcoin-faucet-shell (POSIX shell)
  
 
===Block explorers===
 
===Block explorers===
  
 
* https://explorer.bc-2.jp/
 
* https://explorer.bc-2.jp/
 +
* https://mempool.space/signet
 +
* https://ex.signet.bublina.eu.org
  
 
==Custom Signet==
 
==Custom Signet==
 +
 +
'''NOTE:''' Until it is merged into master branch, you may first need to check-out (or merge) the code referred in https://github.com/bitcoin/bitcoin/pull/19937 in order to get the script <code>contrib/signet/miner</code>.
  
 
Creating your own signet involves a couple of steps: generate keys used for signing, define the block script, start up a node running on the new signet, and import the private key in order to sign blocks.
 
Creating your own signet involves a couple of steps: generate keys used for signing, define the block script, start up a node running on the new signet, and import the private key in order to sign blocks.
Line 131: Line 136:
 
===Generating keys used for signing a block===
 
===Generating keys used for signing a block===
  
The most straightforward way is to simply start up a signet instance and then generating a new key from there.
+
The most straightforward way is to simply start up a regtest node and then generating a new key from there.
  
 
<pre>
 
<pre>
 
$ cd PATHTOBITCOIN/bitcoin/src
 
$ cd PATHTOBITCOIN/bitcoin/src
$ ./bitcoind -signet -daemon
+
$ ./bitcoind -regtest -daemon -wallet="test"
$ ADDR=$(./bitcoin-cli -signet getnewaddress)
+
$ ADDR=$(./bitcoin-cli -regtest getnewaddress)
$ PRIVKEY=$(./bitcoin-cli -signet dumpprivkey $ADDR)
+
$ PRIVKEY=$(./bitcoin-cli -regtest dumpprivkey $ADDR)
$ ./bitcoin-cli -signet getaddressinfo $ADDR | grep pubkey
+
$ ./bitcoin-cli -regtest getaddressinfo $ADDR | grep pubkey
   "pubkey": "02c60c3940e5REDACTEDbd0148cd",
+
   "pubkey": "THE_REAL_PUBKEY",
 
</pre>
 
</pre>
  
We need to jot down the privkey (<code>echo $PRIVKEY</code>) and the pubkey (here <code>02c60...</code>).
+
We need to jot down the privkey (<code>echo $PRIVKEY</code>) and the pubkey (here <code>THE_REAL_PUBKEY</code>).
  
 
===Defining the block script===
 
===Defining the block script===
Line 149: Line 154:
 
* <code>51</code> "1" (signature count)
 
* <code>51</code> "1" (signature count)
 
* <code>21</code> Push 0x21=33 bytes (the length of our pubkey above)
 
* <code>21</code> Push 0x21=33 bytes (the length of our pubkey above)
* <code>02c60c3940e5REDACTEDbd0148cd</code> (our pubkey)
+
* <code>THE_REAL_PUBKEY</code> (our pubkey)
 
* <code>51</code> "1" (pubkey count)
 
* <code>51</code> "1" (pubkey count)
 
* <code>ae</code> <code>OP_CHECKMULTISIG</code> opcode
 
* <code>ae</code> <code>OP_CHECKMULTISIG</code> opcode
  
Put together, our <code>-signet_blockscript</code> value becomes <code>512102c60c3940e5REDACTEDbd0148cd51ae</code>.
+
Put together, our <code>-signetchallenge</code> value becomes <code>5121...51ae</code>. Where <code>...</code> stands for <code>THE_REAL_PUBKEY</code> (see above).
  
 
===Start up a node (issuer)===
 
===Start up a node (issuer)===
Line 162: Line 167:
  
 
<pre>
 
<pre>
$ ./bitcoin-cli -signet stop
+
$ ./bitcoin-cli -regtest stop
 
$ datadir=$HOME/signet-custom
 
$ datadir=$HOME/signet-custom
 
$ mkdir $datadir
 
$ mkdir $datadir
Line 168: Line 173:
 
[signet]
 
[signet]
 
daemon=1
 
daemon=1
signet_blockscript=512102c60c3940e5REDACTEDbd0148cd51ae" > $datadir/bitcoin.conf
+
signetchallenge=5121...51ae # fill in THE_REAL_PUBKEY" > $datadir/bitcoin.conf
$ ./bitcoind -datadir=$datadir
+
$ ./bitcoind -datadir=$datadir -wallet="test"
 
$ ./bitcoin-cli -datadir=$datadir importprivkey $PRIVKEY
 
$ ./bitcoin-cli -datadir=$datadir importprivkey $PRIVKEY
 
</pre>
 
</pre>
Line 177: Line 182:
 
===Run issuer===
 
===Run issuer===
  
Lastly, we start the issuer script located in <code>contrib/signet</code>.
+
Lastly, we're going to get an issuer up and running to mine blocks.
 +
 
 +
We'll need to provide a value for <code>nbits</code> which is the mining target and is inversely proportional to the difficulty. This will allow us to set the average time between mined blocks.
 +
 
 +
We can use the <code>calibrate</code> command to give us the <code>nbits</code> for an average mining time of 10 min (600 s):
 +
 
 +
<pre>
 +
$ ../contrib/signet/miner --cli="./bitcoin-cli" calibrate --grind-cmd="./bitcoin-util grind" --seconds=600
 +
</pre>
 +
 
 +
Referring to our <code>nbits</code> value with the variable <code>$NBITS</code>, we need to specify <code>--set-block-time</code> when mining the first block in a new signet:
  
 
<pre>
 
<pre>
$ cd ../contrib/signet
+
$ ADDR=$(./bitcoin-cli -datadir=$datadir getnewaddress); ../contrib/signet/miner --cli="./bitcoin-cli -datadir=$datadir" generate --address $ADDR --grind-cmd="./bitcoin-util grind" --nbits=$NBITS --set-block-time=$(date +%s)
$ ./issuer.sh 540 ../../src/bitcoin-cli -datadir=$datadir
+
</pre>
- checking node status
+
 
- 23:51:01: node OK with 0 connection(s)
+
This will create an address, and then mine the first block to that address. (Note that you may need to create a wallet first.)
- 23:51:01: mining at maximum capacity with 540 second delay between each block
+
 
- 23:51:01: hit ^C to stop
+
To keep the mining ongoing from there, aiming for blocks arriving every 10 minutes on average, we can run:
- 23:51:01: generating next block
+
 
- 23:51:08: mined block 1 0000321422407052c06fef1eacbee402571787c9828051981adfbb5d50a2330a to 0 peer(s); idling for 540 seconds
+
<pre>
 +
$ ../contrib/signet/miner --cli="./bitcoin-cli -datadir=$datadir" generate --address $ADDR --grind-cmd="./bitcoin-util grind" --nbits=$NBITS --ongoing
 
</pre>
 
</pre>
  
This script will keep on mining blocks every 540 seconds (actually it will take about 60 seconds to generate a block after the difficulty has stabilized, so you should be seeing one block every 600 seconds) until you hit ctrl-C. It may be a good idea to run this in a screen, so you can check back on it occasionally.
+
Next is to have your friends/colleagues/etc join the network by setting the <code>signetchallenge</code> to the same as above, and connecting to your node.
  
You may also want to run the issuer with a lower idle time initially, so you get some mature coinbase outputs faster.
+
===Example Script===
  
Next is to have your friends/colleagues/etc join the network by setting the <code>signet_blockscript</code> and <code>signet_genesisnonce</code> to the same as above, and connecting to your node.
+
A full example script can be found at https://en.bitcoin.it/wiki/Signet:Custom:Script
  
 
[[Category:Technical]]
 
[[Category:Technical]]

Revision as of 16:47, 22 December 2021

Signet (BIP 0325) is a new test network for Bitcoin which adds an additional signature requirement to block validation. Signet is similar in nature to testnet, but more reliable and centrally controlled. There is a default signet network ("Signet Global Test Net VI" as of this writing), but anyone can run their own signet network at their whim.

Run bitcoind with the -signet flag to use the default global signet (or put signet=1 in the bitcoin.conf file). If you wish to use a custom signet, you need to provide the block challenge (aka the block script) using -signetchallenge=<hex>, and preferably also at least one seed node using -signetseednode=<host>[:<port>].

Differences

  • Default Bitcoin network protocol listen port is 38333 (instead of 8333)
  • Default RPC connection port is 38332 (instead of 8332)
  • A different value of ADDRESSVERSION field ensures no signet Bitcoin addresses will work on the production network. (0x6F rather than 0x00)
  • The protocol message header bytes are *dynamically generated* based on the block challenge, i.e. every signet is different; the header for the current default signet is 0x0A03CF40 (that is reversed e.g. in Rust variables) (instead of 0xF9BEB4D9), but see #Genesis_Block_and_Message_Header
  • Genesis block has timestamp 1598918400, nonce 52613770, and difficulty 0x1e0377ae.
  • Segwit is always enabled
  • Additional consensus requirement that the coinbase witness commitment contains an extended signet commitment, which is a script satisfying the block script (usually a k-of-n multisig)

Why run Signet?

  • You are an Instructor, and want to run a controlled Bitcoin network environment for teaching purposes.
  • You are a Software Developer, and want to test your software.
  • You want to try out experimental changes that you want to implement in Bitcoin.
  • You want to test long-term running software and don't want to deal with tens of thousands of block reorgs, or days of no blocks being mined, as is the case with Testnet.
  • You want an easy way to test double spends (signet plans to include support for automated double spends, where you provide two conflicting transactions and they are mined in order, with a reorg happening between them).

Genesis Block and Message Header

All signet networks share the same genesis block, but have a different message header. The message header is the 4 first bytes of the sha256d-hash of the block challenge, as a single script push operation. I.e. if the block challenge is 37 bytes, the message start would be sha256d(0x25 || challenge)[0..3].

Getting Started

NOTE: signet (IV) was merged into the master branch of Bitcoin Core as of https://github.com/bitcoin/bitcoin/pull/18267

Fetch and compile signet

$ git clone https://github.com/bitcoin/bitcoin
$ cd bitcoin
$ ./autogen.sh
$ ./configure
$ make -j5

Create bitcoin.conf file and start up the daemon

$ cd src
$ mkdir signet
$ echo "signet=1
daemon=1" > signet/bitcoin.conf
$ ./bitcoind -datadir=signet

Verify that you're connected

$ ./bitcoin-cli -datadir=signet getconnectioncount
***SHOULD BE MORE THAN ZERO***
$ ./bitcoin-cli -datadir=signet getblockcount
***SHOULD BE MORE THAN ZERO***

Get some coins

There is a command line tool you can use to get coins directly to your instance of Signet, assuming you are on the default network. You can also use the faucet online with an address of yours.

Using online faucet

You first need an address

$ ./bitcoin-cli -datadir=signet getnewaddress

Then go to a faucet, e.g. https://signet.bc-2.jp and enter your address.

Using the command line tool

The tool is in contrib/signet and is called getcoins.sh. You can optionally provide a path to bitcoin-cli using --cmd=[path] and a compatible faucet using --faucet=[url] followed by any number of arguments to bitcoin-cli. The script attempts to autodetect these if left out.

$ cd ../contrib/signet
$ ./getcoins.sh -datadir=../../src/signet
Payment of 10.00000000 BTC sent with txid c0bfa...

Check that you received the coins

Check your faucet transaction confirming at e.g. https://explorer.bc-2.jp and then send coins around to people and/or use signet for testing your wallet/etc.

You can immediately see the amount using getunconfirmedbalance i.e.

$ cd ../../src # if you were in contrib/signet
$ ./bitcoin-cli -datadir=signet getunconfirmedbalance

You can also see info about the transaction that the faucet gave you.

$ ./bitcoin-cli -datadir=signet gettransaction THETXID

Once it has confirmed, you should see it in getbalance.

$ ./bitcoin-cli -datadir=signet getbalance

External links

Faucets

Can also ping @kallewoof on IRC (freenode)/Twitter.

Faucet source code, if you want your own:

Block explorers

Custom Signet

NOTE: Until it is merged into master branch, you may first need to check-out (or merge) the code referred in https://github.com/bitcoin/bitcoin/pull/19937 in order to get the script contrib/signet/miner.

Creating your own signet involves a couple of steps: generate keys used for signing, define the block script, start up a node running on the new signet, and import the private key in order to sign blocks.

Generating keys used for signing a block

The most straightforward way is to simply start up a regtest node and then generating a new key from there.

$ cd PATHTOBITCOIN/bitcoin/src
$ ./bitcoind -regtest -daemon -wallet="test"
$ ADDR=$(./bitcoin-cli -regtest getnewaddress)
$ PRIVKEY=$(./bitcoin-cli -regtest dumpprivkey $ADDR)
$ ./bitcoin-cli -regtest getaddressinfo $ADDR | grep pubkey
  "pubkey": "THE_REAL_PUBKEY",

We need to jot down the privkey (echo $PRIVKEY) and the pubkey (here THE_REAL_PUBKEY).

Defining the block script

The block script is just like any old Bitcoin script, but the most common type is a k-of-n multisig. Here we will do a 1-of-1 multisig with our single pubkey above. Our script becomes

  • 51 "1" (signature count)
  • 21 Push 0x21=33 bytes (the length of our pubkey above)
  • THE_REAL_PUBKEY (our pubkey)
  • 51 "1" (pubkey count)
  • ae OP_CHECKMULTISIG opcode

Put together, our -signetchallenge value becomes 5121...51ae. Where ... stands for THE_REAL_PUBKEY (see above).

Start up a node (issuer)

For the network to be useful, it needs to be generating blocks at decent intervals, so let's start up a node that does that (it may be useful to also use that node as a seed node for other peers).

Note that we are importing $PRIVKEY at the end; any node that needs to issue blocks must import the privkey we generated above, or it will fail to sign blocks.

$ ./bitcoin-cli -regtest stop
$ datadir=$HOME/signet-custom
$ mkdir $datadir
$ echo "signet=1
[signet]
daemon=1
signetchallenge=5121...51ae # fill in THE_REAL_PUBKEY" > $datadir/bitcoin.conf
$ ./bitcoind -datadir=$datadir -wallet="test"
$ ./bitcoin-cli -datadir=$datadir importprivkey $PRIVKEY

Note: if you run into errors above, you may have a different signet running, which is blocking the ports. Either stop that, or set port and rpcport in the $datadir/bitcoin.conf file under the [signet] section and try again from the bitcoind part above.

Run issuer

Lastly, we're going to get an issuer up and running to mine blocks.

We'll need to provide a value for nbits which is the mining target and is inversely proportional to the difficulty. This will allow us to set the average time between mined blocks.

We can use the calibrate command to give us the nbits for an average mining time of 10 min (600 s):

$ ../contrib/signet/miner --cli="./bitcoin-cli" calibrate --grind-cmd="./bitcoin-util grind" --seconds=600

Referring to our nbits value with the variable $NBITS, we need to specify --set-block-time when mining the first block in a new signet:

$ ADDR=$(./bitcoin-cli -datadir=$datadir getnewaddress); ../contrib/signet/miner --cli="./bitcoin-cli -datadir=$datadir" generate --address $ADDR --grind-cmd="./bitcoin-util grind" --nbits=$NBITS --set-block-time=$(date +%s)

This will create an address, and then mine the first block to that address. (Note that you may need to create a wallet first.)

To keep the mining ongoing from there, aiming for blocks arriving every 10 minutes on average, we can run:

$ ../contrib/signet/miner --cli="./bitcoin-cli -datadir=$datadir" generate --address $ADDR --grind-cmd="./bitcoin-util grind" --nbits=$NBITS --ongoing

Next is to have your friends/colleagues/etc join the network by setting the signetchallenge to the same as above, and connecting to your node.

Example Script

A full example script can be found at https://en.bitcoin.it/wiki/Signet:Custom:Script