mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-04-19 22:52:22 +08:00
add state invariant tags for account debits
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from ..config import OPCODE_CREATION_OPS, OPCODE_TRANSITION_OPS, op_get_opcode_name
|
||||
|
||||
@@ -68,16 +69,24 @@ NAMEREC_MUTATE_FIELDS = [
|
||||
]
|
||||
|
||||
|
||||
def state_preorder_invariant_tags():
|
||||
"""
|
||||
Get a list of state-preorder invariant tags
|
||||
"""
|
||||
return [
|
||||
'__account_payment_info__'
|
||||
]
|
||||
|
||||
|
||||
def state_create_invariant_tags():
|
||||
"""
|
||||
Get a list of state-create invariant tags.
|
||||
"""
|
||||
return [
|
||||
'__preorder__',
|
||||
# '__prior_history__',
|
||||
'__table__',
|
||||
'__history_id_key__',
|
||||
'__state_create__'
|
||||
'__state_create__',
|
||||
]
|
||||
|
||||
|
||||
@@ -125,6 +134,11 @@ def state_preorder(collision_checker):
|
||||
# no collision
|
||||
rc = True
|
||||
|
||||
# sanity check---we need to have the appropriate metadata for this operation
|
||||
invariant_tags = state_preorder_invariant_tags()
|
||||
for tag in invariant_tags:
|
||||
assert tag in nameop, "BUG: missing invariant tag '%s'" % tag
|
||||
|
||||
return rc
|
||||
return wrapped_check
|
||||
return wrap
|
||||
@@ -136,7 +150,6 @@ def state_create(history_id_key, table_name, collision_checker, always_set=[]):
|
||||
Decorator for the check() method on state-creating operations.
|
||||
Makes sure that:
|
||||
* there is a __preorder__ field set, which contains the state-creating operation's associated preorder
|
||||
# * there is a __prior_history__ field set, which contains the state-creating operation's associated prior state history
|
||||
* there is a __table__ field set, which contains the table into which to insert this state into
|
||||
* there is a __history_id_key__ field set, which identifies the table's primary key name
|
||||
* there are no unexpired, duplicate instances of this state with this history id.
|
||||
@@ -150,14 +163,13 @@ def state_create(history_id_key, table_name, collision_checker, always_set=[]):
|
||||
# succeeded, and still a state-creating operation?
|
||||
if rc and op_get_opcode_name( nameop['op'] ) in OPCODE_CREATION_OPS:
|
||||
|
||||
# ensure that there's now a __preorder__ # and a __prior_history__
|
||||
# ensure that there's now a __preorder__
|
||||
try:
|
||||
assert '__preorder__' in nameop.keys(), "Missing __preorder__"
|
||||
# assert '__prior_history__' in nameop.keys(), "Missing __prior_history__"
|
||||
except Exception, e:
|
||||
log.exception(e)
|
||||
log.error("FATAL: missing fields")
|
||||
sys.exit(1)
|
||||
os.abort()
|
||||
|
||||
# propagate __table__ and __history_id_key__
|
||||
nameop['__table__'] = table_name
|
||||
@@ -165,7 +177,7 @@ def state_create(history_id_key, table_name, collision_checker, always_set=[]):
|
||||
nameop['__state_create__'] = True
|
||||
nameop['__always_set__'] = always_set
|
||||
|
||||
# sanity check
|
||||
# sanity check---we need to have the appropriate metadata for this operation
|
||||
invariant_tags = state_create_invariant_tags()
|
||||
for tag in invariant_tags:
|
||||
assert tag in nameop, "BUG: missing invariant tag '%s'" % tag
|
||||
@@ -193,12 +205,12 @@ def state_transition_invariant_tags():
|
||||
'__table__',
|
||||
'__history_id_key__',
|
||||
'__state_transition__',
|
||||
'__always_set__'
|
||||
'__always_set__',
|
||||
]
|
||||
|
||||
|
||||
# sanity check decorator for state-transition operations
|
||||
def state_transition(history_id_key, table_name, always_set=[]):
|
||||
def state_transition(history_id_key, table_name, always_set=[], may_spend_tokens=False):
|
||||
"""
|
||||
Decorator for the check() method on state-transition operations.
|
||||
Make sure that:
|
||||
@@ -220,6 +232,12 @@ def state_transition(history_id_key, table_name, always_set=[]):
|
||||
nameop['__state_transition__'] = True
|
||||
nameop['__always_set__'] = always_set
|
||||
|
||||
if not may_spend_tokens:
|
||||
state_transition_put_account_payment_info(nameop, None, None, None)
|
||||
|
||||
elif '__account_payment_info__' not in nameop:
|
||||
raise Exception('Operation spends tokens, but no payment account information is set')
|
||||
|
||||
# sanity check
|
||||
invariant_tags = state_transition_invariant_tags()
|
||||
for tag in invariant_tags:
|
||||
@@ -234,12 +252,35 @@ def get_state_invariant_tags():
|
||||
"""
|
||||
Get the set of state invariant tags for a given opcode
|
||||
"""
|
||||
return list(set( state_create_invariant_tags() + state_transition_invariant_tags() ))
|
||||
return list(set( state_create_invariant_tags() + state_transition_invariant_tags() + state_preorder_invariant_tags() ))
|
||||
|
||||
|
||||
def state_preorder_get_account_payment_info( nameop ):
|
||||
"""
|
||||
Get the payment information for an account. Can be None if no account payments are needed
|
||||
"""
|
||||
return nameop['__account_payment_info__']
|
||||
|
||||
|
||||
def state_preorder_put_account_payment_info( nameop, account_addr, token_type, amount ):
|
||||
"""
|
||||
Call this in a @state_create-decorated method.
|
||||
Identifies the account that must be debited.
|
||||
"""
|
||||
assert amount is None or isinstance(amount, int)
|
||||
assert account_addr is None or isinstance(account_addr, (str,unicode))
|
||||
assert token_type is None or isinstance(token_type, (str,unicode))
|
||||
nameop['__account_payment_info__'] = {
|
||||
'address': str(account_addr) if account_addr is not None else None,
|
||||
'type': str(token_type) if token_type is not None else None,
|
||||
'amount': int(amount) if amount is not None else None
|
||||
}
|
||||
|
||||
|
||||
def state_create_put_preorder( nameop, preorder ):
|
||||
"""
|
||||
Call this in a @state_create-decorated method.
|
||||
Identifies the preorder record for this state.
|
||||
"""
|
||||
nameop['__preorder__'] = preorder
|
||||
|
||||
@@ -251,7 +292,6 @@ def state_create_is_valid( nameop ):
|
||||
assert '__state_create__' in nameop, "Not tagged with @state_create"
|
||||
assert nameop['__state_create__'], "BUG: tagged False by @state_create"
|
||||
assert '__preorder__' in nameop, "No preorder"
|
||||
# assert '__prior_history__' in nameop, "No prior history"
|
||||
assert '__table__' in nameop, "No table given"
|
||||
assert '__history_id_key__' in nameop, "No history ID key given"
|
||||
assert nameop['__history_id_key__'] in nameop, "No history ID given"
|
||||
@@ -299,10 +339,26 @@ def state_transition_is_valid( nameop ):
|
||||
assert history_id_key in ["name", "namespace_id"], "Invalid history ID key '%s'" % history_id_key
|
||||
assert '__table__' in nameop, "Missing __table__"
|
||||
assert '__always_set__' in nameop, "No always-set fields given"
|
||||
assert '__account_payment_info__' in nameop, 'No account payment information present'
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def state_transition_put_account_payment_info( nameop, account_addr, token_type, amount ):
|
||||
"""
|
||||
Call this in a @state_create-decorated method.
|
||||
Identifies the account that must be debited.
|
||||
"""
|
||||
assert amount is None or isinstance(amount, int)
|
||||
assert account_addr is None or isinstance(account_addr, (str,unicode))
|
||||
assert token_type is None or isinstance(token_type, (str,unicode))
|
||||
nameop['__account_payment_info__'] = {
|
||||
'address': str(account_addr) if account_addr is not None else None,
|
||||
'type': str(token_type) if token_type is not None else None,
|
||||
'amount': int(amount) if amount is not None else None
|
||||
}
|
||||
|
||||
|
||||
def state_transition_get_table( nameop ):
|
||||
"""
|
||||
Get the table of a state-transition operation
|
||||
@@ -310,6 +366,13 @@ def state_transition_get_table( nameop ):
|
||||
return nameop['__table__']
|
||||
|
||||
|
||||
def state_transition_get_account_payment_info( nameop ):
|
||||
"""
|
||||
Get the payment information for an account. Can be None if no account payments are needed
|
||||
"""
|
||||
return nameop['__account_payment_info__']
|
||||
|
||||
|
||||
def state_transition_get_history_id_key( nameop ):
|
||||
"""
|
||||
Get the key of the history ID of a state-transition name operation
|
||||
|
||||
Reference in New Issue
Block a user