Collateral script for pool mining

As some of you know, I’ve been working on my own collateral-based mining pool. This will just be another option along with @mhs_sam’s pool. I thought I would post my collateral box script here for public review, in case I’ve missed any obvious issues:

  val poolReward = 67500000000L
    // Case 1: block was mined by alice.
    // Either: (a) we have 1 output of value poolReward,
    // or: (b) we have 2 outputs, 1st is poolReward, 2nd goes to self.
    decodePoint(CONTEXT.minerPubKey) == alice &&
    HEIGHT > SELF.creationInfo._1 &&
    OUTPUTS(0).value == poolReward && {
      OUTPUTS.size == 1 || {
        OUTPUTS.size == 2 &&
        OUTPUTS(1).propositionBytes == SELF.propositionBytes &&
        OUTPUTS(1).creationInfo._1 == HEIGHT
  } || {
    // Case 2: anyone can top-up with more collateral funds.
    OUTPUTS(0).propositionBytes == SELF.propositionBytes &&
    OUTPUTS(0).creationInfo._1 >= SELF.creationInfo._1 &&
    OUTPUTS(0).value > SELF.value
  } || {
    // Case 3: alice can withdraw collateral at any time.

Edit: fixed a bug that would have allowed chained spends in a single block.

The main limitation of this approach is that only one unspent collateral box should exist at any time for a given miner public key, otherwise a pool can spend more than one box in the same block and claim a multiple of the reward. However, I think this is reasonable and it becomes too complex if miners have to create special signatures to avoid this. The top-up mechanism (case 2) allows anyone to top-up a given collateral box.

Another small point is that the pool reward could be adjusted to be a bit under 67.5 ERG to provide additional incentives, though I would note that the miner already gets to keep all the fees if they mine a block.

This collateral mechanism was proposed here by @scalahub back in July 2019!

The paper by @kushti and @scalahub is here.


One additional note: it might seem that (case 2) is unnecessary, since alice can spend their own collateral box to itself whenever they want. However, the case allows anyone to top up the collateral box, including the pool.

For simplicity, my pool will automatically send all pool payments to each user’s collateral. They can withdraw all or part of the collateral at any point, and this means they don’t have to keep remembering to top it up manually.

Update: I found a flaw! Thanks to a discussion with @robert for helping me realise this. The above script doesn’t prevent a chain of transactions that repeatedly spend the collateral box in the same block. We need to enforce a constraint on height to ensure that it strictly increases every time the box is spent.

HEIGHT > SELF.creationInfo._1

Someone can correct me if I’m wrong, but I think the “creation height” for a given box is specified by the creator of that box, and this is not necessarily the height of the block in which it is a mined. So an additional constraint is required to enforce a correct “creation height” to prevent chained spends.

1 Like

The top-up part is interesting addition to initial versions of the script!

on “creation height”, it is specified by the creator indeed, what’s checked by the protocol is that creationHeight <= HEIGHT . Creation height is used in storage rent.

To solve the problem of chained transactions, you can store HEIGHT of last pool-withdrawal or top-up operation in R4, and then check that HEIGHT > SELF.R4, or require for ```
OUTPUTS(1).creationInfo._1 == HEIGHT. However, please note that the check is needed for both the pool-withdrawal and top-up cases, as otherwise an attacker can insert top-up operation (w small amount) in order to clear R4 or “creationHeight”, thus creating chained pool-withdrawal -> top-up -> pool-withdrawal -> … operations .

I think the current script should protect against chaining (multiple spends in one block):

  1. When the pool claims a reward, the input box must have been created in a previous block HEIGHT > SELF.creationInfo._1, and the output box with remainder (change) must have OUTPUTS(1).creationInfo._1 == HEIGHT.
  2. In the top-up case, we don’t really mind if somebody chains these in a single block, as long as the height is never reduced, OUTPUTS(0).creationInfo._1 >= SELF.creationInfo._1.

Am I missing something?

Oh you’re right, I missed the OUTPUTS(0).creationInfo._1 >= SELF.creationInfo._1 check

I thought of a way to prevent a pool from taking a multiple of its reward in the case where a user has inadvertently created more than one collateral box. The problem with multiple collateral boxes for the same minerPubKey is that they can be spent in parallel transactions by the pool, since the only condition for spending them is that the block was mined by the specified minerPubKey.

Note that we already prevent “chained” transactions, so we just need a way to prevent “parallel” transactions, i.e. transactions that do not depend on each other.

The solution is to introduce a singleton token (a token with a value of 1) and require that one of the inputs contains this token when collecting the pool reward. A “perpetual” token would be ideal for this purpose:

1 Like

Wanted to share this recent interest in smart contract mining pools from reddit. Would be great for someone knowledgeable to chime in on discussion, and I have directed the user to this forum.


Oh hey, that is my post!

I am trying to learn as much as I can and build something functional for the Hackathon right now. I have an entry and am researching hard. The project is very much in infancy, as I am unsure of a lot of ErgoScript but in theory it should all be possible.

Here is my overview on GitHub. (no code yet.)

My thinking is that by making crowdfunding an option for pool creation, and automating pool creation with a saturation function participants can have very clear economic incentive to provide actual SECURITY to the network rather than just hoping on the biggest pool and creating a bunch of risk.

If any of you want to join the official team for the hackathon join the ErgoPlatform discord and I’ll invite you. Registration ends tonight I believe. I am very very happy to share any potential rewards :slight_smile:

1 Like