check time exceeds for mempool

This commit is contained in:
Yostra 2020-01-31 16:28:16 -08:00
parent ccb7da08da
commit 3df867c5f6
6 changed files with 112 additions and 23 deletions

View File

@ -16,7 +16,7 @@ class ConditionOpcode(bytes, enum.Enum):
CREATE_COIN = bytes([51])
ASSERT_COIN_CONSUMED = bytes([52])
ASSERT_MY_COIN_ID = bytes([53])
ASSERT_MIN_TIME = bytes([54])
ASSERT_TIME_EXCEEDS = bytes([54])
ASSERT_BLOCK_INDEX_EXCEEDS = bytes([55])
ASSERT_BLOCK_AGE_EXCEEDS = bytes([56])

View File

@ -30,10 +30,11 @@ class Err(Enum):
ASSERT_COIN_CONSUMED_FAILED = 12
ASSERT_BLOCK_AGE_EXCEEDS_FAILED = 13
ASSERT_BLOCK_INDEX_EXCEEDS_FAILED = 14
COIN_AMOUNT_EXCEEDS_MAXIMUM = 15
ASSERT_TIME_EXCEEDS_FAILED = 15
COIN_AMOUNT_EXCEEDS_MAXIMUM = 16
SEXP_ERROR = 16
INVALID_FEE_LOW_FEE = 17
MEMPOOL_CONFLICT = 18
MINTING_COIN = 19
EXTENDS_UNKNOWN_BLOCK = 20
SEXP_ERROR = 17
INVALID_FEE_LOW_FEE = 18
MEMPOOL_CONFLICT = 19
MINTING_COIN = 20
EXTENDS_UNKNOWN_BLOCK = 21

View File

@ -9,6 +9,9 @@ from src.types.pool import Pool
from src.util.Conditions import ConditionVarPair, ConditionOpcode
from src.util.ConsensusError import Err
from src.util.consensus import conditions_dict_for_solution
import time
from src.util.ints import uint64
def mempool_assert_coin_consumed(condition: ConditionVarPair, spend_bundle: SpendBundle, mempool: Pool) -> Optional[
@ -59,6 +62,16 @@ def mempool_assert_block_age_exceeds(condition: ConditionVarPair, unspent: Unspe
return Err.ASSERT_BLOCK_AGE_EXCEEDS_FAILED
return None
def mempool_assert_time_exceeds(condition: ConditionVarPair):
try:
expected_mili_time = clvm.casts.uint64_from_bytes(condition.var1)
except ValueError:
return Err.INVALID_CONDITION
current_time = uint64(time.time() * 1000)
if current_time < expected_mili_time:
return Err.ASSERT_TIME_EXCEEDS_FAILED
return None
async def get_name_puzzle_conditions(block_program: Program) -> Tuple[Optional[Err], Optional[List[NPC]]]:
"""
@ -114,7 +127,8 @@ def mempool_check_conditions_dict(unspent: Unspent, spend_bundle: SpendBundle,
error = mempool_assert_block_index_exceeds(cvp, unspent, mempool)
elif cvp.opcode is ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS:
error = mempool_assert_block_age_exceeds(cvp, unspent, mempool)
# TODO add stuff from Will's pull req
elif cvp.opcode is ConditionOpcode.ASSERT_TIME_EXCEEDS:
error = mempool_assert_time_exceeds(cvp)
if error:
return error

View File

@ -17,11 +17,6 @@ def make_assert_coin_consumed_condition(coin_name):
def make_assert_my_coin_id_condition(coin_name):
return [ConditionOpcode.ASSERT_MY_COIN_ID, coin_name]
def make_assert_min_time_condition(time):
return [ConditionOpcode.ASSERT_MIN_TIME, time]
def make_assert_block_index_exceeds_condition(block_index):
return [ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS, block_index]

View File

@ -1,13 +1,12 @@
import asyncio
from time import time
import pytest
from src.farming.farming_tools import best_solution_program
from src.server.outbound_message import OutboundMessage
from src.protocols import peer_protocol
from src.util.Conditions import ConditionVarPair, ConditionOpcode
from src.util.ints import uint64
from src.util.mempool_check_conditions import get_name_puzzle_conditions
from src.wallet.wallets.standard_wallet.wallet import Wallet
from tests.setup_nodes import setup_two_nodes, test_constants, bt
from tests.wallet_tools import WalletTool
@ -29,7 +28,7 @@ class TestMempool:
num_blocks = 3
wallet_a = WalletTool()
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
wallet_receiver = Wallet()
wallet_receiver = WalletTool()
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash)
@ -297,3 +296,85 @@ class TestMempool:
sb1 = await full_node_1.mempool.get_spendbundle(spend_bundle1.name())
assert sb1 is None
@pytest.mark.asyncio
async def test_assert_time_exceeds(self, two_nodes):
num_blocks = 4
wallet_a = WalletTool()
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
wallet_receiver = WalletTool()
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash)
full_node_1, full_node_2, server_1, server_2 = two_nodes
block = blocks[1]
for b in blocks:
async for _ in full_node_1.block(peer_protocol.Block(b)):
pass
time_now = uint64(time() * 1000)
time_now_plus_10 = time_now + 10000
cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS, time_now.to_bytes(8, 'big'), None)
dic = {cvp.opcode: [cvp]}
spend_bundle1 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, block.body.coinbase, dic)
tx1: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle1)
async for _ in full_node_1.transaction(tx1):
outbound: OutboundMessage = _
# Maybe transaction means that it's accepted in mempool
assert outbound.message.function == "maybe_transaction"
sb1 = await full_node_1.mempool.get_spendbundle(spend_bundle1.name())
assert sb1 is spend_bundle1
@pytest.mark.asyncio
async def test_assert_time_exceeds_both_cases(self, two_nodes):
num_blocks = 4
wallet_a = WalletTool()
coinbase_puzzlehash = wallet_a.get_new_puzzlehash()
wallet_receiver = WalletTool()
receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash)
full_node_1, full_node_2, server_1, server_2 = two_nodes
block = blocks[1]
for b in blocks:
async for _ in full_node_1.block(peer_protocol.Block(b)):
pass
time_now = uint64(time() * 1000)
time_now_plus_10 = time_now + 3000
cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS, time_now_plus_10.to_bytes(8, 'big'), None)
dic = {cvp.opcode: [cvp]}
spend_bundle1 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, block.body.coinbase, dic)
tx1: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle1)
async for _ in full_node_1.transaction(tx1):
outbound: OutboundMessage = _
assert outbound.message.function != "maybe_transaction"
sb1 = await full_node_1.mempool.get_spendbundle(spend_bundle1.name())
assert sb1 is None
# Sleep so that 3 sec passes
await asyncio.sleep(3)
tx1: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle1)
async for _ in full_node_1.transaction(tx1):
outbound: OutboundMessage = _
# Maybe transaction means that it's accepted in mempool
assert outbound.message.function == "maybe_transaction"
sb1 = await full_node_1.mempool.get_spendbundle(spend_bundle1.name())
assert sb1 is spend_bundle1

View File

@ -7,14 +7,12 @@ from blspy import ExtendedPrivateKey
from src.types.hashable import ProgramHash, CoinSolution, SpendBundle, Program, BLSSignature, Coin
from src.util.Conditions import conditions_by_opcode, ConditionVarPair, ConditionOpcode
from src.util.consensus import hash_key_pairs_for_conditions_dict, conditions_for_solution
from src.wallet import keychain
from src.wallet.BLSPrivateKey import BLSPrivateKey
from src.wallet.puzzles.p2_conditions import puzzle_for_conditions
from src.wallet.puzzles.p2_delegated_conditions import solution_for_conditions
from src.wallet.puzzles.p2_delegated_puzzle import puzzle_for_pk
from src.wallet.puzzles.puzzle_utils import make_assert_coin_consumed_condition, make_assert_min_time_condition, \
from src.wallet.puzzles.puzzle_utils import make_assert_coin_consumed_condition, \
make_assert_my_coin_id_condition, make_create_coin_condition, make_assert_block_index_exceeds_condition, \
make_assert_block_age_exceeds_condition, make_assert_aggsig_condition
make_assert_block_age_exceeds_condition, make_assert_aggsig_condition, make_assert_time_exceeds_condition
class WalletTool:
@ -82,8 +80,8 @@ class WalletTool:
ret.append(make_assert_aggsig_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_COIN_CONSUMED:
ret.append(make_assert_coin_consumed_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_MIN_TIME:
ret.append(make_assert_min_time_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_TIME_EXCEEDS:
ret.append(make_assert_time_exceeds_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_MY_COIN_ID:
ret.append(make_assert_my_coin_id_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS: