diff --git a/nucypher/blockchain/eth/aragon.py b/nucypher/blockchain/eth/aragon.py new file mode 100644 index 000000000..ede19407a --- /dev/null +++ b/nucypher/blockchain/eth/aragon.py @@ -0,0 +1,38 @@ +""" + This file is part of nucypher. + + nucypher is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + nucypher is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with nucypher. If not, see . +""" +from typing import Iterable, Tuple + +from eth_utils import to_canonical_address +from web3 import Web3 + + +class CallScriptCodec: + + CALLSCRIPT_ID = Web3.toBytes(hexstr='0x00000001') + + @classmethod + def encode(cls, actions: Iterable[Tuple[str, bytes]]): + callscript = [cls.CALLSCRIPT_ID] + + for target, action_data in actions: + encoded_action = (to_canonical_address(target), + len(action_data).to_bytes(4, 'big'), + action_data) + callscript.extend(encoded_action) + + callscript_data = b''.join(callscript) + return callscript_data diff --git a/tests/unit/test_aragon.py b/tests/unit/test_aragon.py new file mode 100644 index 000000000..11f2377b7 --- /dev/null +++ b/tests/unit/test_aragon.py @@ -0,0 +1,49 @@ +""" + This file is part of nucypher. + + nucypher is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + nucypher is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with nucypher. If not, see . +""" + +import os + +import pytest +from eth_utils import to_canonical_address + +from nucypher.blockchain.eth.aragon import CallScriptCodec + + +def test_callscriptcodec(): + assert CallScriptCodec.CALLSCRIPT_ID == bytes.fromhex("00000001") + + +def test_callscript_encoding_empty(): + actions = tuple() + + callscript_data = CallScriptCodec.encode(actions) + expected_callscript = CallScriptCodec.CALLSCRIPT_ID + assert expected_callscript == callscript_data + + +@pytest.mark.parametrize('data_length', range(0, 100, 5)) +def test_callscript_encoding_one_action(get_random_checksum_address, data_length): + target = get_random_checksum_address() + data = os.urandom(data_length) + actions = [(target, data)] + + callscript_data = CallScriptCodec.encode(actions) + expected_callscript = b''.join((CallScriptCodec.CALLSCRIPT_ID, + to_canonical_address(target), + data_length.to_bytes(4, 'big'), + data)) + assert expected_callscript == callscript_data