mirror of https://github.com/nucypher/nucypher.git
71 lines
2.0 KiB
Python
71 lines
2.0 KiB
Python
import random
|
|
from typing import List
|
|
from nkms_eth import blockchain
|
|
from nkms_eth import token
|
|
|
|
ESCROW_NAME = 'Escrow'
|
|
BLOCKS_PER_PERIOD = 50 # 6100
|
|
MIN_RELEASE_PERIODS = 1 # 30
|
|
MAX_AWARDED_PERIODS = 365
|
|
MINING_COEFF = [
|
|
BLOCKS_PER_PERIOD * MAX_AWARDED_PERIODS * 10 ** 9,
|
|
BLOCKS_PER_PERIOD,
|
|
MIN_RELEASE_PERIODS,
|
|
BLOCKS_PER_PERIOD * MAX_AWARDED_PERIODS,
|
|
MAX_AWARDED_PERIODS
|
|
]
|
|
NULL_ADDR = '0x' + '0' * 40
|
|
|
|
|
|
def create():
|
|
"""
|
|
Creates an escrow which manages mining
|
|
"""
|
|
chain = blockchain.chain()
|
|
creator = chain.web3.eth.accounts[0] # TODO: make it possible to override
|
|
tok = token.get()
|
|
escrow, tx = chain.provider.get_or_deploy_contract(
|
|
ESCROW_NAME, deploy_args=[token.get().address] + MINING_COEFF,
|
|
deploy_transaction={'from': creator})
|
|
chain.wait.for_receipt(tx, timeout=blockchain.TIMEOUT)
|
|
tx = tok.transact({'from': creator}).addMiner(escrow.address)
|
|
chain.wait.for_receipt(tx, timeout=blockchain.TIMEOUT)
|
|
return escrow
|
|
|
|
|
|
def get():
|
|
"""
|
|
Returns an escrow object
|
|
"""
|
|
return token.get(ESCROW_NAME)
|
|
|
|
|
|
def sample(n: int = 10)-> List[str]:
|
|
"""
|
|
Select n random staking Ursulas, according to their stake distribution
|
|
The returned addresses are shuffled, so one can request more than needed and
|
|
throw away those which do not respond
|
|
"""
|
|
escrow = get()
|
|
n_select = int(n * 1.7) # Select more ursulas
|
|
n_tokens = escrow.call().getAllLockedTokens()
|
|
duration = 10
|
|
|
|
for _ in range(5): # number of tries
|
|
points = [0] + sorted(random.randrange(n_tokens) for _ in
|
|
range(n_select))
|
|
deltas = [i - j for i, j in zip(points[1:], points[:-1])]
|
|
addrs = set()
|
|
addr = NULL_ADDR
|
|
shift = 0
|
|
|
|
for delta in deltas:
|
|
addr, shift = escrow.call().findCumSum(addr, delta + shift, duration)
|
|
addrs.add(addr)
|
|
|
|
if len(addrs) >= n:
|
|
addrs = random.sample(addrs, n)
|
|
return addrs
|
|
|
|
raise Exception('Not enough Ursulas')
|