Skip to content

Commit

Permalink
missing docs. stakepool -> vsp. other fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
buck54321 committed Nov 18, 2019
1 parent 556e314 commit cbf6f2e
Show file tree
Hide file tree
Showing 10 changed files with 444 additions and 339 deletions.
8 changes: 4 additions & 4 deletions crypto/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ def hash160(self):

class AddressSecpPubKey:
"""
AddressSecpPubKey represents and address, which is a pubkey hash and it's
base-58 encoding. Argument pubkey should be a ByteArray corresponding the
the serializedCompressed public key (33 bytes).
AddressSecpPubKey represents an address, which is a pubkey hash and its
base-58 encoding. Argument pubkey should be a ByteArray corresponding to the
serializedCompressed public key (33 bytes).
"""
def __init__(self, serializedPubkey, net):
pubkey = Curve.parsePubKey(serializedPubkey)
Expand Down Expand Up @@ -422,7 +422,7 @@ def newAddressPubKey(decoded, net):
if len(decoded) == 33:
# First byte is the signature suite and ybit.
suite = decoded[0]
suite &= ~(1 << 7)
suite &= 127
ybit = not (decoded[0]&(1<<7) == 0)
toAppend = 0x02
if ybit:
Expand Down
46 changes: 37 additions & 9 deletions pydecred/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

from tinydecred.wallet.accounts import Account
from tinydecred.util import tinyjson, helpers
from tinydecred.crypto.crypto import AddressSecpPubKey
from tinydecred.crypto.crypto import AddressSecpPubKey, CrazyKeyError
from tinydecred.pydecred import txscript
from tinydecred.pydecred.stakepool import StakePool
from tinydecred.pydecred.vsp import VotingServiceProvider

log = helpers.getLogger("DCRACCT")

Expand All @@ -31,7 +31,7 @@ def __init__(self, priv, internal):
"""
Args:
priv (func): func(address : string) -> PrivateKey. Retrieves the
associated with the specified address.
private key associated with the specified address.
internal (func): func() -> address : string. Get a new internal
address.
"""
Expand Down Expand Up @@ -102,6 +102,7 @@ def __init__(self, *a, **k):
self.stakePools = []
self.blockchain = None
self.signals = None
self._votingKey = None
def __tojson__(self):
obj = super().__tojson__()
return helpers.recursiveUpdate(obj, {
Expand All @@ -115,6 +116,29 @@ def __fromjson__(obj):
acct.tickets = obj["tickets"]
acct.stakePools = obj["stakePools"]
return acct
def open(self, pw):
"""
Open the Decred account. Runs the parent's method, then performs some
Decred-specific initialization.
"""
super().open(pw)
# The voting key is the first non-crazy stake-branch child.
for i in range(3):
try:
self._votingKey = self.privKey.child(STAKE_BRANCH).child(i).privateKey()
return
except CrazyKeyError:
continue
# It is realistically impossible to reach here.
raise Exception("error finding voting key")
def close(self):
"""
Close the Decred account. Runs the parent's method, then performs some
Decred-specific clean up.
"""
super().close()
self._votingKey.key.zero()
self._votingKey = None
def updateStakeStats(self):
"""
Updates the stake stats object.
Expand Down Expand Up @@ -173,9 +197,9 @@ def watchAddrs(self):
return self.addTicketAddresses(super().watchAddrs())
def votingKey(self):
"""
For now, the voting key is the zeroth child
For now, the voting key is the zeroth child.
"""
return self.privKey.child(STAKE_BRANCH).child(0).privateKey()
return self._votingKey
def votingAddress(self):
"""
The voting address is the pubkey address (not pubkey-hash) for the
Expand All @@ -191,9 +215,9 @@ def setPool(self, pool):
Set the specified pool as the default.
Args:
pool (stakepool.StakePool): The stake pool object.
pool (vsp.VotingServiceProvider): The stake pool object.
"""
assert isinstance(pool, StakePool)
assert isinstance(pool, VotingServiceProvider)
self.stakePools = [pool] + [p for p in self.stakePools if p.apiKey != pool.apiKey]
bc = self.blockchain
addr = pool.purchaseInfo.ticketAddress
Expand All @@ -210,17 +234,21 @@ def hasPool(self):
return self.stakePool() != None
def stakePool(self):
"""
stakePool is the default stakepool.StakePool for the account.
stakePool is the default vsp.VotingServiceProvider for the
account.
Returns:
staekpool.StakePool: The default stake pool object.
vsp.VotingServiceProvider: The default stake pool object.
"""
if self.stakePools:
return self.stakePools[0]
return None
def ticketStats(self):
"""
A getter for the stakeStats.
Returns:
TicketStats: The staking stats.
"""
return self.stakeStats
def blockSignal(self, sig):
Expand Down
25 changes: 11 additions & 14 deletions pydecred/calc.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def attackCost(ticketFraction=None, xcRate=None, blockHeight=None, roi=None,
"""
Calculate the cost of attack, which is the minimum fiat value of equipment, tickets, and
rental expenditures required to outpace the main chain.
The cost of attack can be calculated in direct mode or reverse mode, depending on the parameters provided.
Provide a `nethash` and a `ticketPrice` to calculate in direct mode.
Omit the `nethash` and `ticketPrice`, and instead provide an `roi` and `apy` to calculate in reverse mode.
Expand Down Expand Up @@ -276,7 +276,7 @@ def attackCost(ticketFraction=None, xcRate=None, blockHeight=None, roi=None,

device = device if device else MODEL_DEVICE
if nethash is None:
if roi is None: # mining ROI could be zero
if roi is None: # mining ROI could be zero
raise Exception("minimizeY: Either a nethash or an roi must be provided")
nethash = ReverseEquations.networkHashrate(device, xcRate, roi, blockHeight, blockTime, powSplit)
if rentability or rentalRatio:
Expand Down Expand Up @@ -309,7 +309,7 @@ def purePowAttackCost(xcRate=None, blockHeight=None, roi=None, blockTime=None,
device = device if device else MODEL_DEVICE
treasurySplit = treasurySplit if treasurySplit else NETWORK.TREASURY_SPLIT
if nethash is None:
if roi is None: # mining ROI could be zero
if roi is None: # mining ROI could be zero
raise Exception("minimizeY: Either a nethash or an roi must be provided")
nethash = ReverseEquations.networkHashrate(device, xcRate, roi, blockHeight, blockTime, 1-treasurySplit)
if rentability or rentalRatio:
Expand Down Expand Up @@ -343,11 +343,9 @@ class SubsidyCache(object):
calculations for blocks and votes, including the max potential subsidy for
given block heights, the proportional proof-of-work subsidy, the proportional
proof of stake per-vote subsidy, and the proportional treasury subsidy.
It makes using of caching to avoid repeated calculations.
It makes use of caching to avoid repeated calculations.
"""
# The following fields are protected by the mtx mutex.
#
# cache houses the cached subsidies keyed by reduction interval.
#
# cachedIntervals contains an ordered list of all cached intervals. It is
Expand All @@ -367,7 +365,7 @@ def __init__(self, params):
# be consider valid by consensus.
#
# totalProportions is the sum of the PoW, PoS, and Treasury proportions.
self.minVotesRequired = (params.TicketsPerBlock // 2) + 1
self.minVotesRequired = (params.TicketsPerBlock // 2) + 1
self.totalProportions = (params.WorkRewardProportion +
params.StakeRewardProportion + params.BlockTaxProportion)

Expand All @@ -387,8 +385,7 @@ def calcBlockSubsidy(self, height):

# Calculate the reduction interval associated with the requested height and
# attempt to look it up in cache. When it's not in the cache, look up the
# latest cached interval and subsidy while the mutex is still held for use
# below.
# latest cached interval and subsidy.
reqInterval = height // self.params.SubsidyReductionInterval
if reqInterval in self.cache:
return self.cache[reqInterval]
Expand Down Expand Up @@ -472,14 +469,14 @@ def calcStakeVoteSubsidy(self, height):
CalcStakeVoteSubsidy returns the subsidy for a single stake vote for a block.
It is calculated as a proportion of the total subsidy and max potential
number of votes per block.
Unlike the Proof-of-Work and Treasury subsidies, the subsidy that votes
receive is not reduced when a block contains less than the maximum number of
votes. Consequently, this does not accept the number of votes. However, it
is important to note that blocks that do not receive the minimum required
number of votes for a block to be valid by consensus won't actually produce
any vote subsidy either since they are invalid.
This function is safe for concurrent access.
"""
# Votes have no subsidy prior to the point voting begins. The minus one
Expand All @@ -505,11 +502,11 @@ def calcTreasurySubsidy(self, height, voters):
a block. It is calculated as a proportion of the total subsidy and further
reduced proportionally depending on the number of votes once the height at
which voting begins has been reached.
Note that passing a number of voters fewer than the minimum required for a
block to be valid by consensus along with a height greater than or equal to
the height at which voting begins will return zero.
This function is safe for concurrent access.
"""
# The first two blocks have special subsidy rules.
Expand Down
23 changes: 21 additions & 2 deletions pydecred/dcrdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,12 @@ def bestBlock(self):
"""
return self.dcrdata.block.best()
def stakeDiff(self):
"""
Get the current stake difficulty a.k.a. ticket price.
Returns:
int: The ticket price.
"""
return int(round(self.dcrdata.stake.diff()["next"]*1e8))
def updateTip(self):
"""
Expand Down Expand Up @@ -1113,6 +1119,21 @@ def purchaseTickets(self, keysource, utxosource, req):
limit in the request is greater than or equal to 0, tickets that cost
more than that limit will return an error that not enough funds are
available.
Args:
keysource (account.KeySource): A source for private keys.
utxosource (func(int, filterFunc) -> list(UTXO)): A source for
UTXOs. The filterFunc is an optional function to filter UTXOs,
and is of the form func(UTXO) -> bool.
req (account.TicketRequest): The ticket data.
Returns:
tuple: First element is the split transaction. Second is a list of
generated tickets.
list (msgtx.TxOut): The outputs spent for the split transaction.
internalOutputs (msgtx.TxOut): New outputs that fund internal
addresses.
"""
self.updateTip()
# account minConf is zero for regular outputs for now. Need to make that
Expand Down Expand Up @@ -1225,8 +1246,6 @@ def purchaseTickets(self, keysource, utxosource, req):
# paying themselves with the larger ticket commitment.
splitOuts = []
for i in range(req.count):
# No pool used.
# Stake pool used.
userAmt = neededPerTicket - poolFeeAmt
poolAmt = poolFeeAmt

Expand Down
Loading

0 comments on commit cbf6f2e

Please sign in to comment.