Skip to content

Instantly share code, notes, and snippets.

@nothingmuch
Last active May 11, 2018 23:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nothingmuch/683042343c48a4ef07efd3d438e7ee56 to your computer and use it in GitHub Desktop.
Save nothingmuch/683042343c48a4ef07efd3d438e7ee56 to your computer and use it in GitHub Desktop.

payment channel construction for block reward, where hub + miners control the output, but with the expectation is that hub eventually claims the entire sum, by settling up using other funds, so as to not require every miner participating in a pool to be named explicitly in the coinbase output.

  • miner pubkeys are X_i = x_i * G where i = 1 .. n, hub pubkey is P = p * G
  • blinding factor b = H( P || X_1 || ... || X_n ) (|| is concatenation)
  • combined secret key x = b * p + b * x_1 + ... + b * x_n (* and + denote scalar operations)
  • combined public key X = b * P + b * X_1 + ... + b * X_n (group operations)

assuming hub has n payment channels, one with each miner, all parties can agree on a coinbase output script:

IF   <X> CHECKSIG
ELSE <X_1> CHECKSIGVERIFY <H(k)> HASH256 EQUAL
ENDIF

such that if a block with this output is mined, then the hub can withdraw unilaterally by revealing k, or the hub can withdraw unilaterally by signing with x.

Before a miner includes this in their block template, the hub commits the channel state with payment for that miner's share of this coinbase output, based on their sharechain balance. If the pool unilaterally redeems the coin rewards, the miner can claim the funds given k. Assuming the miner's pubkey on the channel is M, the redemption path for the miner should include a forced disclosure checksig (@fivepiece provided some clarifications and corrections, as well as the magic nonce, which I've since misplaced):

IF   <M> CHECKSIGVERIFY <H(k)> HASH256 EQUAL
ELSE <2> <M> <P> <2> CHECKMULTISIGVERIFY OP_SIZE 60 LESSTHANOREQUAL VERIFY <X_i> CHECKSIG
ENDIF

If a block with the above output is found, since k is the same the miner can unilaterally redeem the payment channel commitment, if the hub claims the reward.

At this point the hub can sign their part of the multisig branch, allowing the miner to redeem that by providing their part of the multisig along with a signature corresponding to X_i, with a DER encoding of a signature that is 60 or fewer bytes, which implies a known known nonce resulting in small values of r and s must be used, disclosing x_i if the miner claims the channel funds.

The miner can then hand off x_i to the hub, and they can re-negotiate a settlement transaction for the channel that does not publish it. This state must also invalidate the previous state, in case k is revealed, so the above script is incomplete and requires additional branches, and a locktime on the preimage path.

When all miners have submitted their x_i, the pool can compute x and spend the block rewards without revealing k, and with only 1 signature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment