Skip to content

Commit

Permalink
Merge pull request #7 from patriacaelum/remove-broker-class-and-use-w…
Browse files Browse the repository at this point in the history
…allet

Remove broker class and use wallet
  • Loading branch information
patriacaelum authored Oct 20, 2021
2 parents dfe8245 + 51c9232 commit af46910
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 98 deletions.
158 changes: 78 additions & 80 deletions parameterized/proposal_inverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,72 @@ def generate_eth_account():

class Wallet(pm.Parameterized):
funds = pm.Number(100)

def __init__(self, **params):
super(Wallet, self).__init__(**params)
(private, public) = generate_eth_account()
self.private = private
self.public = public

def _default_agreement_contract_params(self):
params = dict(
min_stake = 5,
epoch_length = 60*60*24,
min_epochs = 28,
allocation_per_epoch = 10,
min_horizon = 7,
min_brokers = 1,
max_brokers = 5,
)
return params

def deploy(self, initial_funds, **agreement_contract_params):
"""
An actor within the ecosystem can deploy a new agreement contract by specifying which proposal the agreement
supports, setting the parameters of the smart contract providing initial funds, and providing any (unenforced)
commitment to continue topping up the contract as payer under as long as a set of SLAs are met. For the purpose
of this draft, it is assumed that the contract is initialized with some quantity of funds F such that H>Hmin
and that B=∅.
"""
params = self._default_agreement_contract_params()
params.update(agreement_contract_params)

# Check imposed restrictions (whether horizon is greater than the min horizon)
horizon = initial_funds / params['allocation_per_epoch']
if horizon < params['min_horizon']:
print("The Horizon is lower than the mininum required horizon")
return None

agreement_contract = ProposalInverter(
owner = self,
initial_funds = initial_funds,
**params,
)

return agreement_contract

class Broker(Wallet):
pass
def cancel(self, agreement_contract, broker_pool):
"""
In the event that the owner closes down a contract, each Broker gets back their stake, and recieves any
unclaimed tokens allocated to their address as well an equal share of the remaining unallocated assets.
That is to say the quantity Δdi of data tokens is distributed to each broker i∈B
Δdi=si+ai+(R/N)
and thus the penultimate financial state of the contract is
S=0, R=0, A=0
when the contract is self-destructed.
"""
# This function relies on there being given a broker_pool that keeps track of brokers

# Calculate the total allocated funds & total stake for proper calculation
agreement_contract.cancel(self.public)

for broker_key in broker_pool:
broker_pool[broker_key] = agreement_contract.claim_broker_funds(broker_pool[broker_key])

return broker_pool


class BrokerAgreement(pm.Parameterized):
"""
Stores data about a broker in the proposal inverter.
Expand Down Expand Up @@ -60,7 +115,7 @@ def __init__(self, owner: Wallet, initial_funds: float, **params):

self.committed_brokers = set()

def add_broker(self, broker: Broker, stake: float):
def add_broker(self, broker: Wallet, stake: float):
"""
A broker can join the agreement (and must also join the stream associated with that agreement) by staking the
minimum stake.
Expand Down Expand Up @@ -91,7 +146,7 @@ def add_broker(self, broker: Broker, stake: float):

return broker

def claim_broker_funds(self, broker: Broker):
def claim_broker_funds(self, broker: Wallet):
"""
A broker that is attached to an agreement can claim their accumulated rewards at their discretion.
Expand All @@ -117,7 +172,7 @@ def claim_broker_funds(self, broker: Broker):

return broker

def remove_broker(self, broker: Broker):
def remove_broker(self, broker: Wallet):
"""
In the event that the horizon is below the threshold or a broker has been attached to the agreement for more than
the minimum epochs, a broker may exit an agreement and take their stake (and outstanding claims).
Expand Down Expand Up @@ -162,7 +217,7 @@ def iter_epoch(self, n_epochs=1):

# If the forced cancellation conditions are met for a period longer than the buffer period, trigger the cancel function
if (self.current_epoch - self.cancel_epoch) > self.buffer_period:
self.cancel()
self.cancel(self.owner_address)

self.current_epoch += 1

Expand All @@ -184,7 +239,7 @@ def get_horizon(self):
"""
return (self.funds - self.get_allocated_funds()) / self.allocation_per_epoch

def pay(self, broker: Broker, tokens):
def pay(self, broker: Wallet, tokens):
"""
A payer takes the action pay by providing a quantity of tokens (split into Stablecoins and DAO tokens)
ΔF, which increased the unallocated funds (and thus also the total funds).
Expand All @@ -197,7 +252,7 @@ def pay(self, broker: Broker, tokens):
self.funds += tokens
return broker

def cancel(self):
def cancel(self, owner_address: str):
"""
In the event that the owner closes down a contract, each Broker gets back their stake, and recieves any
unclaimed tokens allocated to their address as well an equal share of the remaining unallocated assets.
Expand All @@ -211,78 +266,21 @@ def cancel(self):
S=0R=0A=0
when the contract is self-destructed.
"""
total_stake = sum([broker_agreement.initial_stake for broker_agreement in self.broker_agreements.values()])
total_allocated_funds = self.get_allocated_funds()

for public_key, broker_agreement in self.broker_agreements.items():
broker_agreement.allocated_funds += broker_agreement.initial_stake + (self.funds - total_stake - total_allocated_funds) / self.number_of_brokers()

# If there are no brokers attached to the proposal inverter, return funds to owner
self.broker_agreements[self.owner_address] = BrokerAgreement(
epoch_joined=self.current_epoch,
initial_stake=0,
allocated_funds=self.funds - self.get_allocated_funds(),
total_claimed=0
)


class Owner(Wallet):
def _default_agreement_contract_params(self):
params = dict(
min_stake = 5,
epoch_length = 60*60*24,
min_epochs = 28,
allocation_per_epoch = 10,
min_horizon = 7,
min_brokers = 1,
max_brokers = 5,
)
return params

def deploy(self, initial_funds, **agreement_contract_params):
"""
An actor within the ecosystem can deploy a new agreement contract by specifying which proposal the agreement
supports, setting the parameters of the smart contract providing initial funds, and providing any (unenforced)
commitment to continue topping up the contract as payer under as long as a set of SLAs are met. For the purpose
of this draft, it is assumed that the contract is initialized with some quantity of funds F such that H>Hmin
and that B=∅.
"""
params = self._default_agreement_contract_params()
params.update(agreement_contract_params)

# Check imposed restrictions (whether horizon is greater than the min horizon)
horizon = initial_funds / params['allocation_per_epoch']
if horizon < params['min_horizon']:
print("The Horizon is lower than the mininum required horizon")
return None

agreement_contract = ProposalInverter(
owner = self,
initial_funds = initial_funds,
**params,
)

return agreement_contract

def cancel(self, agreement_contract, broker_pool):
"""
In the event that the owner closes down a contract, each Broker gets back their stake, and recieves any
unclaimed tokens allocated to their address as well an equal share of the remaining unallocated assets.
That is to say the quantity Δdi of data tokens is distributed to each broker i∈B
Δdi=si+ai+(R/N)
and thus the penultimate financial state of the contract is
S=0, R=0, A=0
when the contract is self-destructed.
"""
# This function relies on there being given a broker_pool that keeps track of brokers

# Calculate the total allocated funds & total stake for proper calculation
agreement_contract.cancel()
if owner_address != self.owner_address:
print("Only the owner can cancel a proposal")
else:
total_stake = sum([broker_agreement.initial_stake for broker_agreement in self.broker_agreements.values()])
total_allocated_funds = self.get_allocated_funds()

for broker_key in broker_pool:
broker_pool[broker_key] = agreement_contract.claim_broker_funds(broker_pool[broker_key])

return broker_pool
for public_key, broker_agreement in self.broker_agreements.items():
broker_agreement.allocated_funds += broker_agreement.initial_stake + (self.funds - total_stake - total_allocated_funds) / self.number_of_brokers()

# If there are no brokers attached to the proposal inverter, return funds to owner
self.broker_agreements[self.owner_address] = BrokerAgreement(
epoch_joined=self.current_epoch,
initial_stake=0,
allocated_funds=self.funds - self.get_allocated_funds(),
total_claimed=0
)

40 changes: 27 additions & 13 deletions parameterized/test_proposal_inverter.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,45 @@
import pytest

from proposal_inverter import Owner, Broker, ProposalInverter
from .proposal_inverter import Wallet, ProposalInverter


@pytest.fixture
def inverter():
owner = Owner()
def owner():
owner = Wallet()
owner.funds = 1000

return owner


@pytest.fixture
def inverter(owner):
inverter = owner.deploy(500)

return inverter


@pytest.fixture
def broker1():
broker1 = Broker()
broker1 = Wallet()
broker1.funds = 100

return broker1


@pytest.fixture
def broker2():
broker2 = Broker()
broker2 = Wallet()
broker2.funds = 100

return broker2


@pytest.fixture
def payer():
payer = Wallet()
payer.funds = 100

return payer


def test_add_broker(inverter, broker1):
Expand Down Expand Up @@ -127,14 +141,14 @@ def test_get_allocated_funds(inverter, broker1, broker2):
assert inverter.get_allocated_funds() == 300


def test_pay(inverter, broker1):
broker1 = inverter.pay(broker1, 25)
def test_pay(inverter, payer):
payer = inverter.pay(payer, 25)

assert broker1.funds == 75
assert payer.funds == 75
assert inverter.funds == 525


def test_cancel(inverter, broker1, broker2):
def test_cancel(owner, inverter, broker1, broker2):
# Add brokers (each with a different initial stake)
broker1 = inverter.add_broker(broker1, 50)
broker2 = inverter.add_broker(broker2, 100)
Expand All @@ -145,7 +159,7 @@ def test_cancel(inverter, broker1, broker2):
inverter.iter_epoch(30)

# Cancel the proposal inverter
inverter.cancel()
inverter.cancel(owner.public)

# Each broker makes their claim
broker1 = inverter.claim_broker_funds(broker1)
Expand All @@ -169,7 +183,7 @@ def test_forced_cancel_case1(broker1):
allocated to the single broker in the inverter.
"""
# Deploy proposal inverter
owner = Owner()
owner = Wallet()
owner.funds = 1000
inverter = owner.deploy(100, min_brokers=2)

Expand All @@ -191,7 +205,7 @@ def test_forced_cancel_case2(broker1):
owner.
"""
# Deploy proposal inverter
owner = Owner()
owner = Wallet()
owner.funds = 1000
inverter = owner.deploy(100)

Expand Down Expand Up @@ -219,7 +233,7 @@ def test_forced_cancel_case3(broker1, broker2):
cancel.
"""
# Deploy proposal inverter
owner = Owner()
owner = Wallet()
owner.funds = 1000
inverter = owner.deploy(100, min_brokers=2)

Expand Down
10 changes: 5 additions & 5 deletions parameterized/test_owner.py → parameterized/test_wallet.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from proposal_inverter import Owner, Broker
from .proposal_inverter import Wallet


def test_deploy_proposal_inverter():
owner = Owner()
owner = Wallet()
owner.funds = 1000
inverter = owner.deploy(500)

Expand All @@ -13,13 +13,13 @@ def test_deploy_proposal_inverter():

def test_remove_proposal_inverter():
# Deploy proposal inverter
owner = Owner()
owner = Wallet()
owner.funds = 1000
inverter = owner.deploy(500)

# Add brokers (each with a different initial stake)
broker1 = Broker()
broker2 = Broker()
broker1 = Wallet()
broker2 = Wallet()
broker1.funds = 100
broker2.funds = 100
broker1 = inverter.add_broker(broker1, 50)
Expand Down

0 comments on commit af46910

Please sign in to comment.