Sessions

Sessions

A Brollup state transition involves four subsequent sessions;

  1. Entry Signing Session; This session sums individual signatures from msg.senders of the round and results in an aggregate signature to authorize the payload.

  2. Covenant Signing Session This session sums individual signatures from msg.senders of the round and results in an aggregate signature to constrain payable VTXOs to the shared output.

  3. Forfeiting Session This session forfeits VTXOs from msg.senders of the round to cover transaction fees and payable VTXOs.

Entry Signing Session

Accounts that are initiating calls or deploying contracts initially participate in this session to aggregate their signatures in coordination with the operator. This session employs a straightforward, single-round aggregation scheme where each msg.sender signs their own version, with the signature committing to H(m) rather than H(R || P || m). This allows the operator to simply sum all signatures in a single round. The resulting signature is a 64-byte Schnorr signature, which is batch-verified within the Brollup context.

  +--------------+                                      +--------------+
  |              |--(1)---       entryCtx         ----->|              |
  |              |<-(2)---       entryAck         ------|              |
  |              |                                      |              |
  |  msg.sender  |     // wait until the operator       |   operator   |
  |              |     // aggregates all entries        |              |
  |              |                                      |              |
  |              |<-(3)---      payloadCtx        ------|              |
  +--------------+                                      +--------------+

(1) msg.sender creates a entryCtx, and requests to join the round;

let entryCtx = (prevHash, npub, entry, sig), where;

  • prevHash is the hash of previous Brollup state

  • nsec is secret key of the msg.sender

  • npub is the public key of the msg.sender; nsec • G

  • entry is the non-compact bytecode of the entry that msg.sender intends to transact;

account id (32 bytes) || contract id (32 bytes) || method call (1 byte) || calldata (varsize)
  • let message = TaggedHash(bytes(prevHash || entry), “SighashEntry”)

  • let nonce = TaggedHash(bytes(message || nsec), “DeterministicNonce”)

  • let sig = (nonce • G, (nonce + message • nsec) mod n)

(2) operator responds with an acknowledge message, entryAck.

(3) The operator gathers all entries, sums the signatures, and responds with payloadCtx;

  • let aggpub = nsec1 • G + nsec2 • G .. nsecN • G

  • let aggmsg = m1 + m2 .. mN

  • let aggnonce = 𝑘1 • G + 𝑘2 • G .. 𝑘N • G

  • let aggcmt = (𝑘1 + m1 • nsec1) + (𝑘2 + m2 • nsec2) … (𝑘N + mN • nsecN)

  • let aggsig = (aggnonce, aggcmt)

  • let payloadCtx = (prevHash, npubs[], entries[], fee, aggsig)

At the end of the round, based on the list of entries[] and the fee provided, msg.senders can deterministically see the outcome of their execution and determine the precise amount they need to pay for the execution.

If the outcome of the execution results in an asserted failure in the contract logic, the msg.sender is removed from the round. This prevents failed transactions from being included in blocks, thereby saving space and fees.

Covenant Signing Session

Accounts that pass the entry signing session move into this session to constrain payable VTXOs to the shared output. This session employs a Musig2-based two-round aggregation scheme, where msg.senders aim to produce an aggregate signature from the aggregate key. The resulting signature is a 64-byte valid BIP-340 Schnorr signature.

  +--------------+                                      +--------------+
  |              |--(1)---      signerCtx         ----->|              |
  |              |<-(2)---     covenantCtx        ------|              |
  |              |--(3)---      pubnonce          ----->|              |
  |              |                                      |              |
  |              |     // wait until the operator       |              |
  |              |     // aggregates all pubnonces      |              |
  |  msg.sender  |                                      |   operator   |
  |              |<-(4)---      aggnonce          ------|              |
  |              |--(5)---     partialsig         ----->|              |
  |              |                                      |              |
  |              |    // wait until all signers         |              |
  |              |    // respond with partial sigs      |              |
  |              |                                      |              |
  |              |<-(6)---       aggsig           ------|              |
  +--------------+                                      +--------------+

(0) Given payloadCtx from the earlier session, msg.sender computes the aggregate key aggkey;

  • let (prevHash, msg.senders[], _, _, _) = payloadCtx

  • let keyaggCtx = KeyAgg(msg.senders[]) => (Q, gacc, tacc)

  • Let (aggkey, _, _) = keyaggCtx

(1) msg.sender joins the round with signerCtx;

  • let signerCtx = (prevHash, npub)

(2) operator returns covenantCtx;

let covenantCtx = (outpoint_self, spks[], values[]), where;

  • outpoint_self is the prevout that contains the aggregate key, from which msg.senders aim to produce an aggregate signature.

  • spks[] is an array of scriptPubKeys containing the payable VTXOs

  • values[] is an array nValues containing the payable VTXO amounts.

(3) msg.sender prepares and responds with pubnonce;

  • let (secnonce, pubnonce) = NonceGen(nsec, npub)

(4) operator aggregares pubnonces, and responds with aggnonce; NonceAgg(pubnonce1 .. pubnonceN) => aggnonce

(5) msg.sender signs and responds with partial signature partialsig;

  • let sighash = ReturnSighashCov(covenantCtx)

  • let sessionCtx = (aggnonce, aggkey, sighash)

  • let partialsig = Sign(secnonce, nsec, sessionCtx) => partialsig

(6) operator responds with aggregate signature aggsig;

  • let aggsig = PartialSigAgg(psig1 .. psigN, sessionCtx) => aggsig

Last updated