Skip to content
This repository has been archived by the owner on Jun 13, 2019. It is now read-only.

Commit

Permalink
db interface & MemoryDb impl
Browse files Browse the repository at this point in the history
  • Loading branch information
boolafish committed May 18, 2018
1 parent d728ed8 commit e314ad9
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 23 deletions.
14 changes: 8 additions & 6 deletions plasma_cash/child_chain/child_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

class ChildChain(object):

def __init__(self, authority, root_chain):
def __init__(self, authority, root_chain, db):
self.root_chain = root_chain
self.authority = authority
self.blocks = {}
self.db = db
self.current_block = Block()
self.current_block_number = 1

Expand All @@ -43,7 +43,7 @@ def submit_block(self, sig):
{'from': '0x' + self.authority.hex()}
).submitBlock(merkle_hash, self.current_block_number)

self.blocks[self.current_block_number] = self.current_block
self.db.save_block(self.current_block, self.current_block_number)
self.current_block_number += 1
self.current_block = Block()

Expand All @@ -52,7 +52,7 @@ def submit_block(self, sig):
def apply_transaction(self, transaction):
tx = rlp.decode(utils.decode_hex(transaction), Transaction)

prev_tx = self.blocks[tx.prev_block].get_tx_by_uid(tx.uid)
prev_tx = self.db.get_block(tx.prev_block).get_tx_by_uid(tx.uid)
if prev_tx is None:
raise PreviousTxNotFoundException('failed to apply transaction')
if prev_tx.spent:
Expand All @@ -70,7 +70,9 @@ def get_current_block(self):
return rlp.encode(self.current_block).hex()

def get_block(self, blknum):
return rlp.encode(self.blocks[blknum]).hex()
block = self.db.get_block(blknum)
return rlp.encode(block).hex()

def get_proof(self, blknum, uid):
return self.blocks[blknum].merkle.create_merkle_proof(uid)
block = self.db.get_block(blknum)
return block.merkle.create_merkle_proof(uid)
8 changes: 7 additions & 1 deletion plasma_cash/dependency_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from plasma_cash.client.client import Client
from plasma_cash.config import plasma_config
from plasma_cash.root_chain.deployer import Deployer
from plasma_cash.utils.db.memory_db import MemoryDb


class DependencyContainer(object):
Expand All @@ -12,6 +13,10 @@ def __init__(self):
self._child_chain_client = None
self._client = None

def get_db(self):
# TODO: enable real_db type & memory_db chosen by config
return MemoryDb()

def get_root_chain(self):
if self._root_chain is None:
self._root_chain = Deployer().get_contract('RootChain/RootChain.sol')
Expand All @@ -21,7 +26,8 @@ def get_child_chain(self):
if self._child_chain is None:
authority = plasma_config['AUTHORITY']
root_chain = self.get_root_chain()
self._child_chain = ChildChain(authority, root_chain)
db = self.get_db()
self._child_chain = ChildChain(authority, root_chain, db)
return self._child_chain

def get_child_chain_client(self):
Expand Down
Empty file.
12 changes: 12 additions & 0 deletions plasma_cash/utils/db/db_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import abc


class DbInterface(abc.ABC):

@abc.abstractmethod
def get_block(self, block_number):
return NotImplemented

@abc.abstractmethod
def save_block(self, block, block_number):
return NotImplemented
2 changes: 2 additions & 0 deletions plasma_cash/utils/db/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class BlockAlreadyExistsException(Exception):
"""block already exists"""
16 changes: 16 additions & 0 deletions plasma_cash/utils/db/memory_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from .db_interface import DbInterface
from .exceptions import BlockAlreadyExistsException


class MemoryDb(DbInterface):

def __init__(self):
self.blocks = {}

def get_block(self, block_number):
return self.blocks.get(block_number)

def save_block(self, block, block_number):
if block_number in self.blocks:
raise BlockAlreadyExistsException('should not save block with same id again.')
self.blocks[block_number] = block
39 changes: 23 additions & 16 deletions unit_tests/child_chain/test_child_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,46 @@
TxAlreadySpentException,
TxAmountMismatchException)
from plasma_cash.child_chain.transaction import Transaction
from plasma_cash.utils.db.memory_db import MemoryDb
from unit_tests.unstub_mixin import UnstubMixin


class TestChildChain(UnstubMixin):
DUMMY_AUTHORITY = b"\x14\x7f\x08\x1b\x1a6\xa8\r\xf0Y\x15(ND'\xc1\xf6\xdd\x98\x84"
DUMMY_SIG = '01' * 65 # sig for DUMMY_AUTHORITY
DUMMY_TX_NEW_OWNER = b'\xfd\x02\xec\xeeby~u\xd8k\xcf\xf1d.\xb0\x84J\xfb(\xc7'
ROOT_CHAIN = mock()

@pytest.fixture(scope='function')
def child_chain(self):
def db(self):
return MemoryDb()

@pytest.fixture(scope='function')
def root_chain(self):
return mock()

@pytest.fixture(scope='function')
def child_chain(self, root_chain, db):
DUMMY_TX_OWNER = b'\x8cT\xa4\xa0\x17\x9f$\x80\x1fI\xf92-\xab<\x87\xeb\x19L\x9b'

deposit_filter = mock()
when(self.ROOT_CHAIN).on('Deposit').thenReturn(deposit_filter)
child_chain = ChildChain(authority=self.DUMMY_AUTHORITY,
root_chain=self.ROOT_CHAIN)
when(root_chain).on('Deposit').thenReturn(deposit_filter)
child_chain = ChildChain(self.DUMMY_AUTHORITY, root_chain, db)

# create a dummy transaction
tx = Transaction(prev_block=0, uid=1, amount=10, new_owner=DUMMY_TX_OWNER)

# create a block with the dummy transaction
child_chain.blocks[1] = Block([tx])
db.save_block(Block([tx]), 1)
child_chain.current_block_number = 2
return child_chain

def test_constructor(self):
def test_constructor(self, root_chain, db):
deposit_filter = mock()
when(self.ROOT_CHAIN).on('Deposit').thenReturn(deposit_filter)
when(root_chain).on('Deposit').thenReturn(deposit_filter)

ChildChain(authority=self.DUMMY_AUTHORITY, root_chain=self.ROOT_CHAIN)
ChildChain(self.DUMMY_AUTHORITY, root_chain, db)

verify(self.ROOT_CHAIN).on('Deposit')
verify(root_chain).on('Deposit')
verify(deposit_filter).watch(any)

def test_apply_deposit(self, child_chain):
Expand All @@ -64,20 +71,20 @@ def test_apply_deposit(self, child_chain):
assert tx.uid == DUMMY_UID
assert tx.new_owner == eth_utils.normalize_address(DUMMY_ADDR)

def test_submit_block(self, child_chain):
def test_submit_block(self, child_chain, root_chain):
DUMMY_MERKLE = 'merkle hash'
MOCK_TRANSACT = mock()

block_number = child_chain.current_block_number
block = child_chain.current_block
when(child_chain.current_block).merklize_transaction_set().thenReturn(DUMMY_MERKLE)
when(self.ROOT_CHAIN).transact(any).thenReturn(MOCK_TRANSACT)
when(root_chain).transact(any).thenReturn(MOCK_TRANSACT)

child_chain.submit_block(self.DUMMY_SIG)

verify(MOCK_TRANSACT).submitBlock(DUMMY_MERKLE, block_number)
assert child_chain.current_block_number == block_number + 1
assert child_chain.blocks[block_number] == block
assert child_chain.db.get_block(block_number) == block
assert child_chain.current_block == Block()

def test_submit_block_with_invalid_sig(self, child_chain):
Expand All @@ -98,7 +105,7 @@ def test_apply_transaction(self, child_chain):

child_chain.apply_transaction(rlp.encode(tx).hex())

prev_tx = child_chain.blocks[1].transaction_set[0]
prev_tx = child_chain.db.get_block(1).transaction_set[0]
assert child_chain.current_block.transaction_set[0] == tx
assert prev_tx.new_owner == tx.sender
assert prev_tx.amount == tx.amount
Expand Down Expand Up @@ -152,14 +159,14 @@ def test_get_current_block(self, child_chain):
def test_get_block(self, child_chain):
DUMMY_BLK_NUM = 1

expected = rlp.encode(child_chain.blocks[DUMMY_BLK_NUM]).hex()
expected = rlp.encode(child_chain.db.get_block(DUMMY_BLK_NUM)).hex()
assert expected == child_chain.get_block(DUMMY_BLK_NUM)

def test_get_proof(self, child_chain):
DUMMY_BLK_NUM = 1
DUMMY_UID = 1

block = child_chain.blocks[DUMMY_BLK_NUM]
block = child_chain.db.get_block(DUMMY_BLK_NUM)
block.merklize_transaction_set()
expected_proof = block.merkle.create_merkle_proof(DUMMY_UID)
assert expected_proof == child_chain.get_proof(DUMMY_BLK_NUM, DUMMY_UID)
Empty file added unit_tests/utils/db/__init__.py
Empty file.
26 changes: 26 additions & 0 deletions unit_tests/utils/db/test_memory_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import pytest

from plasma_cash.utils.db.exceptions import BlockAlreadyExistsException
from plasma_cash.utils.db.memory_db import MemoryDb


class TestMemoryDb(object):
@pytest.fixture(scope='function')
def db(self):
return MemoryDb()

def test_block_normal_case(self, db):
DUMMY_BLOCK = 'dummy block'
DUMMY_BLK_NUM = 1
db.save_block(DUMMY_BLOCK, DUMMY_BLK_NUM)
assert db.get_block(DUMMY_BLK_NUM) == DUMMY_BLOCK

def test_get_block_none(self, db):
NON_EXIST_BLK_NUM = -1
assert db.get_block(NON_EXIST_BLK_NUM) is None

def test_save_block_already_exists(self, db):
DUMMY_BLK_NUM = 1
db.save_block('first block', DUMMY_BLK_NUM)
with pytest.raises(BlockAlreadyExistsException):
db.save_block('second block should fail', DUMMY_BLK_NUM)

0 comments on commit e314ad9

Please sign in to comment.