Skip to content

Commit

Permalink
Add test for relative seconds, and rename conditions (Chia-Network#1902)
Browse files Browse the repository at this point in the history
* Add test for relative seconds

* rebased on top of main

* Renamed AGG_SIG to AGG_SIG_UNSAFE
Renamed height and time conditions
Changed some demo p2 puzzles to use AGG_SIG_ME

* fix merge on cost_calculator

* update hex and sha256tree of p2_delegated_conditions

* fix condition name in rl clvm

* updated the innerpuz sha256tree after careful inspection
  • Loading branch information
matt-o-how authored Apr 15, 2021
1 parent 24fdd37 commit 332d939
Show file tree
Hide file tree
Showing 23 changed files with 173 additions and 104 deletions.
28 changes: 14 additions & 14 deletions chia/consensus/blockchain_check_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def blockchain_assert_my_coin_id(condition: ConditionWithArgs, unspent: CoinReco
return None


def blockchain_assert_block_index_exceeds(
def blockchain_assert_absolute_block_height_exceeds(
condition: ConditionWithArgs, prev_transaction_block_height: uint32
) -> Optional[Err]:
"""
Expand All @@ -29,11 +29,11 @@ def blockchain_assert_block_index_exceeds(
return Err.INVALID_CONDITION

if prev_transaction_block_height < expected_block_index:
return Err.ASSERT_HEIGHT_NOW_EXCEEDS_FAILED
return Err.ASSERT_HEIGHT_ABSOLUTE_FAILED
return None


def blockchain_assert_block_age_exceeds(
def blockchain_assert_relative_block_height_exceeds(
condition: ConditionWithArgs, unspent: CoinRecord, prev_transaction_block_height: uint32
) -> Optional[Err]:
"""
Expand All @@ -45,11 +45,11 @@ def blockchain_assert_block_age_exceeds(
except ValueError:
return Err.INVALID_CONDITION
if prev_transaction_block_height < expected_block_index:
return Err.ASSERT_HEIGHT_AGE_EXCEEDS_FAILED
return Err.ASSERT_HEIGHT_RELATIVE_FAILED
return None


def blockchain_assert_time_exceeds(condition: ConditionWithArgs, timestamp):
def blockchain_assert_absolute_time_exceeds(condition: ConditionWithArgs, timestamp):
"""
Checks if current time in millis exceeds the time specified in condition
"""
Expand All @@ -60,7 +60,7 @@ def blockchain_assert_time_exceeds(condition: ConditionWithArgs, timestamp):

current_time = timestamp
if current_time <= expected_mili_time:
return Err.ASSERT_SECONDS_NOW_EXCEEDS_FAILED
return Err.ASSERT_SECONDS_ABSOLUTE_FAILED
return None


Expand All @@ -75,7 +75,7 @@ def blockchain_assert_relative_time_exceeds(condition: ConditionWithArgs, unspen

current_time = timestamp
if current_time <= expected_mili_time + unspent.timestamp:
return Err.ASSERT_SECONDS_AGE_EXCEEDS_FAILED
return Err.ASSERT_SECONDS_RELATIVE_FAILED
return None


Expand Down Expand Up @@ -111,13 +111,13 @@ def blockchain_check_conditions_dict(
error = blockchain_assert_announcement(cvp, coin_announcement_names)
elif cvp.opcode is ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT:
error = blockchain_assert_announcement(cvp, puzzle_announcement_names)
elif cvp.opcode is ConditionOpcode.ASSERT_HEIGHT_NOW_EXCEEDS:
error = blockchain_assert_block_index_exceeds(cvp, prev_transaction_block_height)
elif cvp.opcode is ConditionOpcode.ASSERT_HEIGHT_AGE_EXCEEDS:
error = blockchain_assert_block_age_exceeds(cvp, unspent, prev_transaction_block_height)
elif cvp.opcode is ConditionOpcode.ASSERT_SECONDS_NOW_EXCEEDS:
error = blockchain_assert_time_exceeds(cvp, timestamp)
elif cvp.opcode is ConditionOpcode.ASSERT_SECONDS_AGE_EXCEEDS:
elif cvp.opcode is ConditionOpcode.ASSERT_HEIGHT_ABSOLUTE:
error = blockchain_assert_absolute_block_height_exceeds(cvp, prev_transaction_block_height)
elif cvp.opcode is ConditionOpcode.ASSERT_HEIGHT_RELATIVE:
error = blockchain_assert_relative_block_height_exceeds(cvp, unspent, prev_transaction_block_height)
elif cvp.opcode is ConditionOpcode.ASSERT_SECONDS_ABSOLUTE:
error = blockchain_assert_absolute_time_exceeds(cvp, timestamp)
elif cvp.opcode is ConditionOpcode.ASSERT_SECONDS_RELATIVE:
error = blockchain_assert_relative_time_exceeds(cvp, unspent, timestamp)
if error:
return error
Expand Down
8 changes: 4 additions & 4 deletions chia/consensus/condition_costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ class ConditionCost(Enum):
AGG_SIG = 1200000 # the cost of one G1 subgroup check + aggregated signature validation
CREATE_COIN = 1800000
ASSERT_MY_COIN_ID = 0
ASSERT_SECONDS_NOW_EXCEEDS = 0
ASSERT_SECONDS_AGE_EXCEEDS = 0
ASSERT_HEIGHT_NOW_EXCEEDS = 0
ASSERT_HEIGHT_AGE_EXCEEDS = 0
ASSERT_SECONDS_RELATIVE = 0
ASSERT_SECONDS_ABSOLUTE = 0
ASSERT_HEIGHT_RELATIVE = 0
ASSERT_HEIGHT_ABSOLUTE = 0
RESERVE_FEE = 0
CREATE_COIN_ANNOUNCEMENT = 0
ASSERT_COIN_ANNOUNCEMENT = 0
Expand Down
16 changes: 9 additions & 7 deletions chia/consensus/cost_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@ def calculate_cost_of_program(program: SerializedProgram, cost_per_byte: int, st
npc: NPC
for npc in npc_list:
for condition, cvp_list in npc.condition_dict.items():
if condition is ConditionOpcode.AGG_SIG or condition is ConditionOpcode.AGG_SIG_ME:
if condition is ConditionOpcode.AGG_SIG_UNSAFE or condition is ConditionOpcode.AGG_SIG_ME:
total_cost += len(cvp_list) * ConditionCost.AGG_SIG.value
elif condition is ConditionOpcode.CREATE_COIN:
total_cost += len(cvp_list) * ConditionCost.CREATE_COIN.value
elif condition is ConditionOpcode.ASSERT_SECONDS_NOW_EXCEEDS:
total_cost += len(cvp_list) * ConditionCost.ASSERT_SECONDS_NOW_EXCEEDS.value
elif condition is ConditionOpcode.ASSERT_HEIGHT_AGE_EXCEEDS:
total_cost += len(cvp_list) * ConditionCost.ASSERT_HEIGHT_AGE_EXCEEDS.value
elif condition is ConditionOpcode.ASSERT_HEIGHT_NOW_EXCEEDS:
total_cost += len(cvp_list) * ConditionCost.ASSERT_HEIGHT_NOW_EXCEEDS.value
elif condition is ConditionOpcode.ASSERT_SECONDS_ABSOLUTE:
total_cost += len(cvp_list) * ConditionCost.ASSERT_SECONDS_ABSOLUTE.value
elif condition is ConditionOpcode.ASSERT_HEIGHT_RELATIVE:
total_cost += len(cvp_list) * ConditionCost.ASSERT_HEIGHT_RELATIVE.value
elif condition is ConditionOpcode.ASSERT_HEIGHT_ABSOLUTE:
total_cost += len(cvp_list) * ConditionCost.ASSERT_HEIGHT_ABSOLUTE.value
elif condition is ConditionOpcode.ASSERT_HEIGHT_RELATIVE:
total_cost += len(cvp_list) * ConditionCost.ASSERT_HEIGHT_RELATIVE.value
elif condition is ConditionOpcode.ASSERT_MY_COIN_ID:
total_cost += len(cvp_list) * ConditionCost.ASSERT_MY_COIN_ID.value
elif condition is ConditionOpcode.RESERVE_FEE:
Expand Down
28 changes: 14 additions & 14 deletions chia/full_node/mempool_check_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def mempool_assert_my_coin_id(condition: ConditionWithArgs, unspent: CoinRecord)
return None


def mempool_assert_block_index_exceeds(
def mempool_assert_absolute_block_height_exceeds(
condition: ConditionWithArgs, prev_transaction_block_height: uint32
) -> Optional[Err]:
"""
Expand All @@ -49,11 +49,11 @@ def mempool_assert_block_index_exceeds(
except ValueError:
return Err.INVALID_CONDITION
if prev_transaction_block_height < block_index_exceeds_this:
return Err.ASSERT_HEIGHT_NOW_EXCEEDS_FAILED
return Err.ASSERT_HEIGHT_ABSOLUTE_FAILED
return None


def mempool_assert_block_age_exceeds(
def mempool_assert_relative_block_height_exceeds(
condition: ConditionWithArgs, unspent: CoinRecord, prev_transaction_block_height: uint32
) -> Optional[Err]:
"""
Expand All @@ -65,11 +65,11 @@ def mempool_assert_block_age_exceeds(
except ValueError:
return Err.INVALID_CONDITION
if prev_transaction_block_height < block_index_exceeds_this:
return Err.ASSERT_HEIGHT_AGE_EXCEEDS_FAILED
return Err.ASSERT_HEIGHT_RELATIVE_FAILED
return None


def mempool_assert_time_exceeds(condition: ConditionWithArgs) -> Optional[Err]:
def mempool_assert_absolute_time_exceeds(condition: ConditionWithArgs) -> Optional[Err]:
"""
Check if the current time in millis exceeds the time specified by condition
"""
Expand All @@ -80,7 +80,7 @@ def mempool_assert_time_exceeds(condition: ConditionWithArgs) -> Optional[Err]:

current_time = uint64(int(time.time() * 1000))
if current_time <= expected_mili_time:
return Err.ASSERT_SECONDS_NOW_EXCEEDS_FAILED
return Err.ASSERT_SECONDS_ABSOLUTE_FAILED
return None


Expand All @@ -95,7 +95,7 @@ def mempool_assert_relative_time_exceeds(condition: ConditionWithArgs, unspent:

current_time = uint64(int(time.time() * 1000))
if current_time <= expected_mili_time + unspent.timestamp:
return Err.ASSERT_SECONDS_NOW_EXCEEDS_FAILED
return Err.ASSERT_SECONDS_ABSOLUTE_FAILED
return None


Expand Down Expand Up @@ -200,13 +200,13 @@ def mempool_check_conditions_dict(
error = mempool_assert_announcement(cvp, coin_announcement_names)
elif cvp.opcode is ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT:
error = mempool_assert_announcement(cvp, puzzle_announcement_names)
elif cvp.opcode is ConditionOpcode.ASSERT_HEIGHT_NOW_EXCEEDS:
error = mempool_assert_block_index_exceeds(cvp, prev_transaction_block_height)
elif cvp.opcode is ConditionOpcode.ASSERT_HEIGHT_AGE_EXCEEDS:
error = mempool_assert_block_age_exceeds(cvp, unspent, prev_transaction_block_height)
elif cvp.opcode is ConditionOpcode.ASSERT_SECONDS_NOW_EXCEEDS:
error = mempool_assert_time_exceeds(cvp)
elif cvp.opcode is ConditionOpcode.ASSERT_SECONDS_AGE_EXCEEDS:
elif cvp.opcode is ConditionOpcode.ASSERT_HEIGHT_ABSOLUTE:
error = mempool_assert_absolute_block_height_exceeds(cvp, prev_transaction_block_height)
elif cvp.opcode is ConditionOpcode.ASSERT_HEIGHT_RELATIVE:
error = mempool_assert_relative_block_height_exceeds(cvp, unspent, prev_transaction_block_height)
elif cvp.opcode is ConditionOpcode.ASSERT_SECONDS_ABSOLUTE:
error = mempool_assert_absolute_time_exceeds(cvp)
elif cvp.opcode is ConditionOpcode.ASSERT_SECONDS_RELATIVE:
error = mempool_assert_relative_time_exceeds(cvp, unspent)
elif cvp.opcode is ConditionOpcode.ASSERT_MY_PARENT_ID:
error = mempool_assert_my_parent_id(cvp, unspent)
Expand Down
2 changes: 1 addition & 1 deletion chia/full_node/mempool_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ async def add_spendbundle(
)

if error:
if error is Err.ASSERT_HEIGHT_NOW_EXCEEDS_FAILED or error is Err.ASSERT_HEIGHT_AGE_EXCEEDS_FAILED:
if error is Err.ASSERT_HEIGHT_ABSOLUTE_FAILED or error is Err.ASSERT_HEIGHT_RELATIVE_FAILED:
self.add_to_potential_tx_set(new_spend, spend_name, cost_result)
return uint64(cost), MempoolInclusionStatus.PENDING, error
break
Expand Down
10 changes: 5 additions & 5 deletions chia/types/condition_opcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ConditionOpcode(bytes, enum.Enum):

# the conditions below require bls12-381 signatures

AGG_SIG = bytes([49])
AGG_SIG_UNSAFE = bytes([49])
AGG_SIG_ME = bytes([50])

# the conditions below reserve coin amounts and have to be accounted for in output totals
Expand All @@ -36,12 +36,12 @@ class ConditionOpcode(bytes, enum.Enum):
# the conditions below ensure that we're "far enough" in the future

# wall-clock time
ASSERT_SECONDS_AGE_EXCEEDS = bytes([80])
ASSERT_SECONDS_NOW_EXCEEDS = bytes([81])
ASSERT_SECONDS_RELATIVE = bytes([80])
ASSERT_SECONDS_ABSOLUTE = bytes([81])

# block index
ASSERT_HEIGHT_AGE_EXCEEDS = bytes([82])
ASSERT_HEIGHT_NOW_EXCEEDS = bytes([83])
ASSERT_HEIGHT_RELATIVE = bytes([82])
ASSERT_HEIGHT_ABSOLUTE = bytes([83])

def __bytes__(self) -> bytes:
return bytes(self.value)
Expand Down
2 changes: 1 addition & 1 deletion chia/util/condition_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def pkm_pairs_for_conditions_dict(
assert coin_name is not None
ret: List[Tuple[G1Element, bytes]] = []

for cwa in conditions_dict.get(ConditionOpcode.AGG_SIG, []):
for cwa in conditions_dict.get(ConditionOpcode.AGG_SIG_UNSAFE, []):
assert len(cwa.vars) == 2
assert cwa.vars[0] is not None and cwa.vars[1] is not None
ret.append((G1Element.from_bytes(cwa.vars[0]), cwa.vars[1]))
Expand Down
8 changes: 4 additions & 4 deletions chia/util/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ class Err(Enum):
INVALID_CONDITION = 10
ASSERT_MY_COIN_ID_FAILED = 11
ASSERT_ANNOUNCE_CONSUMED_FAILED = 12
ASSERT_HEIGHT_AGE_EXCEEDS_FAILED = 13
ASSERT_HEIGHT_NOW_EXCEEDS_FAILED = 14
ASSERT_SECONDS_NOW_EXCEEDS_FAILED = 15
ASSERT_HEIGHT_RELATIVE_FAILED = 13
ASSERT_HEIGHT_ABSOLUTE_FAILED = 14
ASSERT_SECONDS_ABSOLUTE_FAILED = 15
COIN_AMOUNT_EXCEEDS_MAXIMUM = 16

SEXP_ERROR = 17
Expand Down Expand Up @@ -127,7 +127,7 @@ class Err(Enum):
TOO_MANY_BLOCKS = 102
INVALID_CC_CHALLENGE = 103
INVALID_PREFARM = 104
ASSERT_SECONDS_AGE_EXCEEDS_FAILED = 105
ASSERT_SECONDS_RELATIVE_FAILED = 105
BAD_COINBASE_SIGNATURE = 106
INITIAL_TRANSACTION_FREEZE = 107
NO_TRANSACTIONS_WHILE_SYNCING = 108
Expand Down
23 changes: 13 additions & 10 deletions chia/util/wallet_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
make_assert_aggsig_condition,
make_assert_coin_announcement,
make_assert_puzzle_announcement,
make_assert_height_age_exceeds_condition,
make_assert_height_now_exceeds_condition,
make_assert_relative_height_exceeds_condition,
make_assert_absolute_height_exceeds_condition,
make_assert_my_coin_id_condition,
make_assert_seconds_now_exceeds_condition,
make_assert_absolute_seconds_exceeds_condition,
make_assert_relative_seconds_exceeds_condition,
make_create_coin_announcement,
make_create_puzzle_announcement,
make_create_coin_condition,
Expand Down Expand Up @@ -106,20 +107,22 @@ def make_solution(self, condition_dic: Dict[ConditionOpcode, List[ConditionWithA
ret.append(make_create_coin_announcement(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT:
ret.append(make_create_puzzle_announcement(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.AGG_SIG:
if cvp.opcode == ConditionOpcode.AGG_SIG_UNSAFE:
ret.append(make_assert_aggsig_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT:
ret.append(make_assert_coin_announcement(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT:
ret.append(make_assert_puzzle_announcement(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_SECONDS_NOW_EXCEEDS:
ret.append(make_assert_seconds_now_exceeds_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_SECONDS_ABSOLUTE:
ret.append(make_assert_absolute_seconds_exceeds_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_SECONDS_RELATIVE:
ret.append(make_assert_relative_seconds_exceeds_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_MY_COIN_ID:
ret.append(make_assert_my_coin_id_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_HEIGHT_NOW_EXCEEDS:
ret.append(make_assert_height_now_exceeds_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_HEIGHT_AGE_EXCEEDS:
ret.append(make_assert_height_age_exceeds_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_HEIGHT_ABSOLUTE:
ret.append(make_assert_absolute_height_exceeds_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_HEIGHT_RELATIVE:
ret.append(make_assert_relative_height_exceeds_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.RESERVE_FEE:
ret.append(make_reserve_fee_condition(cvp.vars[0]))
if cvp.opcode == ConditionOpcode.ASSERT_MY_PARENT_ID:
Expand Down
2 changes: 1 addition & 1 deletion chia/wallet/did_wallet/did_wallet_puzzles.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def get_innerpuzzle_from_puzzle(puzzle: Program) -> Optional[Program]:


def create_recovery_message_puzzle(recovering_coin: bytes32, newpuz: bytes32, pubkey: G1Element):
puzstring = f"(q . ((0x{ConditionOpcode.CREATE_COIN_ANNOUNCEMENT.hex()} 0x{recovering_coin.hex()}) (0x{ConditionOpcode.AGG_SIG.hex()} 0x{bytes(pubkey).hex()} 0x{newpuz.hex()})))" # noqa
puzstring = f"(q . ((0x{ConditionOpcode.CREATE_COIN_ANNOUNCEMENT.hex()} 0x{recovering_coin.hex()}) (0x{ConditionOpcode.AGG_SIG_UNSAFE.hex()} 0x{bytes(pubkey).hex()} 0x{newpuz.hex()})))" # noqa
puz = binutils.assemble(puzstring)
return Program.to(puz)

Expand Down
10 changes: 5 additions & 5 deletions chia/wallet/puzzles/condition_codes.clvm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; See chia/types/condition_opcodes.py

(
(defconstant AGG_SIG 49)
(defconstant AGG_SIG_UNSAFE 49)
(defconstant AGG_SIG_ME 50)

; the conditions below reserve coin amounts and have to be accounted for in output totals
Expand Down Expand Up @@ -29,10 +29,10 @@
; the conditions below ensure that we're "far enough" in the future

; wall-clock time
(defconstant ASSERT_SECONDS_AGE_EXCEEDS 80)
(defconstant ASSERT_SECONDS_NOW_EXCEEDS 81)
(defconstant ASSERT_SECONDS_RELATIVE 80)
(defconstant ASSERT_SECONDS_ABSOLUTE 81)

; block index
(defconstant ASSERT_HEIGHT_AGE_EXCEEDS 82)
(defconstant ASSERT_HEIGHT_NOW_EXCEEDS 83)
(defconstant ASSERT_HEIGHT_RELATIVE 82)
(defconstant ASSERT_HEIGHT_ABSOLUTE 83)
)
6 changes: 3 additions & 3 deletions chia/wallet/puzzles/did_innerpuz.clvm
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
;recovery message module - gets values curried in to make the puzzle
;TODO - this should probably be imported
(defun make_message_puzzle (recovering_coin newpuz pubkey)
(qq (q . (((unquote CREATE_COIN_ANNOUNCEMENT) (unquote recovering_coin)) ((unquote AGG_SIG) (unquote pubkey) (unquote newpuz)))))
(qq (q . (((unquote CREATE_COIN_ANNOUNCEMENT) (unquote recovering_coin)) ((unquote AGG_SIG_UNSAFE) (unquote pubkey) (unquote newpuz)))))
)

(defun create_consume_message (coin_id my_id new_innerpuz pubkey)
Expand Down Expand Up @@ -146,9 +146,9 @@
)
;if we're out of identites to check for, return our output
(if (> num_verifications num_verifications_required)
(c (list AGG_SIG pubkey new_puz) output)
(c (list AGG_SIG_UNSAFE pubkey new_puz) output)
(if (= num_verifications num_verifications_required)
(c (list AGG_SIG pubkey new_puz) output)
(c (list AGG_SIG_UNSAFE pubkey new_puz) output)
(x "not enough verifications")
)
)
Expand Down
Loading

0 comments on commit 332d939

Please sign in to comment.