Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ testAmuletBurn = do

-- bootstrap user and service provider party
validator1 <- setupValidator app "validator1"
provider1 <- setupUser app "provider1" validator1
provider2 <- setupUser app "provider2" validator1
user <- setupUser app "user" validator1
provider1 <- setupUser app "provider1"
provider2 <- setupUser app "provider2"
user <- setupUser app "user"

advanceToIssuanceWithPrice app 0.005

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ testTransferExceedsMaxLockHolders = do
[(_, amuletRules)] <- query @AmuletRules app.dso
now <- getTime
let config = getValueAsOf now amuletRules.configSchedule
bobs <- forA [0..config.transferConfig.maxNumLockHolders] $ \i -> setupUser app ("bob_" <> show i) bobValidator.primaryParty
bobs <- forA [0..config.transferConfig.maxNumLockHolders] $ \i -> setupUser app ("bob_" <> show i)
amulet <- tap app alice 100.0
context <- getPaymentTransferContext app alice
now <- getTime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ test_designExample= do
runNextIssuance app
runAmuletDepositBots app

alice <- setupUser app "alice" app.dso
arbiter <- setupUser app "arbiter" app.dso
alice <- setupUser app "alice"
arbiter <- setupUser app "arbiter"
featureApp app arbiter

-- retrieve the config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Daml.Script
import DA.Time
import DA.Assert

import Splice.Amulet (ValidatorRight)
import Splice.Amulet.TokenApiUtils
import Splice.AmuletRules
import Splice.Scripts.Util
Expand All @@ -31,9 +30,6 @@ testExternalPartySetup = script do
validFrom = now
lastRenewedAt = now
expiresAt = proposal.preapprovalExpiresAt
-- check validator right was granted
[(rightCid, _)] <- queryFilter @ValidatorRight aliceValidator.primaryParty (\r -> r.user == externalUser.primaryParty)
rightCid === validatorRightCid

pure ()

Expand Down
45 changes: 12 additions & 33 deletions daml/splice-amulet-test/daml/Splice/Scripts/Util.daml
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,16 @@ setupUserWithoutValidatorRight app name = do
createUser (User userId (Some user)) [CanActAs user, CanReadAs app.dso]
return (AmuletUser userId user)

setupUser : AmuletApp -> Text -> Party -> Script AmuletUser
setupUser app name validator = do
setupUser : AmuletApp -> Text -> Script AmuletUser
setupUser app name = do
user <- setupUserWithoutValidatorRight app name
recordValidatorOf app user.primaryParty validator
tap app user 1.0
return user

setupSelfHostedUser: AmuletApp -> Text -> Script (AmuletUser, AmuletUser)
setupSelfHostedUser app name = do
validator <- setupValidator' app (name <> "_validator")
user <- setupUser app name validator.primaryParty
user <- setupUser app name
return (user, validator)

data DefaultAppWithUsers = DefaultAppWithUsers with
Expand All @@ -164,17 +163,11 @@ setupDefaultAppWithUsers = do
app <- setupApp
(alice, aliceValidator) <- setupSelfHostedUser app "alice"
(bob, bobValidator) <- setupSelfHostedUser app "bob"
charlie <- setupUser app "charlie" bobValidator.primaryParty
charlie <- setupUser app "charlie"
(provider1, provider1Validator) <- setupSelfHostedUser app "provider1"
(provider2, provider2Validator) <- setupSelfHostedUser app "provider2"
return DefaultAppWithUsers with ..

-- dummy argument to avoid running this script by default.
getAllValidatorRights : AmuletApp -> Script [ValidatorRight]
getAllValidatorRights _app = do
parties <- listKnownParties
map snd <$> query @ValidatorRight (map party parties)

recordValidatorOf : AmuletApp -> Party -> Party -> Script ()
recordValidatorOf app u v =
submitMulti [u, v] [] $
Expand Down Expand Up @@ -422,23 +415,19 @@ runAmuletDepositBots app = do
(openRound, _) <- getLatestOpenRound app
issuingRounds <- getOpenIssuingRounds app
let issuingRoundNumbers = map (._2.round) issuingRounds
let mkContext validatorRights = TransferContext with
let transferContext = TransferContext with
openMiningRound = openRound
issuingMiningRounds = Map.fromList [ (round.round, roundCid) | (roundCid, round) <- issuingRounds ]
validatorRights
validatorRights = Map.empty
featuredAppRight = None
-- iterate over all validator rights to use the right readAs values
-- TODO(M4-82): remove the need for reading as the validator
allValidatorRights <- getAllValidatorRights app
forA_ allValidatorRights $ \validatorRight -> do
-- get all burns for this user
let user = validatorRight.user
validatorRights <- getValidatorRights user
allParties <- listKnownParties
forA_ allParties $ \partyDetails -> do
let user = partyDetails.party
appRewardCoupons <- queryFilter @AppRewardCoupon app.dso $ \c ->
c.round `elem` issuingRoundNumbers && fromOptional c.provider c.beneficiary == user

validatorRewardCoupons <- queryFilter @ValidatorRewardCoupon app.dso $ \c ->
c.round `elem` issuingRoundNumbers && c.user `Map.member` validatorRights
c.round `elem` issuingRoundNumbers && c.user == user

validatorFaucetCoupons <- queryFilter @ValidatorFaucetCoupon app.dso $ \c ->
c.round `elem` issuingRoundNumbers && c.validator == user
Expand All @@ -451,10 +440,6 @@ runAmuletDepositBots app = do

-- get all amulets of this user
amulets <- getAmuletInputs user
-- Need readAs rights for all hosted users to collect their validator rewards,
-- and readAs rights for the validator to see mining round state contracts
-- TODO(M4-82): remove the need for reading as the validator
let readAs = Map.keys validatorRights ++ [validatorRight.validator]
-- merge multiple of them into a single amulet to minimize the holding fees
let transfer = Transfer with
sender = user
Expand All @@ -470,9 +455,9 @@ runAmuletDepositBots app = do
beneficiaries = None -- no beneficiaries for self-transfer
-- merge multiple amulets or rewards and claim rewards even if there are no amulets yet
when (length transfer.inputs > 1 || (length transfer.inputs == 1 && null amulets)) $ void $
submitExerciseAmuletRulesByKey app [user] readAs AmuletRules_Transfer with
submitExerciseAmuletRulesByKey app [user] [] AmuletRules_Transfer with
transfer
context = mkContext validatorRights
context = transferContext
expectedDso = Some app.dso

-- sanity check: test that the amulet deposit bot merged all amulets
Expand All @@ -494,12 +479,6 @@ getOpenIssuingRounds app = do
miningRounds <- query @IssuingMiningRound app.dso
return [ (cid, r) | (cid, r) <- miningRounds, r.opensAt <= now ]

-- | All validator rights for the given user.
getValidatorRights : Party -> Script (Map.Map Party (ContractId ValidatorRight))
getValidatorRights validator = do
rights <- queryFilter @ValidatorRight validator (\right -> right.validator == validator)
return $ Map.fromList [ (right.user, rightCid) | (rightCid, right) <- rights ]

-- Primarily used by submitters to decide against which round they should try to transact.
getLatestOpenRound : AmuletApp -> Script (ContractId OpenMiningRound, OpenMiningRound)
getLatestOpenRound app = do
Expand Down
38 changes: 17 additions & 21 deletions daml/splice-amulet/daml/Splice/Amulet.daml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ data SvRewardCoupon_ArchiveAsBeneficiaryResult = SvRewardCoupon_ArchiveAsBenefic

data UnclaimedActivityRecord_ArchiveAsBeneficiaryResult = UnclaimedActivityRecord_ArchiveAsBeneficiaryResult

data UnclaimedActivityRecord_DsoExpireResult = UnclaimedActivityRecord_DsoExpireResult with
data UnclaimedActivityRecord_DsoExpireResult = UnclaimedActivityRecord_DsoExpireResult with
unclaimedRewardCid : ContractId UnclaimedReward

-- | A amulet, which can be locked and whose amount expires over time.
Expand Down Expand Up @@ -191,7 +191,9 @@ template LockedAmulet
-- Contracts to implement reward issuance
-- ======================================

-- | The right to claim amulet issuances for a user's burns as their validator.
-- | Deprecated, since users collect their own validator rewards.
--
-- It was used to represent the right to claim amulet issuances for a user's burns as their validator.
template ValidatorRight with
dso : Party
user : Party
Expand All @@ -207,8 +209,6 @@ template ValidatorRight with
controller user
do return ValidatorRight_ArchiveAsUserResult

-- TODO(M3-90): cancellation, withdrawal


-- | The right for an application provider to earn featured app rewards.
template FeaturedAppRight with
Expand Down Expand Up @@ -336,14 +336,12 @@ template ValidatorRewardCoupon


choice ValidatorRewardCoupon_ArchiveAsValidator : ValidatorRewardCoupon_ArchiveAsValidatorResult
-- ^ This choice is used by validators to archive the burn receipt upon claiming its corresponding issuance.
-- ^ This choice was used by validators to archive the burn receipt upon claiming its corresponding issuance.
with
validator : Party
rightCid : ContractId ValidatorRight
controller dso, validator
do
requireMatchingContract rightCid (ValidatorRight with dso; validator, user)
return ValidatorRewardCoupon_ArchiveAsValidatorResult
do fail "ValidatorRewardCoupon_ArchiveAsValidator: disabled, as users collect their rewards directly"


-- | A coupon for a beneficiary to receive part of the SV issuance for a specific SV node and round.
Expand Down Expand Up @@ -390,29 +388,29 @@ template UnclaimedReward with

signatory dso

-- | A record of activity that can be minted by the beneficiary.
-- Note that these do not come out of the per-round issuance but are instead created by burning
-- UnclaimedRewardCoupon as defined through a vote by the SVs. That's also why expiry is a separate
-- | A record of activity that can be minted by the beneficiary.
-- Note that these do not come out of the per-round issuance but are instead created by burning
-- UnclaimedRewardCoupon as defined through a vote by the SVs. That's also why expiry is a separate
-- time-based expiry instead of being tied to a round like the other activity records.
template UnclaimedActivityRecord
with
dso : Party
beneficiary : Party -- ^ The owner of the `Amulet` to be minted.
amount : Decimal -- ^ The amount of `Amulet` to be minted.
reason : Text -- ^ A reason to mint the `Amulet`.
expiresAt : Time -- ^ Selected timestamp defining the lifetime of the contract.
where
reason : Text -- ^ A reason to mint the `Amulet`.
expiresAt : Time -- ^ Selected timestamp defining the lifetime of the contract.
where
signatory dso
observer beneficiary
ensure amount > 0.0

choice UnclaimedActivityRecord_DsoExpire : UnclaimedActivityRecord_DsoExpireResult
controller dso
do
do
assertDeadlineExceeded "UnclaimedActivityRecord.expiresAt" expiresAt
unclaimedRewardCid <- create UnclaimedReward with dso; amount
pure UnclaimedActivityRecord_DsoExpireResult with unclaimedRewardCid


requireAmuletExpiredForAllOpenRounds : ContractId OpenMiningRound -> Amulet -> Update ()
requireAmuletExpiredForAllOpenRounds roundCid amulet = do
Expand All @@ -439,10 +437,8 @@ instance HasCheckedFetch AppRewardCoupon ForOwner where
instance HasCheckedFetch SvRewardCoupon ForOwner where
contractGroupId SvRewardCoupon{..} = ForOwner with dso; owner = beneficiary

-- This instance is slightly dangerous, as it could lead to a missed check of the validator.
-- We accept this, as at least the DSO party check is done, and the remainder is careful coding.
instance HasCheckedFetch ValidatorRewardCoupon ForDso where
contractGroupId ValidatorRewardCoupon {..} = ForDso with dso
instance HasCheckedFetch ValidatorRewardCoupon ForOwner where
contractGroupId ValidatorRewardCoupon {..} = ForOwner with dso; owner = user

instance HasCheckedFetch UnclaimedReward ForDso where
contractGroupId UnclaimedReward {..} = ForDso with dso
Expand All @@ -454,4 +450,4 @@ instance HasCheckedFetch FeaturedAppActivityMarker ForDso where
contractGroupId FeaturedAppActivityMarker {..} = ForDso with dso

instance HasCheckedFetch UnclaimedActivityRecord ForOwner where
contractGroupId UnclaimedActivityRecord{..} = ForOwner with dso; owner = beneficiary
contractGroupId UnclaimedActivityRecord{..} = ForOwner with dso; owner = beneficiary
32 changes: 7 additions & 25 deletions daml/splice-amulet/daml/Splice/AmuletRules.daml
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,6 @@ data TransferContextSummary = TransferContextSummary with
config : TransferConfig Amulet
openRound : OpenMiningRound
issuingMiningRounds : Map Round IssuingMiningRound
validatorRights : Map Party (ContractId ValidatorRight)
deriving (Eq, Show)

data TransferInputsSummary = TransferInputsSummary with
Expand Down Expand Up @@ -806,23 +805,11 @@ summarizeAndValidateContext context dso tf = do
assertDeadlineExceeded ("issuingRound[" <> show round.number <> "].opensAt") issuingRound.opensAt
pure (round, issuingRound)

-- pre-resolve validator rights
validatorRights <- forA (Map.toList context.validatorRights) $ \(user, rightCid) -> do
requireMatchingContract rightCid (ValidatorRight with dso; validator = tf.sender; user)
pure (user, rightCid)

return TransferContextSummary with
config = scaleFees (1.0 / openRound.amuletPrice) openRound.transferConfigUsd
featuredAppProvider
openRound = openRound
issuingMiningRounds = Map.fromList issuingMiningRounds
validatorRights = Map.fromList validatorRights

getValidatorRight : TransferContextSummary -> Party -> Update (ContractId ValidatorRight)
getValidatorRight csum user =
case Map.lookup user csum.validatorRights of
None -> abort $ "TransferContext did contain validator right for user: " <> show user
Some rightCid -> pure rightCid

getIssuingMiningRound : TransferContextSummary -> Round -> Update IssuingMiningRound
getIssuingMiningRound csum round = do
Expand Down Expand Up @@ -884,12 +871,7 @@ summarizeAndConsumeInputs csum dso sender inps = do

summarizeAndConsumeInput _round s (InputValidatorRewardCoupon couponCid) = do
-- we must and do use the validator right to archive the coupon of the user
coupon <- fetchButArchiveLater (ForDso with dso) couponCid
do
rightCid <- getValidatorRight csum coupon.user
exercise couponCid ValidatorRewardCoupon_ArchiveAsValidator with
validator = sender
rightCid
coupon <- fetchAndArchive forOwner couponCid
-- compute balance change
miningRound <- getIssuingMiningRound csum coupon.round
return TransferInputsSummary with
Expand Down Expand Up @@ -1207,7 +1189,7 @@ data TransferContext = TransferContext
with
openMiningRound : ContractId OpenMiningRound
issuingMiningRounds : Map Round (ContractId IssuingMiningRound)
validatorRights : Map Party (ContractId ValidatorRight) -- ^ Map from user to ValidatorRight contract.
validatorRights : Map Party (ContractId ValidatorRight) -- ^ Deprecated since users collect their rewards directly. Set to the empty map.
featuredAppRight : Optional (ContractId FeaturedAppRight) -- ^ Optional proof that the provider is a featured app provider.
deriving (Show, Eq)

Expand Down Expand Up @@ -1390,18 +1372,16 @@ template ExternalPartySetupProposal
controller user
do
assertWithinDeadline "ExternalPartySetupProposal.preapprovalExpiresAt" preapprovalExpiresAt
validatorRightCid <- create ValidatorRight with
dso
validator
user
transferPreapprovalCid <- create TransferPreapproval with
receiver = user
provider = validator
dso
validFrom = createdAt
lastRenewedAt = createdAt
expiresAt = preapprovalExpiresAt
return ExternalPartySetupProposal_AcceptResult with ..
return ExternalPartySetupProposal_AcceptResult with
validatorRightCid = coerceContractId self -- Use self as dummy contract-id, as we must set a value.
transferPreapprovalCid

-- users can always reject the proposal
choice ExternalPartySetupProposal_Reject : ExternalPartySetupProposal_RejectResult
Expand All @@ -1420,6 +1400,8 @@ template ExternalPartySetupProposal
data ExternalPartySetupProposal_AcceptResult = ExternalPartySetupProposal_AcceptResult
with
validatorRightCid : ContractId ValidatorRight
-- ^ Deprecated. This was the ValidatorRight contract-id, but now contains a dummy contract-id,
-- as no ValidatorRight is created for the user.
transferPreapprovalCid : ContractId TransferPreapproval
deriving (Show, Eq)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ testUnclaimedRewardsMerging : Script ()
testUnclaimedRewardsMerging = do
(app, _, (sv1, _, _, _)) <- initDevNet

-- onboard a validator
validator1 <- setupValidator app "validator1"
provider1 <- setupUser app "provider1" validator1
provider1 <- setupUser app "provider1"

forA_ [1..6] do \_ -> generateUnclaimedReward app provider1

Expand Down Expand Up @@ -151,7 +149,7 @@ testDecentralizedAns : Script ()
testDecentralizedAns = do
(app, dso, (sv1, sv2, sv3, sv4)) <- initDevNet

alice <- setupUser app "alice" app.dso
alice <- setupUser app "alice"

[(dsoRulesCid, _)] <- query @DsoRules dso
[(ansRulesCid, _)] <- query @AnsRules dso
Expand Down Expand Up @@ -284,7 +282,7 @@ terminatedSubscriptionCanBeCleanedUp : Script ()
terminatedSubscriptionCanBeCleanedUp = script do
(app, dso, (sv1, _, _, _)) <- initDevNet

alice <- setupUser app "alice" app.dso
alice <- setupUser app "alice"

[(dsoRulesCid, _)] <- query @DsoRules dso
[(ansRulesCid, _)] <- query @AnsRules dso
Expand Down Expand Up @@ -338,7 +336,7 @@ testTransferPreapprovalSend : Script ()
testTransferPreapprovalSend = do
(app, dso, (sv1, sv2, sv3, _)) <- initDevNet
validator <- setupValidator app "validator"
alice <- setupUser app "alice" validator
alice <- setupUser app "alice"
externalParty <- allocateParty "externalParty"
(externalPartyAmuletRulesCid, _) <- getExternalPartyAmuletRules app
now <- getTime
Expand Down
6 changes: 3 additions & 3 deletions daml/splice-wallet-test/daml/Splice/Scripts/TestWallet.daml
Original file line number Diff line number Diff line change
Expand Up @@ -908,9 +908,9 @@ testInsufficientFundsBatchSubscriptions = script do
runAmuletDepositBots app

validator <- setupValidator app "validator1"
alice <- setupUser app "alice" validator
pizzeria <- setupUser app "pizzeria" validator
provider <- setupUser app "la_famiglia" validator
alice <- setupUser app "alice"
pizzeria <- setupUser app "pizzeria"
provider <- setupUser app "la_famiglia"

install <- submitMulti [alice.primaryParty, validator] [] $ createCmd $ WalletAppInstall with
endUserParty = alice.primaryParty
Expand Down
Loading
Loading