adding cic-eth as sub dir
This commit is contained in:
167
apps/cic-eth/tests/unit/api/test_callback.py
Normal file
167
apps/cic-eth/tests/unit/api/test_callback.py
Normal file
@@ -0,0 +1,167 @@
|
||||
# standard imports
|
||||
import socket
|
||||
import celery
|
||||
import threading
|
||||
import logging
|
||||
import time
|
||||
import json
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
import redis as redis_interface
|
||||
|
||||
# local imports
|
||||
from cic_eth.callbacks import http
|
||||
from cic_eth.callbacks import tcp
|
||||
from cic_eth.callbacks import redis
|
||||
|
||||
celery_app = celery.current_app
|
||||
|
||||
logg = celery_app.log.get_default_logger()
|
||||
|
||||
|
||||
class Response:
|
||||
|
||||
status = 200
|
||||
|
||||
@pytest.mark.skip()
|
||||
def test_callback_http(
|
||||
celery_session_worker,
|
||||
mocker,
|
||||
):
|
||||
|
||||
mocker.patch('cic_eth.callbacks.http.urlopen', return_value=Response())
|
||||
s = celery.signature(
|
||||
'cic_eth.callbacks.http.http',
|
||||
[
|
||||
'foo',
|
||||
'http://localhost:65000',
|
||||
1,
|
||||
],
|
||||
)
|
||||
t = s.apply_async()
|
||||
t.get()
|
||||
|
||||
|
||||
@pytest.mark.skip()
|
||||
def test_callback_tcp(
|
||||
celery_session_worker,
|
||||
):
|
||||
|
||||
timeout=2
|
||||
|
||||
data = {
|
||||
'foo': 'bar',
|
||||
'xyzzy': 42,
|
||||
}
|
||||
|
||||
class Accept(threading.Thread):
|
||||
|
||||
def __init__(self, socket):
|
||||
super(Accept, self).__init__()
|
||||
self.socket = socket
|
||||
self.exception = None
|
||||
|
||||
def run(self):
|
||||
(c, sockaddr) = self.socket.accept()
|
||||
echo = c.recv(1024)
|
||||
c.close()
|
||||
logg.debug('recived {} '.format(data))
|
||||
o = json.loads(echo)
|
||||
try:
|
||||
assert o == data
|
||||
except Exception as e:
|
||||
self.exception = e
|
||||
|
||||
def join(self):
|
||||
threading.Thread.join(self)
|
||||
if self.exception != None:
|
||||
raise self.exception
|
||||
|
||||
|
||||
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
|
||||
s.bind(('localhost', 0))
|
||||
s.settimeout(timeout)
|
||||
s.listen(1)
|
||||
sockaddr = s.getsockname()
|
||||
|
||||
a = Accept(s)
|
||||
a.start()
|
||||
|
||||
s_cb = celery.signature(
|
||||
'cic_eth.callbacks.tcp.tcp',
|
||||
[
|
||||
data,
|
||||
'{}:{}'.format(sockaddr[0], sockaddr[1]),
|
||||
'1',
|
||||
],
|
||||
queue=None,
|
||||
)
|
||||
s_cb.apply_async()
|
||||
a.join()
|
||||
s.close()
|
||||
|
||||
|
||||
def test_callback_redis(
|
||||
load_config,
|
||||
celery_session_worker,
|
||||
):
|
||||
|
||||
timeout=2
|
||||
|
||||
channel = 'barbarbar'
|
||||
host = load_config.get('REDIS_HOST', 'localhost')
|
||||
port = load_config.get('REDIS_PORT', '6379')
|
||||
db = load_config.get('REDIS_DB', '0')
|
||||
|
||||
data = {
|
||||
'foo': 'bar',
|
||||
'xyzzy': 42,
|
||||
}
|
||||
|
||||
class Accept(threading.Thread):
|
||||
|
||||
def __init__(self, pubsub):
|
||||
super(Accept, self).__init__()
|
||||
self.pubsub = pubsub
|
||||
self.exception = None
|
||||
|
||||
def run(self):
|
||||
self.pubsub.get_message() # subscribe message
|
||||
echo = self.pubsub.get_message(timeout=timeout)
|
||||
o = json.loads(echo['data'])
|
||||
logg.debug('recived {} '.format(o))
|
||||
try:
|
||||
assert o == data
|
||||
except Exception as e:
|
||||
self.exception = e
|
||||
|
||||
def join(self):
|
||||
threading.Thread.join(self)
|
||||
if self.exception != None:
|
||||
raise self.exception
|
||||
|
||||
ps = None
|
||||
try:
|
||||
r = redis_interface.Redis(host=host, port=int(port), db=int(db))
|
||||
ps = r.pubsub(
|
||||
)
|
||||
ps.subscribe(channel)
|
||||
except redis_interface.exceptions.ConnectionError as e:
|
||||
pytest.skip('cannot connect to redis, skipping test: {}'.format(e))
|
||||
|
||||
a = Accept(ps)
|
||||
a.start()
|
||||
|
||||
s_cb = celery.signature(
|
||||
'cic_eth.callbacks.redis.redis',
|
||||
[
|
||||
data,
|
||||
'{}:{}:{}:{}'.format(host, port, db, channel),
|
||||
'1',
|
||||
],
|
||||
queue=None,
|
||||
)
|
||||
s_cb.apply_async()
|
||||
a.join()
|
||||
r.close()
|
||||
29
apps/cic-eth/tests/unit/db/test_block_sync.py
Normal file
29
apps/cic-eth/tests/unit/db/test_block_sync.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.otx import OtxSync
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def test_db_block_sync(
|
||||
init_database,
|
||||
):
|
||||
|
||||
s = OtxSync('eip155:8995:bloxberg')
|
||||
|
||||
s.head(666, 12)
|
||||
assert s.head() == (666, 12)
|
||||
|
||||
s.session(42, 13)
|
||||
assert s.session() == (42, 13)
|
||||
|
||||
s.backlog(13, 2)
|
||||
assert s.backlog() == (13, 2)
|
||||
|
||||
assert not s.synced
|
||||
|
||||
s.backlog(42, 13)
|
||||
assert s.backlog() == (42, 13)
|
||||
assert s.synced
|
||||
29
apps/cic-eth/tests/unit/db/test_db_convert_transfer.py
Normal file
29
apps/cic-eth/tests/unit/db/test_db_convert_transfer.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import os
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from cic_eth.db import TxConvertTransfer
|
||||
from cic_eth.db.error import UnknownConvertError
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def test_convert_transfer(
|
||||
init_database,
|
||||
default_chain_spec,
|
||||
):
|
||||
|
||||
tx_hash_hex = '0x' + os.urandom(32).hex()
|
||||
recipient = '0x' + os.urandom(20).hex()
|
||||
txct = TxConvertTransfer(tx_hash_hex, recipient, str(default_chain_spec))
|
||||
init_database.add(txct)
|
||||
init_database.commit()
|
||||
|
||||
txct = TxConvertTransfer.get(tx_hash_hex)
|
||||
|
||||
assert txct.convert_tx_hash == tx_hash_hex
|
||||
|
||||
tx_hash_bogus_hex = '0x' + os.urandom(32).hex()
|
||||
with pytest.raises(UnknownConvertError):
|
||||
TxConvertTransfer.get(tx_hash_bogus_hex)
|
||||
5
apps/cic-eth/tests/unit/db/test_default.py
Normal file
5
apps/cic-eth/tests/unit/db/test_default.py
Normal file
@@ -0,0 +1,5 @@
|
||||
def test_db_init(
|
||||
init_database,
|
||||
):
|
||||
pass
|
||||
|
||||
67
apps/cic-eth/tests/unit/db/test_lock.py
Normal file
67
apps/cic-eth/tests/unit/db/test_lock.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# standard imports
|
||||
import os
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.lock import Lock
|
||||
from cic_eth.db.enum import LockEnum
|
||||
|
||||
|
||||
def test_lock(
|
||||
init_database,
|
||||
default_chain_spec,
|
||||
):
|
||||
|
||||
chain_str = str(default_chain_spec)
|
||||
|
||||
# Check matching flag for global (zero-address) lock
|
||||
a = 0xffffffffffffffff & LockEnum.CREATE
|
||||
r = Lock.set(chain_str, a)
|
||||
assert r == a
|
||||
assert Lock.check(chain_str, a) > 0
|
||||
|
||||
# Check matching flag for address specific lock
|
||||
address = '0x' + os.urandom(20).hex()
|
||||
b = 0xffffffffffffffff & (LockEnum.QUEUE | LockEnum.SEND)
|
||||
Lock.set(chain_str, b, address=address)
|
||||
assert Lock.check(chain_str, b, address=address) == b
|
||||
assert Lock.check(chain_str, a, address=address) == 0
|
||||
assert Lock.check(chain_str, b & LockEnum.QUEUE, address=address) == LockEnum.QUEUE
|
||||
assert Lock.check(chain_str, b) == 0
|
||||
|
||||
# Reset single flag
|
||||
r = Lock.reset(chain_str, LockEnum.QUEUE, address=address)
|
||||
assert r == LockEnum.SEND
|
||||
|
||||
# Reset to 0
|
||||
r = Lock.reset(chain_str, LockEnum.SEND, address=address)
|
||||
assert r == 0
|
||||
|
||||
# Row should be deleted when flags value reaches 0
|
||||
q = init_database.query(Lock)
|
||||
q = q.filter(Lock.address==address)
|
||||
assert q.first() == None
|
||||
|
||||
|
||||
|
||||
def test_lock_merge_check(
|
||||
init_database,
|
||||
default_chain_spec,
|
||||
):
|
||||
|
||||
chain_str = str(default_chain_spec)
|
||||
|
||||
foo_address = '0x' + os.urandom(20).hex()
|
||||
bar_address = '0x' + os.urandom(20).hex()
|
||||
|
||||
Lock.set(chain_str, LockEnum.CREATE)
|
||||
assert Lock.check_aggregate(chain_str, LockEnum.CREATE, address=foo_address) > 0
|
||||
assert Lock.check_aggregate(chain_str, LockEnum.CREATE, address=bar_address) > 0
|
||||
|
||||
|
||||
Lock.set(chain_str, LockEnum.CREATE, address=foo_address)
|
||||
assert Lock.check_aggregate(chain_str, LockEnum.CREATE, address=foo_address) > 0
|
||||
assert Lock.check_aggregate(chain_str, LockEnum.CREATE, address=bar_address) > 0
|
||||
|
||||
Lock.reset(chain_str, LockEnum.CREATE)
|
||||
assert Lock.check_aggregate(chain_str, LockEnum.CREATE, address=foo_address) > 0
|
||||
assert Lock.check_aggregate(chain_str, LockEnum.CREATE, address=bar_address) == 0
|
||||
20
apps/cic-eth/tests/unit/db/test_nonce_db.py
Normal file
20
apps/cic-eth/tests/unit/db/test_nonce_db.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# third-party imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.nonce import Nonce
|
||||
|
||||
def test_nonce_increment(
|
||||
init_database,
|
||||
eth_empty_accounts,
|
||||
database_engine,
|
||||
):
|
||||
|
||||
# if database_engine[:6] == 'sqlite':
|
||||
# pytest.skip('sqlite cannot lock tables which is required for this test, skipping')
|
||||
|
||||
nonce = Nonce.next(eth_empty_accounts[0], 3)
|
||||
assert nonce == 3
|
||||
|
||||
nonce = Nonce.next(eth_empty_accounts[0], 3)
|
||||
assert nonce == 4
|
||||
84
apps/cic-eth/tests/unit/db/test_otx.py
Normal file
84
apps/cic-eth/tests/unit/db/test_otx.py
Normal file
@@ -0,0 +1,84 @@
|
||||
# standard imports
|
||||
import os
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.base import SessionBase
|
||||
from cic_eth.db.models.otx import OtxStateLog
|
||||
from cic_eth.db.models.otx import Otx
|
||||
from cic_eth.db.enum import StatusEnum
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
@pytest.mark.skip()
|
||||
def test_get(
|
||||
init_w3,
|
||||
init_database,
|
||||
):
|
||||
|
||||
tx_def = {
|
||||
'from': init_w3.eth.accounts[0],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 0,
|
||||
'value': 101,
|
||||
'gasPrice': 2000000000,
|
||||
'gas': 21000,
|
||||
'data': '',
|
||||
'chainId': 1,
|
||||
}
|
||||
|
||||
session = init_database
|
||||
txs = []
|
||||
for i in range(10):
|
||||
nonce = init_w3.eth.getTransactionCount(init_w3.eth.accounts[0], 'pending')
|
||||
tx_def['nonce'] = nonce
|
||||
tx = init_w3.eth.sign_transaction(tx_def)
|
||||
tx_hash = init_w3.eth.send_raw_transaction(tx['raw'])
|
||||
logg.debug('tx {}'.format(tx))
|
||||
|
||||
address = init_w3.eth.accounts[i%3]
|
||||
otx = Otx(int((i/3)+1), address, '0x'+tx_hash.hex(), tx['raw'])
|
||||
txs.append(otx)
|
||||
session.add(otx)
|
||||
session.flush()
|
||||
|
||||
logg.debug(txs)
|
||||
session.commit()
|
||||
|
||||
txs[0].status = 0
|
||||
session.add(txs[0])
|
||||
session.commit()
|
||||
session.close()
|
||||
|
||||
get_txs = Otx.get()
|
||||
logg.debug(get_txs)
|
||||
|
||||
|
||||
def test_state_log(
|
||||
init_database,
|
||||
):
|
||||
|
||||
Otx.tracing = True
|
||||
|
||||
address = '0x' + os.urandom(20).hex()
|
||||
tx_hash = '0x' + os.urandom(32).hex()
|
||||
signed_tx = '0x' + os.urandom(128).hex()
|
||||
otx = Otx.add(0, address, tx_hash, signed_tx, session=init_database)
|
||||
|
||||
otx.waitforgas(session=init_database)
|
||||
otx.sent(session=init_database)
|
||||
otx.success(1024, session=init_database)
|
||||
|
||||
q = init_database.query(OtxStateLog)
|
||||
q = q.filter(OtxStateLog.otx_id==otx.id)
|
||||
q = q.order_by(OtxStateLog.date.asc())
|
||||
logs = q.all()
|
||||
|
||||
assert logs[0].status == StatusEnum.PENDING
|
||||
assert logs[1].status == StatusEnum.WAITFORGAS
|
||||
assert logs[2].status == StatusEnum.SENT
|
||||
assert logs[3].status == StatusEnum.SUCCESS
|
||||
55
apps/cic-eth/tests/unit/db/test_queue.py
Normal file
55
apps/cic-eth/tests/unit/db/test_queue.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_eth.db import Otx
|
||||
from cic_eth.db.error import TxStateChangeError
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
# Check that invalid transitions throw exceptions
|
||||
# sent
|
||||
def test_db_queue_states(
|
||||
init_database,
|
||||
):
|
||||
|
||||
session = init_database
|
||||
|
||||
# these values are completely arbitary
|
||||
tx_hash = '0xF182DFA3AD48723E7E222FE7B4C2C44C23CD4D7FF413E8999DFA15ECE53F'
|
||||
address = '0x38C5559D6EDDDA1F705D3AB1A664CA1B397EB119'
|
||||
signed_tx = '0xA5866A5383249AE843546BDA46235A1CA1614F538FB486140693C2EF1956FC53213F6AEF0F99F44D7103871AF3A12B126DCF9BFB7AF11143FAB3ECE2B452EE35D1320C4C7C6F999C8DF4EB09E729715B573F6672ED852547F552C4AE99D17DCD14C810'
|
||||
o = Otx(
|
||||
nonce=42,
|
||||
address=address[2:],
|
||||
tx_hash=tx_hash[2:],
|
||||
signed_tx=signed_tx[2:],
|
||||
)
|
||||
session.add(o)
|
||||
session.commit()
|
||||
|
||||
o.sent(session=session)
|
||||
session.commit()
|
||||
|
||||
# send after sent is ok
|
||||
o.sent(session=session)
|
||||
session.commit()
|
||||
|
||||
o.sendfail(session=session)
|
||||
session.commit()
|
||||
|
||||
with pytest.raises(TxStateChangeError):
|
||||
o.sendfail(session=session)
|
||||
|
||||
o.sent(session=session)
|
||||
session.commit()
|
||||
|
||||
o.minefail(1234, session=session)
|
||||
session.commit()
|
||||
|
||||
with pytest.raises(TxStateChangeError):
|
||||
o.sent(session=session)
|
||||
29
apps/cic-eth/tests/unit/db/test_role.py
Normal file
29
apps/cic-eth/tests/unit/db/test_role.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# local imports
|
||||
from cic_eth.db.models.role import AccountRole
|
||||
|
||||
def test_db_role(
|
||||
init_database,
|
||||
eth_empty_accounts,
|
||||
):
|
||||
|
||||
foo = AccountRole.set('foo', eth_empty_accounts[0])
|
||||
init_database.add(foo)
|
||||
init_database.commit()
|
||||
assert AccountRole.get_address('foo') == eth_empty_accounts[0]
|
||||
|
||||
bar = AccountRole.set('bar', eth_empty_accounts[1])
|
||||
init_database.add(bar)
|
||||
init_database.commit()
|
||||
assert AccountRole.get_address('bar') == eth_empty_accounts[1]
|
||||
|
||||
foo = AccountRole.set('foo', eth_empty_accounts[2])
|
||||
init_database.add(foo)
|
||||
init_database.commit()
|
||||
assert AccountRole.get_address('foo') == eth_empty_accounts[2]
|
||||
assert AccountRole.get_address('bar') == eth_empty_accounts[1]
|
||||
|
||||
tag = AccountRole.role_for(eth_empty_accounts[2])
|
||||
assert tag == 'foo'
|
||||
|
||||
tag = AccountRole.role_for(eth_empty_accounts[3])
|
||||
assert tag == None
|
||||
124
apps/cic-eth/tests/unit/db/test_tx.py
Normal file
124
apps/cic-eth/tests/unit/db/test_tx.py
Normal file
@@ -0,0 +1,124 @@
|
||||
# standard imports
|
||||
import os
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
from cic_registry import zero_address
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.tx import TxCache
|
||||
from cic_eth.db.models.otx import Otx
|
||||
from cic_eth.eth.task import sign_tx
|
||||
|
||||
|
||||
def test_set(
|
||||
init_w3,
|
||||
init_database,
|
||||
):
|
||||
|
||||
tx_def = {
|
||||
'from': init_w3.eth.accounts[0],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 0,
|
||||
'value': 500000000000000000000,
|
||||
'gasPrice': 2000000000,
|
||||
'gas': 21000,
|
||||
'data': '',
|
||||
'chainId': 1,
|
||||
}
|
||||
(tx_hash, tx_signed) = sign_tx(tx_def, 'Foo:1')
|
||||
otx = Otx(
|
||||
tx_def['nonce'],
|
||||
tx_def['from'],
|
||||
tx_hash,
|
||||
tx_signed,
|
||||
)
|
||||
|
||||
init_database.add(otx)
|
||||
init_database.commit()
|
||||
|
||||
bogus_from_token = '0x' + os.urandom(20).hex()
|
||||
to_value = int(tx_def['value'] / 2)
|
||||
|
||||
tx = TxCache(
|
||||
tx_hash,
|
||||
tx_def['from'],
|
||||
tx_def['to'],
|
||||
bogus_from_token,
|
||||
zero_address,
|
||||
tx_def['value'],
|
||||
to_value,
|
||||
666,
|
||||
13,
|
||||
)
|
||||
init_database.add(tx)
|
||||
init_database.commit()
|
||||
|
||||
tx_stored = init_database.query(TxCache).first()
|
||||
assert (tx_stored.sender == tx_def['from'])
|
||||
assert (tx_stored.recipient == tx_def['to'])
|
||||
assert (tx_stored.source_token_address == bogus_from_token)
|
||||
assert (tx_stored.destination_token_address == zero_address)
|
||||
assert (tx_stored.from_value == '1b1ae4d6e2ef500000')
|
||||
assert (tx_stored.to_value == '0d8d726b7177a80000')
|
||||
assert (tx_stored.values() == (tx_def['value'], to_value))
|
||||
assert (tx_stored.block_number == 666)
|
||||
assert (tx_stored.tx_index == 13)
|
||||
|
||||
|
||||
def test_clone(
|
||||
init_database,
|
||||
init_w3,
|
||||
):
|
||||
|
||||
txs = []
|
||||
for i in range(2):
|
||||
tx_def = {
|
||||
'from': init_w3.eth.accounts[0],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 0,
|
||||
'value': 500000000000000000000,
|
||||
'gasPrice': 2000000000 + i,
|
||||
'gas': 21000,
|
||||
'data': '',
|
||||
'chainId': 1,
|
||||
}
|
||||
(tx_hash, tx_signed) = sign_tx(tx_def, 'Foo:1')
|
||||
otx = Otx(
|
||||
tx_def['nonce'],
|
||||
tx_def['from'],
|
||||
tx_hash,
|
||||
tx_signed,
|
||||
)
|
||||
init_database.add(otx)
|
||||
tx_def['hash'] = tx_hash
|
||||
txs.append(tx_def)
|
||||
|
||||
init_database.commit()
|
||||
|
||||
txc = TxCache(
|
||||
txs[0]['hash'],
|
||||
txs[0]['from'],
|
||||
txs[0]['to'],
|
||||
zero_address,
|
||||
zero_address,
|
||||
txs[0]['value'],
|
||||
txs[0]['value'],
|
||||
)
|
||||
init_database.add(txc)
|
||||
init_database.commit()
|
||||
|
||||
TxCache.clone(txs[0]['hash'], txs[1]['hash'])
|
||||
|
||||
q = init_database.query(TxCache)
|
||||
q = q.join(Otx)
|
||||
q = q.filter(Otx.tx_hash==txs[1]['hash'])
|
||||
txc_clone = q.first()
|
||||
|
||||
assert txc_clone != None
|
||||
assert txc_clone.sender == txc.sender
|
||||
assert txc_clone.recipient == txc.recipient
|
||||
assert txc_clone.source_token_address == txc.source_token_address
|
||||
assert txc_clone.destination_token_address == txc.destination_token_address
|
||||
assert txc_clone.from_value == txc.from_value
|
||||
assert txc_clone.to_value == txc.to_value
|
||||
129
apps/cic-eth/tests/unit/eth/test_bancor.py
Normal file
129
apps/cic-eth/tests/unit/eth/test_bancor.py
Normal file
@@ -0,0 +1,129 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
from cic_registry import CICRegistry
|
||||
|
||||
# local imports
|
||||
from cic_eth.eth.bancor import BancorTxFactory, unpack_convert
|
||||
from cic_eth.eth.bancor import resolve_converters_by_tokens
|
||||
from cic_eth.eth.util import unpack_signed_raw_tx
|
||||
from cic_eth.queue.tx import create as queue_create
|
||||
from cic_eth.eth.bancor import otx_cache_convert
|
||||
from cic_eth.db.models.otx import Otx
|
||||
from cic_eth.db.models.tx import TxCache
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def test_resolve_converters_by_tokens(
|
||||
cic_registry,
|
||||
init_w3,
|
||||
bancor_tokens,
|
||||
bancor_registry,
|
||||
default_chain_spec,
|
||||
):
|
||||
|
||||
r = resolve_converters_by_tokens(
|
||||
[
|
||||
{
|
||||
'address': bancor_tokens[0],
|
||||
},
|
||||
{
|
||||
'address': bancor_tokens[1],
|
||||
},
|
||||
],
|
||||
str(default_chain_spec),
|
||||
)
|
||||
|
||||
logg.warning('this test should be hardened by verifying the converters')
|
||||
for t in r:
|
||||
assert t['converters'] != None
|
||||
assert len(t['converters']) == 1
|
||||
|
||||
|
||||
def test_unpack_convert(
|
||||
default_chain_spec,
|
||||
cic_registry,
|
||||
init_w3,
|
||||
init_rpc,
|
||||
bancor_tokens,
|
||||
bancor_registry,
|
||||
):
|
||||
|
||||
txf = BancorTxFactory(init_w3.eth.accounts[0], init_rpc)
|
||||
|
||||
default_reserve = CICRegistry.get_contract(default_chain_spec, 'BNTToken')
|
||||
|
||||
convert_tx = txf.convert(
|
||||
bancor_tokens[0],
|
||||
bancor_tokens[1],
|
||||
default_reserve.address(),
|
||||
42,
|
||||
13,
|
||||
default_chain_spec,
|
||||
)
|
||||
|
||||
s = init_w3.eth.sign_transaction(convert_tx)
|
||||
s_bytes = bytes.fromhex(s['raw'][2:])
|
||||
tx_dict = unpack_signed_raw_tx(s_bytes, default_chain_spec.chain_id())
|
||||
|
||||
convert_contract = CICRegistry.get_contract(default_chain_spec, 'BancorNetwork')
|
||||
assert tx_dict['from'] == init_w3.eth.accounts[0]
|
||||
assert tx_dict['to'] == convert_contract.address()
|
||||
assert tx_dict['value'] == 0
|
||||
|
||||
convert_data = unpack_convert(tx_dict['data'])
|
||||
|
||||
assert convert_data['amount'] == 42
|
||||
assert convert_data['min_return'] == 13
|
||||
assert convert_data['source_token'] == bancor_tokens[0]
|
||||
assert convert_data['destination_token'] == bancor_tokens[1]
|
||||
assert convert_data['fee_recipient'] == '0000000000000000000000000000000000000000000000000000000000000000'
|
||||
assert convert_data['fee'] == 0
|
||||
|
||||
|
||||
def test_queue_cache_convert(
|
||||
default_chain_spec,
|
||||
init_w3,
|
||||
init_rpc,
|
||||
init_database,
|
||||
cic_registry,
|
||||
bancor_registry,
|
||||
bancor_tokens,
|
||||
):
|
||||
|
||||
txf = BancorTxFactory(init_w3.eth.accounts[0], init_rpc)
|
||||
amount = 42
|
||||
min_return = 13
|
||||
default_reserve = CICRegistry.get_contract(default_chain_spec, 'BNTToken', 'ERC20')
|
||||
transfer_tx = txf.convert(
|
||||
bancor_tokens[0],
|
||||
bancor_tokens[1],
|
||||
default_reserve.address(),
|
||||
amount,
|
||||
min_return,
|
||||
default_chain_spec,
|
||||
)
|
||||
tx_signed = init_w3.eth.sign_transaction(transfer_tx)
|
||||
tx_hash = init_w3.eth.sendRawTransaction(tx_signed['raw'])
|
||||
tx_hash_hex = tx_hash.hex()
|
||||
nonce = int(tx_signed['nonce'][2:], 16)
|
||||
tx_hash_queue = queue_create(nonce, init_w3.eth.accounts[0], tx_hash_hex, tx_signed['raw'], str(default_chain_spec))
|
||||
tx_hash_cache = otx_cache_convert(tx_hash_hex, tx_signed['raw'], str(default_chain_spec))
|
||||
|
||||
assert tx_hash_hex == tx_hash_queue
|
||||
assert tx_hash_hex == tx_hash_cache
|
||||
|
||||
session = Otx.create_session()
|
||||
otx = session.query(Otx).filter(Otx.tx_hash==tx_hash_hex).first()
|
||||
assert otx.tx_hash == tx_hash_hex
|
||||
|
||||
txc = session.query(TxCache).filter(TxCache.otx_id==otx.id).first()
|
||||
|
||||
assert txc.sender == init_w3.eth.accounts[0]
|
||||
assert txc.recipient == init_w3.eth.accounts[0]
|
||||
assert txc.source_token_address == bancor_tokens[0]
|
||||
assert txc.destination_token_address == bancor_tokens[1]
|
||||
assert txc.values() == (amount, amount)
|
||||
51
apps/cic-eth/tests/unit/eth/test_nonce.py
Normal file
51
apps/cic-eth/tests/unit/eth/test_nonce.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# local imports
|
||||
from cic_eth.eth.nonce import NonceOracle
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def test_nonce_sequence(
|
||||
eth_empty_accounts,
|
||||
init_database,
|
||||
init_rpc,
|
||||
):
|
||||
|
||||
account= init_rpc.w3.eth.personal.new_account('')
|
||||
no = NonceOracle(account, 0)
|
||||
n = no.next()
|
||||
assert n == 0
|
||||
|
||||
n = no.next()
|
||||
assert n == 1
|
||||
|
||||
init_rpc.w3.eth.sendTransaction({
|
||||
'from': init_rpc.w3.eth.accounts[0],
|
||||
'to': account,
|
||||
'value': 200000000,
|
||||
})
|
||||
init_rpc.w3.eth.sendTransaction({
|
||||
'from': account,
|
||||
'to': eth_empty_accounts[0],
|
||||
'value': 100,
|
||||
})
|
||||
|
||||
c = init_rpc.w3.eth.getTransactionCount(account, 'pending')
|
||||
logg.debug('nonce {}'.format(c))
|
||||
|
||||
account= init_rpc.w3.eth.personal.new_account('')
|
||||
no = NonceOracle(account, c)
|
||||
|
||||
n = no.next()
|
||||
assert n == 1
|
||||
|
||||
n = no.next()
|
||||
assert n == 2
|
||||
|
||||
# try with bogus value
|
||||
no = NonceOracle(account, 4)
|
||||
n = no.next()
|
||||
assert n == 3
|
||||
|
||||
24
apps/cic-eth/tests/unit/eth/test_raw.py
Normal file
24
apps/cic-eth/tests/unit/eth/test_raw.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from cic_eth.eth.util import unpack_signed_raw_tx
|
||||
from cic_eth.eth.task import sign_tx
|
||||
|
||||
def test_unpack(
|
||||
init_rpc,
|
||||
w3,
|
||||
):
|
||||
|
||||
tx = {
|
||||
'from': w3.eth.accounts[1],
|
||||
'to': w3.eth.accounts[0],
|
||||
'nonce': 0,
|
||||
'value': 1024,
|
||||
'gas': 21000,
|
||||
'gasPrice': 200000000,
|
||||
'data': '0x',
|
||||
'chainId': 8995,
|
||||
}
|
||||
|
||||
(tx_hash, tx_raw) = sign_tx(tx, 'Foo:8995')
|
||||
|
||||
tx_recovered = unpack_signed_raw_tx(bytes.fromhex(tx_raw[2:]), 8995)
|
||||
|
||||
assert tx_hash == tx_recovered['hash']
|
||||
88
apps/cic-eth/tests/unit/eth/test_token.py
Normal file
88
apps/cic-eth/tests/unit/eth/test_token.py
Normal file
@@ -0,0 +1,88 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
from cic_registry import CICRegistry
|
||||
|
||||
# local imports
|
||||
from cic_eth.eth.token import TokenTxFactory, unpack_transfer, otx_cache_transfer
|
||||
from cic_eth.eth.util import unpack_signed_raw_tx
|
||||
from cic_eth.queue.tx import create as queue_create
|
||||
from cic_eth.db.models.otx import Otx
|
||||
from cic_eth.db.models.tx import TxCache
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def test_unpack_transfer(
|
||||
default_chain_spec,
|
||||
init_w3,
|
||||
init_rpc,
|
||||
cic_registry,
|
||||
bancor_tokens,
|
||||
bancor_registry,
|
||||
):
|
||||
|
||||
source_token = CICRegistry.get_address(default_chain_spec, bancor_tokens[0])
|
||||
logg.debug('bancor tokens {} {}'.format(bancor_tokens, source_token))
|
||||
txf = TokenTxFactory(init_w3.eth.accounts[0], init_rpc)
|
||||
transfer_tx = txf.transfer(
|
||||
source_token.address(),
|
||||
init_w3.eth.accounts[1],
|
||||
42,
|
||||
default_chain_spec,
|
||||
)
|
||||
s = init_w3.eth.sign_transaction(transfer_tx)
|
||||
s_bytes = bytes.fromhex(s['raw'][2:])
|
||||
tx_dict = unpack_signed_raw_tx(s_bytes, default_chain_spec.chain_id())
|
||||
assert tx_dict['from'] == init_w3.eth.accounts[0]
|
||||
assert tx_dict['to'] == bancor_tokens[0]
|
||||
assert tx_dict['value'] == 0
|
||||
|
||||
transfer_data = unpack_transfer(tx_dict['data'])
|
||||
|
||||
assert transfer_data['to'] == init_w3.eth.accounts[1]
|
||||
assert transfer_data['amount'] == 42
|
||||
|
||||
|
||||
def test_queue_cache_transfer(
|
||||
default_chain_spec,
|
||||
init_w3,
|
||||
init_rpc,
|
||||
init_database,
|
||||
cic_registry,
|
||||
bancor_tokens,
|
||||
bancor_registry,
|
||||
):
|
||||
|
||||
source_token = CICRegistry.get_address(default_chain_spec, bancor_tokens[0])
|
||||
txf = TokenTxFactory(init_w3.eth.accounts[0], init_rpc)
|
||||
value = 42
|
||||
transfer_tx = txf.transfer(
|
||||
source_token.address(),
|
||||
init_w3.eth.accounts[1],
|
||||
value,
|
||||
default_chain_spec,
|
||||
)
|
||||
tx_signed = init_w3.eth.sign_transaction(transfer_tx)
|
||||
tx_hash = init_w3.eth.sendRawTransaction(tx_signed['raw'])
|
||||
tx_hash_hex = tx_hash.hex()
|
||||
nonce = int(tx_signed['nonce'][2:], 16)
|
||||
tx_hash_queue = queue_create(nonce, init_w3.eth.accounts[0], tx_hash_hex, tx_signed['raw'], str(default_chain_spec))
|
||||
tx_hash_cache = otx_cache_transfer(tx_hash_hex, tx_signed['raw'], str(default_chain_spec))
|
||||
|
||||
assert tx_hash_hex == tx_hash_queue
|
||||
assert tx_hash_hex == tx_hash_cache
|
||||
|
||||
session = Otx.create_session()
|
||||
otx = session.query(Otx).filter(Otx.tx_hash==tx_hash_hex).first()
|
||||
assert otx.tx_hash == tx_hash_hex
|
||||
|
||||
txc = session.query(TxCache).filter(TxCache.otx_id==otx.id).first()
|
||||
|
||||
assert txc.sender == init_w3.eth.accounts[0]
|
||||
assert txc.recipient == init_w3.eth.accounts[1]
|
||||
assert txc.source_token_address == bancor_tokens[0]
|
||||
assert txc.destination_token_address == bancor_tokens[0]
|
||||
assert txc.values() == (value, value)
|
||||
22
apps/cic-eth/tests/unit/queue/test_otx_state_log.py
Normal file
22
apps/cic-eth/tests/unit/queue/test_otx_state_log.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# standard imports
|
||||
import os
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.otx import Otx
|
||||
from cic_eth.queue.tx import get_state_log
|
||||
|
||||
|
||||
def test_otx_state_log(
|
||||
init_database,
|
||||
):
|
||||
|
||||
Otx.tracing = True
|
||||
|
||||
address = '0x' + os.urandom(20).hex()
|
||||
tx_hash = '0x' + os.urandom(32).hex()
|
||||
signed_tx = '0x' + os.urandom(128).hex()
|
||||
otx = Otx.add(0, address, tx_hash, signed_tx, session=init_database)
|
||||
init_database.commit()
|
||||
|
||||
log = get_state_log(tx_hash)
|
||||
assert len(log) == 1
|
||||
65
apps/cic-eth/tests/unit/queue/test_queue_lock.py
Normal file
65
apps/cic-eth/tests/unit/queue/test_queue_lock.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# standard imports
|
||||
import os
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_eth.queue.tx import create as queue_create
|
||||
from cic_eth.db.models.lock import Lock
|
||||
from cic_eth.db.enum import LockEnum
|
||||
from cic_eth.error import LockedError
|
||||
|
||||
|
||||
def test_queue_lock(
|
||||
init_database,
|
||||
default_chain_spec,
|
||||
):
|
||||
|
||||
chain_str = str(default_chain_spec)
|
||||
|
||||
address = '0x' + os.urandom(20).hex()
|
||||
tx_hash = '0x' + os.urandom(32).hex()
|
||||
tx_raw = '0x' + os.urandom(128).hex()
|
||||
|
||||
Lock.set(chain_str, LockEnum.QUEUE)
|
||||
with pytest.raises(LockedError):
|
||||
queue_create(
|
||||
0,
|
||||
address,
|
||||
tx_hash,
|
||||
tx_raw,
|
||||
chain_str
|
||||
)
|
||||
|
||||
Lock.set(chain_str, LockEnum.QUEUE, address=address)
|
||||
with pytest.raises(LockedError):
|
||||
queue_create(
|
||||
0,
|
||||
address,
|
||||
tx_hash,
|
||||
tx_raw,
|
||||
chain_str
|
||||
)
|
||||
|
||||
Lock.reset(chain_str, LockEnum.QUEUE)
|
||||
with pytest.raises(LockedError):
|
||||
queue_create(
|
||||
0,
|
||||
address,
|
||||
tx_hash,
|
||||
tx_raw,
|
||||
chain_str
|
||||
)
|
||||
|
||||
Lock.set(chain_str, LockEnum.QUEUE, address=address, tx_hash=tx_hash)
|
||||
with pytest.raises(LockedError):
|
||||
queue_create(
|
||||
0,
|
||||
address,
|
||||
tx_hash,
|
||||
tx_raw,
|
||||
chain_str
|
||||
)
|
||||
|
||||
|
||||
500
apps/cic-eth/tests/unit/queue/test_tx_queue.py
Normal file
500
apps/cic-eth/tests/unit/queue/test_tx_queue.py
Normal file
@@ -0,0 +1,500 @@
|
||||
# standard imports import logging
|
||||
import datetime
|
||||
import os
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
from sqlalchemy import DateTime
|
||||
from cic_registry import CICRegistry
|
||||
|
||||
# local imports
|
||||
from cic_eth.eth.rpc import RpcClient
|
||||
from cic_eth.eth.tx import cache_gas_refill_data
|
||||
from cic_eth.db.models.otx import Otx
|
||||
from cic_eth.db.models.otx import OtxSync
|
||||
from cic_eth.db.models.tx import TxCache
|
||||
from cic_eth.db.models.lock import Lock
|
||||
from cic_eth.db.models.base import SessionBase
|
||||
from cic_eth.db.enum import StatusEnum
|
||||
from cic_eth.db.enum import LockEnum
|
||||
from cic_eth.queue.tx import create as queue_create
|
||||
from cic_eth.queue.tx import set_final_status
|
||||
from cic_eth.queue.tx import set_sent_status
|
||||
from cic_eth.queue.tx import set_waitforgas
|
||||
from cic_eth.queue.tx import set_ready
|
||||
from cic_eth.queue.tx import get_paused_txs
|
||||
from cic_eth.queue.tx import get_upcoming_tx
|
||||
from cic_eth.queue.tx import get_account_tx
|
||||
from cic_eth.queue.tx import get_tx
|
||||
from cic_eth.eth.util import unpack_signed_raw_tx
|
||||
from cic_eth.db.error import TxStateChangeError
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def test_finalize(
|
||||
default_chain_spec,
|
||||
init_w3,
|
||||
init_database,
|
||||
):
|
||||
|
||||
tx_hashes = []
|
||||
for i in range(1, 6):
|
||||
tx = {
|
||||
'from': init_w3.eth.accounts[0],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 42 + int(i/5),
|
||||
'gas': 21000,
|
||||
'gasPrice': 1000000*i,
|
||||
'value': 128,
|
||||
'chainId': 666,
|
||||
'data': '',
|
||||
}
|
||||
logg.debug('nonce {}'.format(tx['nonce']))
|
||||
tx_signed = init_w3.eth.sign_transaction(tx)
|
||||
#tx_hash = RpcClient.w3.keccak(hexstr=tx_signed['raw'])
|
||||
tx_hash = init_w3.keccak(hexstr=tx_signed['raw'])
|
||||
queue_create(tx['nonce'], tx['from'], tx_hash.hex(), tx_signed['raw'], str(default_chain_spec))
|
||||
cache_gas_refill_data(tx_hash.hex(), tx)
|
||||
tx_hashes.append(tx_hash.hex())
|
||||
|
||||
if i < 4:
|
||||
set_sent_status(tx_hash.hex())
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[0]).first()
|
||||
assert otx.status == StatusEnum.OBSOLETED
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[1]).first()
|
||||
assert otx.status == StatusEnum.OBSOLETED
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[2]).first()
|
||||
assert otx.status == StatusEnum.OBSOLETED
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[3]).first()
|
||||
assert otx.status == StatusEnum.PENDING
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[4]).first()
|
||||
assert otx.status == StatusEnum.PENDING
|
||||
|
||||
set_sent_status(tx_hashes[3], False)
|
||||
set_sent_status(tx_hashes[4], False)
|
||||
set_final_status(tx_hashes[3], 1024)
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[0]).first()
|
||||
assert otx.status == StatusEnum.CANCELLED
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[1]).first()
|
||||
assert otx.status == StatusEnum.CANCELLED
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[2]).first()
|
||||
assert otx.status == StatusEnum.CANCELLED
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[3]).first()
|
||||
assert otx.status == StatusEnum.SUCCESS
|
||||
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hashes[4]).first()
|
||||
assert otx.status == StatusEnum.SENT
|
||||
|
||||
|
||||
def test_expired(
|
||||
default_chain_spec,
|
||||
init_database,
|
||||
init_w3,
|
||||
):
|
||||
|
||||
tx_hashes = []
|
||||
for i in range(1, 6):
|
||||
tx = {
|
||||
'from': init_w3.eth.accounts[0],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 42 + int(i/2),
|
||||
'gas': 21000,
|
||||
'gasPrice': 1000000*i,
|
||||
'value': 128,
|
||||
'chainId': 666,
|
||||
'data': '0x',
|
||||
}
|
||||
tx_signed = init_w3.eth.sign_transaction(tx)
|
||||
#tx_hash = RpcClient.w3.keccak(hexstr=tx_signed['raw'])
|
||||
tx_hash = init_w3.keccak(hexstr=tx_signed['raw'])
|
||||
queue_create(tx['nonce'], tx['from'], tx_hash.hex(), tx_signed['raw'], str(default_chain_spec))
|
||||
cache_gas_refill_data(tx_hash.hex(), tx)
|
||||
tx_hashes.append(tx_hash.hex())
|
||||
set_sent_status(tx_hash.hex(), False)
|
||||
otx = init_database.query(Otx).filter(Otx.tx_hash==tx_hash.hex()).first()
|
||||
fake_created = datetime.datetime.utcnow() - datetime.timedelta(seconds=40*i)
|
||||
otx.date_created = fake_created
|
||||
init_database.add(otx)
|
||||
init_database.commit()
|
||||
init_database.refresh(otx)
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
delta = datetime.timedelta(seconds=61)
|
||||
then = now - delta
|
||||
|
||||
otxs = OtxSync.get_expired(then)
|
||||
nonce_acc = 0
|
||||
for otx in otxs:
|
||||
nonce_acc += otx.nonce
|
||||
|
||||
assert nonce_acc == (43 + 44)
|
||||
|
||||
|
||||
def test_get_paused(
|
||||
init_w3,
|
||||
init_database,
|
||||
cic_registry,
|
||||
default_chain_spec,
|
||||
):
|
||||
|
||||
tx_hashes = []
|
||||
for i in range(1, 3):
|
||||
tx = {
|
||||
'from': init_w3.eth.accounts[0],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 42 + int(i),
|
||||
'gas': 21000,
|
||||
'gasPrice': 1000000*i,
|
||||
'value': 128,
|
||||
'chainId': 8995,
|
||||
'data': '0x',
|
||||
}
|
||||
logg.debug('nonce {}'.format(tx['nonce']))
|
||||
tx_signed = init_w3.eth.sign_transaction(tx)
|
||||
#tx_hash = RpcClient.w3.keccak(hexstr=tx_signed['raw'])
|
||||
tx_hash = init_w3.keccak(hexstr=tx_signed['raw'])
|
||||
queue_create(tx['nonce'], tx['from'], tx_hash.hex(), tx_signed['raw'], str(default_chain_spec))
|
||||
cache_gas_refill_data(tx_hash.hex(), tx)
|
||||
tx_hashes.append(tx_hash.hex())
|
||||
|
||||
#txs = get_paused_txs(recipient=init_w3.eth.accounts[1])
|
||||
txs = get_paused_txs(sender=init_w3.eth.accounts[0])
|
||||
assert len(txs.keys()) == 0
|
||||
|
||||
q = init_database.query(Otx)
|
||||
q = q.filter(Otx.tx_hash==tx_hashes[0])
|
||||
r = q.first()
|
||||
r.waitforgas(session=init_database)
|
||||
init_database.add(r)
|
||||
init_database.commit()
|
||||
|
||||
chain_id = default_chain_spec.chain_id()
|
||||
txs = get_paused_txs(chain_id=chain_id)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
#txs = get_paused_txs(recipient=init_w3.eth.accounts[1])
|
||||
txs = get_paused_txs(sender=init_w3.eth.accounts[0], chain_id=chain_id)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
txs = get_paused_txs(status=StatusEnum.WAITFORGAS)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
#txs = get_paused_txs(recipient=init_w3.eth.accounts[1], status=StatusEnum.WAITFORGAS)
|
||||
txs = get_paused_txs(sender=init_w3.eth.accounts[0], status=StatusEnum.WAITFORGAS, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
|
||||
q = init_database.query(Otx)
|
||||
q = q.filter(Otx.tx_hash==tx_hashes[1])
|
||||
o = q.first()
|
||||
o.waitforgas(session=init_database)
|
||||
init_database.add(o)
|
||||
init_database.commit()
|
||||
|
||||
txs = get_paused_txs()
|
||||
assert len(txs.keys()) == 2
|
||||
|
||||
#txs = get_paused_txs(recipient=init_w3.eth.accounts[1])
|
||||
txs = get_paused_txs(sender=init_w3.eth.accounts[0], chain_id=chain_id)
|
||||
assert len(txs.keys()) == 2
|
||||
|
||||
txs = get_paused_txs(status=StatusEnum.WAITFORGAS, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 2
|
||||
|
||||
#txs = get_paused_txs(recipient=init_w3.eth.accounts[1], status=StatusEnum.WAITFORGAS)
|
||||
txs = get_paused_txs(sender=init_w3.eth.accounts[0], status=StatusEnum.WAITFORGAS, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 2
|
||||
|
||||
|
||||
q = init_database.query(Otx)
|
||||
q = q.filter(Otx.tx_hash==tx_hashes[1])
|
||||
o = q.first()
|
||||
o.sendfail(session=init_database)
|
||||
init_database.add(o)
|
||||
init_database.commit()
|
||||
|
||||
txs = get_paused_txs()
|
||||
assert len(txs.keys()) == 2
|
||||
|
||||
txs = get_paused_txs(sender=init_w3.eth.accounts[0], chain_id=chain_id)
|
||||
assert len(txs.keys()) == 2
|
||||
|
||||
txs = get_paused_txs(status=StatusEnum.WAITFORGAS, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
#txs = get_paused_txs(recipient=init_w3.eth.accounts[1], status=StatusEnum.WAITFORGAS)
|
||||
txs = get_paused_txs(sender=init_w3.eth.accounts[0], status=StatusEnum.WAITFORGAS, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
|
||||
def test_get_upcoming(
|
||||
default_chain_spec,
|
||||
init_w3,
|
||||
init_database,
|
||||
cic_registry,
|
||||
):
|
||||
|
||||
tx_hashes = []
|
||||
for i in range(0, 7):
|
||||
tx = {
|
||||
'from': init_w3.eth.accounts[i % 3],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 42 + int(i / 3),
|
||||
'gas': 21000,
|
||||
'gasPrice': 1000000*i,
|
||||
'value': 128,
|
||||
'chainId': 8995,
|
||||
'data': '0x',
|
||||
}
|
||||
tx_signed = init_w3.eth.sign_transaction(tx)
|
||||
tx_hash = init_w3.keccak(hexstr=tx_signed['raw'])
|
||||
logg.debug('{} nonce {} {}'.format(i, tx['nonce'], tx_hash.hex()))
|
||||
queue_create(tx['nonce'], tx['from'], tx_hash.hex(), tx_signed['raw'], str(default_chain_spec))
|
||||
cache_gas_refill_data(tx_hash.hex(), tx)
|
||||
tx_hashes.append(tx_hash.hex())
|
||||
|
||||
chain_id = int(default_chain_spec.chain_id())
|
||||
|
||||
txs = get_upcoming_tx(StatusEnum.PENDING, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 3
|
||||
|
||||
tx = unpack_signed_raw_tx(bytes.fromhex(txs[tx_hashes[0]][2:]), chain_id)
|
||||
assert tx['nonce'] == 42
|
||||
|
||||
tx = unpack_signed_raw_tx(bytes.fromhex(txs[tx_hashes[1]][2:]), chain_id)
|
||||
assert tx['nonce'] == 42
|
||||
|
||||
tx = unpack_signed_raw_tx(bytes.fromhex(txs[tx_hashes[2]][2:]), chain_id)
|
||||
assert tx['nonce'] == 42
|
||||
|
||||
q = init_database.query(TxCache)
|
||||
q = q.filter(TxCache.sender==init_w3.eth.accounts[0])
|
||||
for o in q.all():
|
||||
o.date_checked -= datetime.timedelta(seconds=30)
|
||||
init_database.add(o)
|
||||
init_database.commit()
|
||||
|
||||
before = datetime.datetime.now() - datetime.timedelta(seconds=20)
|
||||
logg.debug('before {}'.format(before))
|
||||
txs = get_upcoming_tx(StatusEnum.PENDING, before=before)
|
||||
logg.debug('txs {} {}'.format(txs.keys(), txs.values()))
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
# Now date checked has been set to current time, and the check returns no results
|
||||
txs = get_upcoming_tx(StatusEnum.PENDING, before=before)
|
||||
logg.debug('txs {} {}'.format(txs.keys(), txs.values()))
|
||||
assert len(txs.keys()) == 0
|
||||
|
||||
set_sent_status(tx_hashes[0])
|
||||
|
||||
txs = get_upcoming_tx(StatusEnum.PENDING)
|
||||
assert len(txs.keys()) == 3
|
||||
with pytest.raises(KeyError):
|
||||
tx = txs[tx_hashes[0]]
|
||||
|
||||
tx = unpack_signed_raw_tx(bytes.fromhex(txs[tx_hashes[3]][2:]), chain_id)
|
||||
assert tx['nonce'] == 43
|
||||
|
||||
set_waitforgas(tx_hashes[1])
|
||||
txs = get_upcoming_tx(StatusEnum.PENDING)
|
||||
assert len(txs.keys()) == 3
|
||||
with pytest.raises(KeyError):
|
||||
tx = txs[tx_hashes[1]]
|
||||
|
||||
tx = unpack_signed_raw_tx(bytes.fromhex(txs[tx_hashes[3]][2:]), chain_id)
|
||||
assert tx['nonce'] == 43
|
||||
|
||||
|
||||
txs = get_upcoming_tx(StatusEnum.WAITFORGAS)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
|
||||
def test_upcoming_with_lock(
|
||||
default_chain_spec,
|
||||
init_database,
|
||||
init_w3,
|
||||
):
|
||||
|
||||
chain_id = int(default_chain_spec.chain_id())
|
||||
chain_str = str(default_chain_spec)
|
||||
|
||||
tx = {
|
||||
'from': init_w3.eth.accounts[0],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 42,
|
||||
'gas': 21000,
|
||||
'gasPrice': 1000000,
|
||||
'value': 128,
|
||||
'chainId': 8995,
|
||||
'data': '0x',
|
||||
}
|
||||
tx_signed = init_w3.eth.sign_transaction(tx)
|
||||
tx_hash = init_w3.keccak(hexstr=tx_signed['raw'])
|
||||
logg.debug('nonce {} {}'.format(tx['nonce'], tx_hash.hex()))
|
||||
queue_create(tx['nonce'], tx['from'], tx_hash.hex(), tx_signed['raw'], str(default_chain_spec))
|
||||
cache_gas_refill_data(tx_hash.hex(), tx)
|
||||
|
||||
txs = get_upcoming_tx(StatusEnum.PENDING, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
Lock.set(chain_str, LockEnum.SEND, address=init_w3.eth.accounts[0])
|
||||
|
||||
txs = get_upcoming_tx(StatusEnum.PENDING, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 0
|
||||
|
||||
tx = {
|
||||
'from': init_w3.eth.accounts[1],
|
||||
'to': init_w3.eth.accounts[0],
|
||||
'nonce': 42,
|
||||
'gas': 21000,
|
||||
'gasPrice': 1000000,
|
||||
'value': 128,
|
||||
'chainId': 8995,
|
||||
'data': '0x',
|
||||
}
|
||||
tx_signed = init_w3.eth.sign_transaction(tx)
|
||||
tx_hash = init_w3.keccak(hexstr=tx_signed['raw'])
|
||||
logg.debug('nonce {} {}'.format(tx['nonce'], tx_hash.hex()))
|
||||
queue_create(tx['nonce'], tx['from'], tx_hash.hex(), tx_signed['raw'], str(default_chain_spec))
|
||||
cache_gas_refill_data(tx_hash.hex(), tx)
|
||||
|
||||
txs = get_upcoming_tx(StatusEnum.PENDING, chain_id=chain_id)
|
||||
assert len(txs.keys()) == 1
|
||||
|
||||
|
||||
def test_obsoletion(
|
||||
default_chain_spec,
|
||||
init_w3,
|
||||
init_database,
|
||||
):
|
||||
|
||||
tx_hashes = []
|
||||
for i in range(0, 4):
|
||||
tx = {
|
||||
'from': init_w3.eth.accounts[int(i/2)],
|
||||
'to': init_w3.eth.accounts[1],
|
||||
'nonce': 42 + int(i/3),
|
||||
'gas': 21000,
|
||||
'gasPrice': 1000000*i,
|
||||
'value': 128,
|
||||
'chainId': 8995,
|
||||
'data': '0x',
|
||||
}
|
||||
|
||||
logg.debug('nonce {}'.format(tx['nonce']))
|
||||
tx_signed = init_w3.eth.sign_transaction(tx)
|
||||
tx_hash = init_w3.keccak(hexstr=tx_signed['raw'])
|
||||
queue_create(tx['nonce'], tx['from'], tx_hash.hex(), tx_signed['raw'], str(default_chain_spec))
|
||||
cache_gas_refill_data(tx_hash.hex(), tx)
|
||||
tx_hashes.append(tx_hash.hex())
|
||||
|
||||
if i < 2:
|
||||
set_sent_status(tx_hash.hex())
|
||||
|
||||
session = SessionBase.create_session()
|
||||
q = session.query(Otx)
|
||||
q = q.filter(Otx.status==StatusEnum.OBSOLETED)
|
||||
z = 0
|
||||
for o in q.all():
|
||||
z += o.nonce
|
||||
|
||||
session.close()
|
||||
assert z == 42
|
||||
|
||||
set_final_status(tx_hashes[1], 362436, True)
|
||||
|
||||
session = SessionBase.create_session()
|
||||
q = session.query(Otx)
|
||||
q = q.filter(Otx.status==StatusEnum.OBSOLETED)
|
||||
zo = 0
|
||||
for o in q.all():
|
||||
zo += o.nonce
|
||||
|
||||
q = session.query(Otx)
|
||||
q = q.filter(Otx.status==StatusEnum.CANCELLED)
|
||||
zc = 0
|
||||
for o in q.all():
|
||||
zc += o.nonce
|
||||
|
||||
session.close()
|
||||
assert zo == 0
|
||||
assert zc == 42
|
||||
|
||||
|
||||
def test_retry(
|
||||
init_database,
|
||||
):
|
||||
|
||||
address = '0x' + os.urandom(20).hex()
|
||||
tx_hash = '0x' + os.urandom(32).hex()
|
||||
signed_tx = '0x' + os.urandom(128).hex()
|
||||
otx = Otx(0, address, tx_hash, signed_tx)
|
||||
init_database.add(otx)
|
||||
init_database.commit()
|
||||
|
||||
set_sent_status(tx_hash, True)
|
||||
set_ready(tx_hash)
|
||||
|
||||
q = init_database.query(Otx)
|
||||
q = q.filter(Otx.tx_hash==tx_hash)
|
||||
otx = q.first()
|
||||
|
||||
assert otx.status == StatusEnum.RETRY
|
||||
|
||||
set_sent_status(tx_hash, False)
|
||||
set_ready(tx_hash)
|
||||
|
||||
q = init_database.query(Otx)
|
||||
q = q.filter(Otx.tx_hash==tx_hash)
|
||||
otx = q.first()
|
||||
|
||||
assert otx.status == StatusEnum.RETRY
|
||||
|
||||
|
||||
def test_get_account_tx(
|
||||
default_chain_spec,
|
||||
init_database,
|
||||
init_w3,
|
||||
):
|
||||
|
||||
tx_hashes = []
|
||||
|
||||
for i in range(0, 4):
|
||||
|
||||
tx = {
|
||||
'from': init_w3.eth.accounts[int(i/3)],
|
||||
'to': init_w3.eth.accounts[3-i],
|
||||
'nonce': 42 + i,
|
||||
'gas': 21000,
|
||||
'gasPrice': 1000000*i,
|
||||
'value': 128,
|
||||
'chainId': 666,
|
||||
'data': '',
|
||||
}
|
||||
logg.debug('nonce {}'.format(tx['nonce']))
|
||||
tx_signed = init_w3.eth.sign_transaction(tx)
|
||||
tx_hash = init_w3.keccak(hexstr=tx_signed['raw'])
|
||||
queue_create(tx['nonce'], tx['from'], tx_hash.hex(), tx_signed['raw'], str(default_chain_spec))
|
||||
cache_gas_refill_data(tx_hash.hex(), tx)
|
||||
tx_hashes.append(tx_hash.hex())
|
||||
|
||||
txs = get_account_tx(init_w3.eth.accounts[0])
|
||||
logg.debug('tx {} tx {}'.format(list(txs.keys()), tx_hashes))
|
||||
assert list(txs.keys()) == tx_hashes
|
||||
|
||||
txs = get_account_tx(init_w3.eth.accounts[0], as_recipient=False)
|
||||
assert list(txs.keys()) == tx_hashes[:3]
|
||||
|
||||
txs = get_account_tx(init_w3.eth.accounts[0], as_sender=False)
|
||||
assert list(txs.keys()) == tx_hashes[3:]
|
||||
43
apps/cic-eth/tests/unit/sync/test_head.py
Normal file
43
apps/cic-eth/tests/unit/sync/test_head.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# local imports
|
||||
from cic_eth.sync.head import HeadSyncer
|
||||
from cic_eth.sync.backend import SyncerBackend
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def test_head(
|
||||
init_rpc,
|
||||
init_database,
|
||||
init_eth_tester,
|
||||
mocker,
|
||||
eth_empty_accounts,
|
||||
):
|
||||
|
||||
#backend = SyncBackend(eth_empty_accounts[0], 'foo')
|
||||
block_number = init_rpc.w3.eth.blockNumber
|
||||
backend = SyncerBackend.live('foo:666', block_number)
|
||||
syncer = HeadSyncer(backend)
|
||||
|
||||
#init_eth_tester.mine_block()
|
||||
nonce = init_rpc.w3.eth.getTransactionCount(init_rpc.w3.eth.accounts[0], 'pending')
|
||||
logg.debug('nonce {}'.format(nonce))
|
||||
tx = {
|
||||
'from': init_rpc.w3.eth.accounts[0],
|
||||
'to': eth_empty_accounts[0],
|
||||
'value': 404,
|
||||
'gas': 21000,
|
||||
'gasPrice': init_rpc.w3.eth.gasPrice,
|
||||
'nonce': nonce,
|
||||
}
|
||||
tx_hash_one = init_rpc.w3.eth.sendTransaction(tx)
|
||||
|
||||
block_number = init_rpc.w3.eth.blockNumber
|
||||
backend.set(block_number, 0)
|
||||
b = syncer.get(init_rpc.w3)
|
||||
|
||||
tx = init_rpc.w3.eth.getTransactionByBlock(b[0], 0)
|
||||
|
||||
assert tx.hash.hex() == tx_hash_one.hex()
|
||||
194
apps/cic-eth/tests/unit/sync/test_history.py
Normal file
194
apps/cic-eth/tests/unit/sync/test_history.py
Normal file
@@ -0,0 +1,194 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
from web3.exceptions import BlockNotFound
|
||||
from cic_registry import CICRegistry
|
||||
|
||||
# local imports
|
||||
from cic_eth.sync.history import HistorySyncer
|
||||
from cic_eth.sync.head import HeadSyncer
|
||||
#from cic_eth.sync import Syncer
|
||||
from cic_eth.db.models.otx import OtxSync
|
||||
from cic_eth.db.models.base import SessionBase
|
||||
from cic_eth.sync.backend import SyncerBackend
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
class FinishedError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class DebugFilter:
|
||||
|
||||
def __init__(self, address):
|
||||
self.txs = []
|
||||
self.monitor_to_address = address
|
||||
|
||||
def filter(self, w3, tx, rcpt, chain_spec):
|
||||
logg.debug('sync filter {}'.format(tx['hash'].hex()))
|
||||
if tx['to'] == self.monitor_to_address:
|
||||
self.txs.append(tx)
|
||||
# hack workaround, latest block hash not found in eth_tester for some reason
|
||||
if len(self.txs) == 2:
|
||||
raise FinishedError('intentionally finished on tx {}'.format(tx))
|
||||
|
||||
|
||||
def test_history(
|
||||
init_rpc,
|
||||
init_database,
|
||||
init_eth_tester,
|
||||
#celery_session_worker,
|
||||
eth_empty_accounts,
|
||||
):
|
||||
|
||||
nonce = init_rpc.w3.eth.getTransactionCount(init_rpc.w3.eth.accounts[0], 'pending')
|
||||
logg.debug('nonce {}'.format(nonce))
|
||||
tx = {
|
||||
'from': init_rpc.w3.eth.accounts[0],
|
||||
'to': eth_empty_accounts[0],
|
||||
'value': 404,
|
||||
'gas': 21000,
|
||||
'gasPrice': init_rpc.w3.eth.gasPrice,
|
||||
'nonce': nonce,
|
||||
}
|
||||
tx_hash_one = init_rpc.w3.eth.sendTransaction(tx)
|
||||
|
||||
nonce = init_rpc.w3.eth.getTransactionCount(init_rpc.w3.eth.accounts[0], 'pending')
|
||||
logg.debug('nonce {}'.format(nonce))
|
||||
tx = {
|
||||
'from': init_rpc.w3.eth.accounts[1],
|
||||
'to': eth_empty_accounts[0],
|
||||
'value': 404,
|
||||
'gas': 21000,
|
||||
'gasPrice': init_rpc.w3.eth.gasPrice,
|
||||
'nonce': nonce,
|
||||
}
|
||||
tx_hash_two = init_rpc.w3.eth.sendTransaction(tx)
|
||||
init_eth_tester.mine_block()
|
||||
|
||||
block_number = init_rpc.w3.eth.blockNumber
|
||||
|
||||
live_syncer = SyncerBackend.live('foo:666', 0)
|
||||
HeadSyncer(live_syncer)
|
||||
|
||||
history_syncers = SyncerBackend.resume('foo:666', block_number)
|
||||
|
||||
for history_syncer in history_syncers:
|
||||
logg.info('history syncer start {} target {}'.format(history_syncer.start(), history_syncer.target()))
|
||||
|
||||
backend = history_syncers[0]
|
||||
|
||||
syncer = HistorySyncer(backend)
|
||||
fltr = DebugFilter(eth_empty_accounts[0])
|
||||
syncer.filter.append(fltr.filter)
|
||||
|
||||
logg.debug('have txs {} {}'.format(tx_hash_one.hex(), tx_hash_two.hex()))
|
||||
|
||||
try:
|
||||
syncer.loop(0.1)
|
||||
except FinishedError:
|
||||
pass
|
||||
except BlockNotFound as e:
|
||||
logg.error('the last block given in loop does not seem to exist :/ {}'.format(e))
|
||||
|
||||
check_hashes = []
|
||||
for h in fltr.txs:
|
||||
check_hashes.append(h['hash'].hex())
|
||||
assert tx_hash_one.hex() in check_hashes
|
||||
assert tx_hash_two.hex() in check_hashes
|
||||
|
||||
|
||||
def test_history_multiple(
|
||||
init_rpc,
|
||||
init_database,
|
||||
init_eth_tester,
|
||||
#celery_session_worker,
|
||||
eth_empty_accounts,
|
||||
):
|
||||
|
||||
block_number = init_rpc.w3.eth.blockNumber
|
||||
live_syncer = SyncerBackend.live('foo:666', block_number)
|
||||
HeadSyncer(live_syncer)
|
||||
|
||||
nonce = init_rpc.w3.eth.getTransactionCount(init_rpc.w3.eth.accounts[0], 'pending')
|
||||
logg.debug('nonce {}'.format(nonce))
|
||||
tx = {
|
||||
'from': init_rpc.w3.eth.accounts[0],
|
||||
'to': eth_empty_accounts[0],
|
||||
'value': 404,
|
||||
'gas': 21000,
|
||||
'gasPrice': init_rpc.w3.eth.gasPrice,
|
||||
'nonce': nonce,
|
||||
}
|
||||
tx_hash_one = init_rpc.w3.eth.sendTransaction(tx)
|
||||
|
||||
|
||||
init_eth_tester.mine_block()
|
||||
block_number = init_rpc.w3.eth.blockNumber
|
||||
history_syncers = SyncerBackend.resume('foo:666', block_number)
|
||||
for history_syncer in history_syncers:
|
||||
logg.info('halfway history syncer start {} target {}'.format(history_syncer.start(), history_syncer.target()))
|
||||
live_syncer = SyncerBackend.live('foo:666', block_number)
|
||||
HeadSyncer(live_syncer)
|
||||
|
||||
nonce = init_rpc.w3.eth.getTransactionCount(init_rpc.w3.eth.accounts[0], 'pending')
|
||||
logg.debug('nonce {}'.format(nonce))
|
||||
tx = {
|
||||
'from': init_rpc.w3.eth.accounts[1],
|
||||
'to': eth_empty_accounts[0],
|
||||
'value': 404,
|
||||
'gas': 21000,
|
||||
'gasPrice': init_rpc.w3.eth.gasPrice,
|
||||
'nonce': nonce,
|
||||
}
|
||||
tx_hash_two = init_rpc.w3.eth.sendTransaction(tx)
|
||||
|
||||
init_eth_tester.mine_block()
|
||||
block_number = init_rpc.w3.eth.blockNumber
|
||||
history_syncers = SyncerBackend.resume('foo:666', block_number)
|
||||
live_syncer = SyncerBackend.live('foo:666', block_number)
|
||||
HeadSyncer(live_syncer)
|
||||
|
||||
for history_syncer in history_syncers:
|
||||
logg.info('history syncer start {} target {}'.format(history_syncer.start(), history_syncer.target()))
|
||||
|
||||
assert len(history_syncers) == 2
|
||||
|
||||
backend = history_syncers[0]
|
||||
syncer = HistorySyncer(backend)
|
||||
fltr = DebugFilter(eth_empty_accounts[0])
|
||||
syncer.filter.append(fltr.filter)
|
||||
try:
|
||||
syncer.loop(0.1)
|
||||
except FinishedError:
|
||||
pass
|
||||
except BlockNotFound as e:
|
||||
logg.error('the last block given in loop does not seem to exist :/ {}'.format(e))
|
||||
|
||||
check_hashes = []
|
||||
for h in fltr.txs:
|
||||
check_hashes.append(h['hash'].hex())
|
||||
assert tx_hash_one.hex() in check_hashes
|
||||
|
||||
|
||||
backend = history_syncers[1]
|
||||
syncer = HistorySyncer(backend)
|
||||
fltr = DebugFilter(eth_empty_accounts[0])
|
||||
syncer.filter.append(fltr.filter)
|
||||
try:
|
||||
syncer.loop(0.1)
|
||||
except FinishedError:
|
||||
pass
|
||||
except BlockNotFound as e:
|
||||
logg.error('the last block given in loop does not seem to exist :/ {}'.format(e))
|
||||
|
||||
check_hashes = []
|
||||
for h in fltr.txs:
|
||||
check_hashes.append(h['hash'].hex())
|
||||
assert tx_hash_two.hex() in check_hashes
|
||||
|
||||
history_syncers = SyncerBackend.resume('foo:666', block_number)
|
||||
|
||||
assert len(history_syncers) == 0
|
||||
79
apps/cic-eth/tests/unit/sync/test_syncer_scratch.py
Normal file
79
apps/cic-eth/tests/unit/sync/test_syncer_scratch.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# third-party imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.models.sync import BlockchainSync
|
||||
from cic_eth.sync.backend import SyncerBackend
|
||||
|
||||
|
||||
def test_scratch(
|
||||
init_database,
|
||||
):
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
s = SyncerBackend('Testchain:666', 13)
|
||||
|
||||
syncer = SyncerBackend.live('Testchain:666', 13)
|
||||
|
||||
s = SyncerBackend('Testchain:666', syncer.object_id)
|
||||
|
||||
|
||||
|
||||
def test_live(
|
||||
init_database,
|
||||
):
|
||||
|
||||
s = SyncerBackend.live('Testchain:666', 13)
|
||||
|
||||
s.connect()
|
||||
assert s.db_object.target() == None
|
||||
s.disconnect()
|
||||
|
||||
assert s.get() == (13, 0)
|
||||
|
||||
s.set(14, 1)
|
||||
assert s.get() == (14, 1)
|
||||
|
||||
|
||||
def test_resume(
|
||||
init_database,
|
||||
):
|
||||
|
||||
live = SyncerBackend.live('Testchain:666', 13)
|
||||
live.set(13, 2)
|
||||
|
||||
resumes = SyncerBackend.resume('Testchain:666', 26)
|
||||
|
||||
assert len(resumes) == 1
|
||||
resume = resumes[0]
|
||||
|
||||
assert resume.get() == (13, 2)
|
||||
|
||||
resume.set(13, 4)
|
||||
assert resume.get() == (13, 4)
|
||||
assert resume.start() == (13, 2)
|
||||
assert resume.target() == 26
|
||||
|
||||
|
||||
def test_unsynced(
|
||||
init_database,
|
||||
):
|
||||
|
||||
live = SyncerBackend.live('Testchain:666', 13)
|
||||
live.set(13, 2)
|
||||
|
||||
resumes = SyncerBackend.resume('Testchain:666', 26)
|
||||
live = SyncerBackend.live('Testchain:666', 26)
|
||||
resumes[0].set(18, 12)
|
||||
|
||||
resumes = SyncerBackend.resume('Testchain:666', 42)
|
||||
|
||||
assert len(resumes) == 2
|
||||
|
||||
assert resumes[0].start() == (13, 2)
|
||||
assert resumes[0].get() == (18, 12)
|
||||
assert resumes[0].target() == 26
|
||||
|
||||
assert resumes[1].start() == (26, 0)
|
||||
assert resumes[1].get() == (26, 0)
|
||||
assert resumes[1].target() == 42
|
||||
19
apps/cic-eth/tests/unit/util/test_num.py
Normal file
19
apps/cic-eth/tests/unit/util/test_num.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# third-party imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_eth.db.util import num_serialize
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'n,b',
|
||||
[
|
||||
(0, b'\x00'),
|
||||
(1, b'\x01'),
|
||||
(255, b'\xff'),
|
||||
(256, b'\x01\x00'),
|
||||
(18446744073709551616, b'\x01\x00\x00\x00\x00\x00\x00\x00\x00'),
|
||||
],
|
||||
)
|
||||
def test_num_serialize(n, b):
|
||||
assert(num_serialize(n) == b)
|
||||
30
apps/cic-eth/tests/unit/util/test_unpack.py
Normal file
30
apps/cic-eth/tests/unit/util/test_unpack.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from cic_eth.eth.task import sign_tx
|
||||
from cic_eth.eth.util import tx_hex_string
|
||||
from cic_eth.eth.util import unpack_signed_raw_tx_hex
|
||||
|
||||
def test_unpack(
|
||||
init_w3_conn,
|
||||
):
|
||||
|
||||
tx = {
|
||||
'nonce': 42,
|
||||
'from': init_w3_conn.eth.accounts[0],
|
||||
'to': init_w3_conn.eth.accounts[1],
|
||||
'data': '0xdeadbeef',
|
||||
'value': 1024,
|
||||
'gas': 23000,
|
||||
'gasPrice': 1422521,
|
||||
'chainId': 1337,
|
||||
}
|
||||
|
||||
(tx_hash, tx_signed) = sign_tx(tx, 'Foo:1337')
|
||||
|
||||
tx_unpacked = unpack_signed_raw_tx_hex(tx_signed, 1337)
|
||||
|
||||
for k in tx.keys():
|
||||
assert tx[k] == tx_unpacked[k]
|
||||
|
||||
tx_str = tx_hex_string(tx_signed, 1337)
|
||||
assert tx_str == 'tx nonce 42 from 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf to 0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF hash 0xe5aba32b1a7255d035faccb70cd8bb92c8c4a2f6bbea3f655bc5a8b802bbaa91'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user