Skip to content

Conversation

@domob1812
Copy link

@domob1812 domob1812 commented Sep 28, 2020

Based on the op-code changes (OP_REQUIRE_COINSTAKE) by @galpHub, this finishes the consensus-parts of the planned fork to implement staking vaults. It introduces a new time-activated fork (currently at block time 2'000'000'000, to be scheduled with a follow-up change). The changes to consensus are as follows:

  1. Blocks after the activation time will enforce OP_REQUIRE_COINSTAKE in signature verification.
  2. They also enforce new rules on the structure of coinstakes: If a coinstake is spending a vault output, the coins used for staking and the staking reward have to be paid back to the same script in a single output.
  3. From the fork, staking vault scripts are able to sign the blocks (in addition to P2PK and P2PKH scripts that are able to sign blocks before).
  4. The extra signature verification done on the coinstake in CheckProofOfStake is no longer enforcing SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS, and it is also using OP_REQUIRE_COINSTAKE.

Note that 3) and 4) implement a hard fork, that is scheduled in parallel with the script changes which by themselves would only be a soft fork. This hard fork just lifts some rules that were stricter before; so once all is through and activated for long enough, we can retro-actively remove the stricter rules until genesis and simplify the code for 3) and 4).

Copy link

@galpHub galpHub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll give it another pass tomorrow as well. Overall looks great. Just need to review the code more closely.

Copy link

@galpHub galpHub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So taking a look at the fixups, I think that - on second thought - maybe not so much a decorator of the CoinMinter but rather a decorator for the BlockFactory. I noticed that for PoS blocks the suggested changes will succeed but not so much for PoW blocks as it changes the merkle root.

In the constructor for the CoinMinter, since it receives the chain's parameters, you could instead do (pseudocode only for clarity)
blockFactory_( Params().IsRegTest() ? std::make_shared(...) : std::make_shared(...) )

@domob1812 domob1812 force-pushed the vault-upgrade branch 2 times, most recently from 984732a to 554cb5d Compare October 1, 2020 12:21
@domob1812
Copy link
Author

I've now done some more follow-up changes (in 554cb5d and the preceding commits), which separate the changes to the CoinMinter and BlockFactory for generateblock off into a specific subclass used only in that place.

Copy link

@galpHub galpHub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few rename suggestions.

@domob1812
Copy link
Author

I've applied the renaming changes in a fixup commit (will squash properly later when the review is done). I've also added a test per your suggestion for paying to another vault script.

@domob1812
Copy link
Author

domob1812 commented Nov 4, 2020

We should update this PR to be based on the ActivationManager from #46 for fork activation.

EDIT: Done.

@domob1812 domob1812 force-pushed the vault-upgrade branch 2 times, most recently from b63373c to 90a7487 Compare November 5, 2020 15:00
@domob1812 domob1812 marked this pull request as draft November 5, 2020 15:02
@domob1812 domob1812 force-pushed the vault-upgrade branch 2 times, most recently from 00751fe to 78bc15c Compare November 6, 2020 15:31
@domob1812 domob1812 force-pushed the vault-upgrade branch 2 times, most recently from 2c687bf to a79419a Compare November 11, 2020 12:57
@domob1812 domob1812 force-pushed the vault-upgrade branch 2 times, most recently from 4254e7e to 5da18a6 Compare November 17, 2020 13:50
@domob1812 domob1812 force-pushed the vault-upgrade branch 13 times, most recently from a428971 to 08b4e3f Compare November 26, 2020 14:12
This defines a new fork, to be scheduled at a future block time,
with these consensus changes:

- Once activated, verify scripts with OP_REQUIRE_COINSTAKE.
- In addition, blocks also apply the custom CheckCoinstakeForVaults
  verification routine to coinstake transactions (making sure that
  vault payments are correct, i.e. back to the vault with the right amount).

For now, the fork is scheduled for UNIX time 2000000000 (more than
a decade from now).  This will be updated to the real time later,
when the schedule has been finalised.
@domob1812 domob1812 marked this pull request as ready for review December 1, 2020 13:13
@domob1812
Copy link
Author

With the recent merge of #55 and #48, this is now quite simplified and ready for review and merging.

Extend the PoS block signing and verifying logic to accept also
signatures from vault scripts; otherwise, staking with vaults will
not actually be possible.

Note that this is a hard fork.  We activate it together with the
other (soft fork) parts at the StakingVaults activation time.
The new regtest vaultfork.py verifies behaviour around activating
the OP_REQUIRE_COINSTAKE fork with an activation time.

Once the time has been reached, new blocks will enforce the post-fork rules
(i.e. OP_REQUIRE_COINSTAKE and some extra coinstake checks).
In addition to normal signature verification done on transactions
in blocks, CheckProofOfStake by itself already verifies the
coinstake transaction's signature (presumably as some kind of
DoS protection to fail early for blocks faked with someone else's
stake).

This verification uses SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS,
which makes it impossible to implement upgrades like the vault
fork (as well as future changes) as soft forks.

This change introduces a hard fork activated together with
Fork::StakingVaults, which removes this flag and thus allows
coinstake scripts to contain upgradable NOPs.

We also add SCRIPT_REQUIRE_COINSTAKE to the flags used in
CheckProofOfStake.  Since the transaction there is always a
coinstake, this does not change anything except turn
OP_REQUIRE_COINSTAKE from a NOP to a "real" opcode.
Add tests for vault scripts in real coinstakes of blocks in the
vaultfork.py integration test.  This verifies the extra conditions
we apply to them after the fork (so the staker cannot steal coins
from a vault) as well as verifies that proper staking as the vault
is possible.
@galpHub galpHub merged commit b287ef3 into DiviProject:Development Dec 3, 2020
@domob1812 domob1812 deleted the vault-upgrade branch December 4, 2020 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants