Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
262 lines (202 sloc) 10.7 KB

UIP-15: Remote staking

Author:   Azat Nizametdinov <>
Status:   Proposed
Created:  2018-12-20


This UIP introduces the concept of remote staking which allows users to delegate staking to other nodes which can stake their funds but can not spend them. The mechanism is similar to the cold staking in Particl and to the account leasing in NXT.


Remote staking solves the following problems:

  1. The Proof-of-Stake protocol requires users to keep their wallets (usually with a significant amounts of money) online to propose and validate blocks. If a computer with the staking wallet gets hacked then the attacker will be able to steal the money.

  2. Currently, it is not possible to use P2SH (and P2WSH) outputs as a stake. The reason is that a block must be signed with the same key which is used to unlock the stake, and P2SH might have redeemScript which does not involve public key cryptography at all.

  3. Public keys get revealed during the process of staking which makes wallets vulnerable to quantum computing attacks. Obviously, those kinds of attacks are purely theoretical at the moment.


Remote staking is enabled by a special kind of unlocking scripts which require different keys for staking and spending transactions. There are two versions of remote-staking scripts: version 1 and version 2 which extend respectively P2WPKH and P2WSH.

The version 1 remote-staking scriptPubKey, remote-staking P2WPKH (RSP2WPKH), consists of 1-byte push opcode OP_1 followed by two data pushes of 20 and 32 bytes:

1 <20-byte-staking-pubkey-hash> <32-byte-spending-pubkey-hash>

Where data pushes correspond to the following hashes:

  1. <20-byte-staking-pubkey-hash> is a HASH160 of a public key for staking (i.e. RIPEMD160(SHA256(compressed pubkey)));
  2. <32-byte-spending-pubkey-hash> is a SHA256 of a public key for spending.

The version 2 remote-staking scriptPubKey, remote-staking P2WSH (RSP2WSH), consists of 1-byte push opcode OP_2 followed by two data pushes of 20 and 32 bytes:

2 <20-byte-staking-pubkey-hash> <32-byte-spending-script-hash>

Where data pushes have the following meaning:

  1. <20-byte-staking-pubkey-hash> is a HASH160 of a public key for staking;
  2. <32-byte-spending-script-hash> is a SHA256 of a witnessScript.

Validation of the witness

For RSP2WPKH, the witness MUST be validated in the same way as it is validated for P2WPKH (as specified in BIP-141) except for the validation of a public key hash:

  • The witness MUST consist of exactly 2 items (≤ 520 bytes each). The first one a signature, and the second one a public key.
  • The validation of a public key hash depends on the type of transaction which spends the output with the remote-staking scriptPubKey:
    • when the transaction is a coinbase transaction (TxType::COINBASE) then HASH160 of the public key MUST match the <20-byte-staking-pubkey-hash>,
    • otherwise the SHA256 of the public key MUST match <32-byte-spending-pubkey-hash>.
  • The signature is verified against the public key with CHECKSIG operation. The verification MUST result in a single TRUE on the stack.

For RSP2WPKH, the validation of the witness depends on the type of the transaction which spends an output with RSP2WSH script. When the transaction is a coinbase transaction (TxType::COINBASE) then it MUST be validated as described above for RSP2WPKH. Otherwise, it MUST be validated as P2WSH (as specified in BIP-141):

  • The witness must consist of an input stack to feed to the script, followed by a serialized script (witnessScript).
  • The witnessScript (≤ 10,000 bytes) is popped off the initial witness stack. SHA256 of the witnessScript must match the 32-byte spending script hash.
  • The witnessScript is deserialized, and executed after normal script evaluation with the remaining witness stack (≤ 520 bytes for each stack item).
  • The script must not fail and result in exactly a single TRUE on the stack.

Transaction Signature Verification

BIP-143 specifies the transaction digest algorithm for version 0 witness programs. According to it, the transaction digest algorithm looks as follows:

  Double SHA256 of the serialization of:
     1. nVersion of the transaction (4-byte little endian)
     2. hashPrevouts (32-byte hash)
     3. hashSequence (32-byte hash)
     4. outpoint (32-byte hash + 4-byte little endian)
     5. scriptCode of the input (serialized as scripts inside CTxOuts)
     6. value of the output spent by this input (8-byte little endian)
     7. nSequence of the input (4-byte little endian)
     8. hashOutputs (32-byte hash)
     9. nLocktime of the transaction (4-byte little endian)
    10. sighash type of the signature (4-byte little endian)

For version 1 and 2 witness programs the algorithm is the same as specified in BIP-143 except for the fifth field scriptCode value of which depends on the type of the transaction. If the transaction is a coinbase transaction then scriptCode is 0x1976a914{20-byte-staking-pubkey-hash}88ac ( OP_DUP OP_HASH160 <20-byte-staking-pubkey-hash> OP_EQUALVERIFY OP_CHECKSIG). If the transaction has any other type

  • for RSP2WPKH (version 1) scriptCode is 0x2576a820{32-byte-spending-pubkey-hash}88ac (OP_DUP OP_SHA256 <32-byte-spending-pubkey-hash> OP_EQUALVERIFY OP_CHECKSIG).
  • for RSP2WSH (version 2):
    • if the witnessScript does not contain any OP_CODESEPARATOR, the scriptCode is the witnessScript serialized as scripts inside CTxOut.
    • if the witnessScript contains any OP_CODESEPARATOR, the scriptCode is the witnessScript but removing everything up to and including the last executed OP_CODESEPARATOR before the signature checking opcode being executed, serialized as scripts inside CTxOut. (See examples in BIP-143)

Consensus rule

To prevent the remote-staking node from spending funds in coinbase transactions the following consensus rule is required:

If a coinbase transaction contains an input with a remote-staking scriptPubKey then at least the same amount MUST be sent back to the same scriptPubKey.

Note that the reward does not have to be sent to the same script. This fact can be used to add reward address to remote-staking node settings.


The following is an example of a version 1 remote-staking scriptPubKey and corresponding witness and scriptSig.

  witness:      <signature> <pubkey>
  scriptSig:    (empty)
  scriptPubKey: 1 <20-byte-staking-key-hash> <32-byte-spending-key-hash>


SegWit vs non-SegWit

Alternatively remote staking can be implemented with the following script:

  OP_DUP OP_HASH160 <20-byte-staking-pubkey-hash> OP_EQUALVERIFY OP_CHECKSIG
  OP_DUP OP_SHA256 <32-byte-spending-pubkey-hash> OP_EQUALVERIFY OP_CHECKSIG

Where OP_PUSH_TXTYPE is a new opcode pushes the type of the transaction to the stack; OP_PUSH_TXTYPE OP_1 OP_EQUAL checks if the transaction has type TxType::COINBASE.

The segwit remote-staking program has the following advantages in comparison to the non-segwit script:

  • The segwit remote-staking program is much shorter than the non-segwit script.
  • To enforce the aforementioned consensus rule, remote-staking scripts have to be distinguished from other types of scripts. The process of identifying of non-segwit remote-staking scripts is more involved.

The downside of the segwit version is that it seems to be less flexible. For example, the else branch of the non-segwit remote-staking script can be changed to P2SH but doing so with the segwit will require the introduction of a new script version.

256-bit destination (SHA256 of a public key)

SHA256 of a public key is used to prevent the situation when users can receive funds which are stakeable by someone else. Suppose the remote-staking script has the following form:

1 <20-byte-staking-key-hash> <20-byte-spending-key-hash>

Where <20-byte-spending-key-hash> is a HASH160 of a public key, i.e. it corresponds to an ordinary address. Then the following situation might happen. Alice asks Bob to send her 0.1 UTE. Instead of sending them directly Bob creates a transaction with the following remote-staking scriptPubKey:

1 <Bob's address> <Alice's address>

This script allows Bob (and only Bob) to use the output as a stake. And it is spendable only by Alice. As a result, Alice sees that she has received money but she might not notice that she cannot stake them.

Why someone might want to do so:

  1. To receive more rewards (this scenario could also be prevented by restricting reward addresses in coin-base transactions);
  2. To acquire staking power in a cost-efficient way (for example to perform a 51% attack).

256-bit destinations do not completely prevent this scenario but make it much harder since they are not normally revealed.

Note that we do not need to introduce new 256-bit address format as the usage of 256-bit destinations SHOULD be hidden from the users.

Use cases

The main use case is the following. Suppose Alice wants to securely stake her UTEs. To do so she setups a remote-staking unit-e node (probably on some cheap hardware like Raspberry Pi) which does not own any UTEs. Then she sends her money to the following scriptPubKey:

1 <remote-staking nodes's 20-byte pubkey hash> <Alice's 32-byte pubkey hash>

After that Alice can shut down her wallet. The remote-staking node will use these UTXOs as a stake when proposing a block and send rewards back to the same scriptPubKey. Alice can spend the remote-stakeable UTXOs any time she wants.

Another use case is staking pools. But the description of staking pools is out of the scope of this UIP.

Reference implementation

Pull requests #402 and #517 implement RSP2PKH. Pull request #592 implements RSP2WSH.


  • 2019-01-17 Added a link to the reference implementation and changed the status to proposed.
  • 2019-02-21 Extended UIP with the specification of RSP2WSH.


This document and all its auxiliary files are dual-licensed under CC0 and MIT.

You can’t perform that action at this time.