Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 160 additions & 8 deletions casper/src/main/resources/Pos.rhox
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ new
deployerId(`rho:rchain:deployerId`),
systemContractManagerCh,
dispatcherCh,
configPublicKeyCheckCh
configPublicKeyCheckCh,
stdout(`rho:io:stdout`)
in {
// Simultaneously retrieves RevVault, ListOps, TreeHashMap, and MultiSigRevVault contracts from the registry.
registryLookup!(`rho:rchain:revVault`, *revVaultCh) |
Expand Down Expand Up @@ -179,7 +180,8 @@ in {
for (@initialActive <- initialActiveCh;
@(true, _) <- moveInitialBondCh) {
new stateCh, rewardsInfo, calTotalActiveBonds,
accumulateSndNum, accumulateFstOfSndArg, accumulateItemInState in {
accumulateSndNum, accumulateFstOfSndArg, accumulateItemInState,
bStateCh in {
// Initializes PoS state structure.
stateCh!({
// Map[PublicKey, Int] - each validator stake
Expand All @@ -198,6 +200,8 @@ in {
"randomImages" : {},
"randomNumbers" : {},
}) |
// bonding requests state contains empty set
bStateCh!([].toSet()) |
contract rewardsInfo(retCh) = {
new posBalanceCh, totalActiveBondCh, totalBondCh, totalWithdrawCh, committedRewardsCh in {
@posVault!("balance", *posBalanceCh) |
Expand Down Expand Up @@ -331,13 +335,11 @@ in {
new userCh, depositCh,
processCh
in {
runMVar!(*stateCh, *processCh, *returnCh) |
runMVar!(*bStateCh, *processCh, *returnCh) |
getUser!(deployerId, *userCh) |
for (@state, resultCh <- processCh &
@userPk <- userCh) {
if (state.get("allBonds").contains(userPk)) {
resultCh!(state, (false, "Public key is already bonded."))
} else if (amount < $$minimumBond$$) {
if (amount < $$minimumBond$$) {
resultCh!(state, (false, "Bond is less than minimum!"))
} else if (amount > $$maximumBond$$) {
resultCh!(state, (false, "Bond is greater than maximum!"))
Expand All @@ -348,7 +350,7 @@ in {
match depositResult {
// If deposit is successful, the user becomes a bonded validator.
(true, _) => {
resultCh!(state.set("allBonds", state.get("allBonds").set(userPk, amount)), depositResult)
resultCh!(state.union(Set((userPk, amount))), depositResult)
}
// If deposit is unsuccessful, the user is not bonded.
(false, errorMsg) => {
Expand Down Expand Up @@ -505,6 +507,157 @@ in {
}
}
} |
// Private method which are executed on top of each new fringe
contract PoS(@"newFringe", @sysAuthToken, ackCh) = {
new isValidTokenCh in {
sysAuthTokenOps!("check", sysAuthToken, *isValidTokenCh) |
for (@isValid <- isValidTokenCh) {
if (isValid) {
// Epoch change occurs.
new payWithdrawer, removeQuarantinedWithdrawers,
stateProcessCh, paymentDoneCh,
accDepositsDoneCh, commitRewardsCh,
newValidatorsCh, removeQuarantinedCh, currentEpochRewardCh,
commitCurrentEpochRewards, updatedRewardsCh, movePendingWithdrawCh,
movePendingWithdrawer, addToBodsMap, newBondsMapCh
in {
stdout!("newFringe") |
PoS!("getCurrentEpochRewards", *currentEpochRewardCh) |
for (@currentRewards <- currentEpochRewardCh) {
stdout!("currentEpochRewardCh") |
stdout!(currentRewards) |
runMVar!(*stateCh, *stateProcessCh, *ackCh) |
for (@state, stateUpdateCh <- stateProcessCh) {
// 1. Calculate all the validator current epoch rewards based on active validator bonding proportion
// 2. Accumulate `committedRewards` with the result of step 1
stdout!("state, stateUpdateCh") |
commitCurrentEpochRewards!(state, currentRewards, *updatedRewardsCh) |
for (@newCommittedState <- updatedRewardsCh) {
stdout!(newCommittedState) |
stdout!("newCommittedState") |
// 3. Update `withdrawers` according to `allBonds` and `pendingWithdrawers`
// when pendingWithdrawers is not empty, remove the validator in `allBonds`
movePendingWithdrawer!(newCommittedState, *movePendingWithdrawCh) |
for (@newMovedPendingState <- movePendingWithdrawCh){
stdout!("newMovedPendingState") |
stdout!(newMovedPendingState) |
// 4. When the block number reaches the quantinue of `withdrawers` ,
// transfer the corresponding bonds+ rewards to the corresponding validator from posVault.
// 5. update `pendingWithdrawers` to empty Map {}.
removeQuarantinedWithdrawers!(0, newMovedPendingState, *removeQuarantinedCh) |
for (@newRemovedQuantinueState <- removeQuarantinedCh) {
// 6. Put requests for bonding into a bonds map TODO this is not really needed
stdout!("newRemovedQuantinueState") |
stdout!(newRemovedQuantinueState) |
for (@bRequests <<- bStateCh) {
stdout!("bRequests") |
stdout!(bRequests) |
addToBodsMap!(newRemovedQuantinueState, bRequests, *newBondsMapCh) |
for (@newBondsMap <- newBondsMapCh) {
// 7. Pick new `activeValidators`
stdout!("newBondsMap") |
stdout!(newBondsMap) |
pickActiveValidators!(newBondsMap.get("allBonds").toList(), *newValidatorsCh) |
for (@newValidators <- newValidatorsCh) {
stdout!("newValidators") |
stdout!(newValidators) |
stateUpdateCh!(newBondsMap.set("activeValidators", newValidators), (true, Nil))
}
}
}
}
}
}
}
} |
// Transfers withdrawing validator's bond + accumulated rewards from PoS vault to their vault.
contract payWithdrawer(@(pk, amount), returnCh) = {
new vaultCh, revAddressCh, createCh, posAuthKeyCh in {
revAddressOps!("fromPublicKey", pk, *revAddressCh) |
@RevVault!("unforgeableAuthKey", posVaultUnf, *posAuthKeyCh) |
for (@toRevAddress <- revAddressCh; @posAuthKey <- posAuthKeyCh) {
@RevVault!("findOrCreate", toRevAddress, *createCh) |
for (@_ <- createCh){
@posVault!("transfer", toRevAddress, amount, posAuthKey, *returnCh)
}
}
}
} |
contract addToBodsMap(@state, @bondRequests, returnCh) = {
new accumulate in {
stdout!("accumulate") |
@ListOps!("fold", bondRequests.toList(), state, *accumulate, *returnCh) |
contract accumulate(@(pk, bond), @s, resultCh) = {
stdout!("step") |
if (s.get("allBonds").contains(pk)) {
resultCh!(s)
} else {
resultCh!(s.set("allBonds", s.get("allBonds").set(pk, bond)))
}
}
}
} |
contract commitCurrentEpochRewards(@state, @currentRewards, returnCh) = {
new accumulate in {
@ListOps!("fold", currentRewards.toList(), state, *accumulate, *returnCh) |
contract accumulate(@(pk, reward), @updatedState, resultCh) = {
resultCh!(updatedState.set("committedRewards",
updatedState.get("committedRewards").set(pk, updatedState.get("committedRewards").getOrElse(pk, 0) + reward)))
}
}
} |
contract movePendingWithdrawer(@state, returnCh) = {
new movePending in {
@ListOps!("fold", state.get("pendingWithdrawers").toList(), state, *movePending, *returnCh) |
contract movePending(@(pk, quantine), @updatedState, resultCh) = {
resultCh!(updatedState
.set("withdrawers", updatedState.get("withdrawers").set(pk, (updatedState.get("allBonds").get(pk), quantine)))
.set("allBonds", updatedState.get("allBonds").delete(pk))
.set("pendingWithdrawers", updatedState.get("pendingWithdrawers").delete(pk))
)
}
}
} |
// Checks withdrawer's quarantine period against current block number,
// then computes their payment, removes them from the bonds and withdrawers maps, and
// updates the committed rewards map.
contract removeQuarantinedWithdrawers(@currentBlockNumber, @state, returnCh) = {
new quarantinedValidatorsCh, validatorsToWithdrawListCh,
isQuarantineFinished, notWithdrawn, payWithdraw,
newBondsListCh, newWithdrawersListCh,
computeRemove, payRet
in {
// Calculate rewards by taking PoS balance on PoS vault and subtract all active stake + newly bonded
@ListOps!("filter", state.get("withdrawers").toList(), *isQuarantineFinished, *quarantinedValidatorsCh) |
for (@quarantinedValidators <- quarantinedValidatorsCh) {
@ListOps!("unorderedParMap", quarantinedValidators, *payWithdraw, *payRet) |
contract payWithdraw(@(pk, (bonds, quantine)), resultCh) = {
// FIXME fix transfer in failure case
payWithdrawer!((pk, bonds + state.get("committedRewards").getOrElse(pk, 0)), *resultCh)
} |
for (@_ <- payRet) {
@ListOps!("fold", quarantinedValidators, state, *computeRemove, *returnCh) |
contract computeRemove(@(pk, (bonds, quantine)), @updatedState, resultCh) = {
resultCh!(updatedState
.set("committedRewards", updatedState.get("committedRewards").delete(pk))
.set("withdrawers", updatedState.get("withdrawers").delete(pk))
)
}
}
} |
// Check whether quarantine period is finished.
contract isQuarantineFinished(@(pk, (bonds, blockNumber)), resultCh) = {
resultCh!(currentBlockNumber >= blockNumber)
}
}
}
}
} else {
ackCh!((false, "Invalid system auth token"))
}
}
}
} |
// Private method which signals the end of block processing.
contract PoS(@"closeBlock", @sysAuthToken, ackCh) = {
new isValidTokenCh in {
Expand Down Expand Up @@ -630,7 +783,6 @@ in {
}
}
} |
//
contract PoS(@"commitRandomImage", @deployerId, @hash, ackCh) = {
new userCh, mvarCh in {
getUser!(deployerId, *userCh) |
Expand Down
Loading