Skip to content

Commit 9ef70a4

Browse files
committed
Remove unnecessary Safe call on serializer
- Ensure that 1271 works from 1_1_1.
1 parent f84fde4 commit 9ef70a4

File tree

7 files changed

+81
-76
lines changed

7 files changed

+81
-76
lines changed

safe_transaction_service/account_abstraction/tests/test_helpers.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
from django.test import TestCase
22

33
from hexbytes import HexBytes
4-
from safe_eth.eth.tests.mocks.mock_bundler import (
5-
user_operation_mock,
6-
)
4+
from safe_eth.eth.tests.mocks.mock_bundler import user_operation_mock
75
from safe_eth.safe.tests.safe_test_case import SafeTestCaseMixin
86

97
from ..helpers import DecodedInitCode, decode_init_code
108

119

1210
class TestAccountAbstractionHelpers(SafeTestCaseMixin, TestCase):
13-
def test_decode_init_code_v141(self):
11+
def test_decode_init_code(self):
1412
with self.assertRaises(ValueError):
1513
decode_init_code(b"", self.ethereum_client)
1614

safe_transaction_service/history/serializers.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@
3434
TxDecoderException,
3535
get_db_tx_decoder,
3636
)
37-
from safe_transaction_service.safe_messages.utils import (
38-
select_safe_encoded_message_hash_by_safe_version,
39-
)
4037
from safe_transaction_service.tokens.serializers import TokenInfoResponseSerializer
4138
from safe_transaction_service.utils.serializers import (
4239
EpochDateTimeField,
@@ -122,11 +119,8 @@ def validate_signature(self, signature: bytes):
122119
)
123120

124121
safe_owners = get_safe_owners(safe_address)
125-
safe_hash_preimage = select_safe_encoded_message_hash_by_safe_version(
126-
safe.get_version(), safe_tx.safe_tx_hash, safe_tx.safe_tx_hash_preimage
127-
)
128122
parsed_signatures = SafeSignature.parse_signature(
129-
signature, safe_tx_hash, safe_hash_preimage=safe_hash_preimage
123+
signature, safe_tx_hash, safe_hash_preimage=safe_tx.safe_tx_hash_preimage
130124
)
131125
signature_owners = []
132126
ethereum_client = get_auto_ethereum_client()
@@ -272,13 +266,11 @@ def validate(self, attrs):
272266
signature_owners = []
273267
# TODO Make signature mandatory
274268
signature = attrs.get("signature", b"")
275-
# For v1.5.0+, the isValidSignature(bytes32,bytes) expects the original message_hash (bytes32),
276-
safe_signature_hash = select_safe_encoded_message_hash_by_safe_version(
277-
safe.get_version(), safe_tx.safe_tx_hash, safe_tx.safe_tx_hash_preimage
278-
)
269+
279270
parsed_signatures = SafeSignature.parse_signature(
280-
signature, safe_tx_hash, safe_hash_preimage=safe_signature_hash
271+
signature, safe_tx_hash, safe_hash_preimage=safe_tx.safe_tx_hash_preimage
281272
)
273+
282274
attrs["parsed_signatures"] = parsed_signatures
283275
# If there's at least one signature, transaction is trusted (until signatures are mandatory)
284276
attrs["trusted"] = bool(parsed_signatures)

safe_transaction_service/history/tests/test_views.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from eth_account import Account
1515
from factory.fuzzy import FuzzyText
1616
from hexbytes import HexBytes
17+
from packaging.version import Version
1718
from requests import ReadTimeout
1819
from rest_framework import status
1920
from rest_framework.exceptions import ErrorDetail
@@ -31,9 +32,6 @@
3132
from safe_transaction_service.contracts.models import ContractQuerySet
3233
from safe_transaction_service.contracts.tests.factories import ContractFactory
3334
from safe_transaction_service.contracts.tx_decoder import DbTxDecoder
34-
from safe_transaction_service.safe_messages.utils import (
35-
select_safe_encoded_message_hash_by_safe_version,
36-
)
3735
from safe_transaction_service.tokens.models import Token
3836
from safe_transaction_service.tokens.tests.factories import TokenFactory
3937
from safe_transaction_service.utils.utils import datetime_to_str
@@ -1773,12 +1771,14 @@ def test_post_multisig_transaction_with_1271_signature(self):
17731771
)
17741772
safe_tx_hash = safe_tx.safe_tx_hash
17751773
safe_tx_hash_preimage = safe_tx.safe_tx_hash_preimage
1776-
1777-
selected_hash = select_safe_encoded_message_hash_by_safe_version(
1778-
safe.get_version(), safe_tx_hash, safe_tx_hash_preimage
1774+
# >= v1.3.0: supports isValidSignature(bytes32, bytes) and isValidSignature(bytes, bytes)
1775+
# < v1.3.0: only isValidSignature(bytes, bytes) with the preimage
1776+
# < v1.5.0: test isValidSignature(bytes, bytes) for backward compatibility
1777+
safe_owner_message_hash = safe_owner.get_message_hash(
1778+
safe_tx_hash
1779+
if Version(safe.get_version()) >= Version("1.5.0")
1780+
else safe_tx_hash_preimage
17791781
)
1780-
1781-
safe_owner_message_hash = safe_owner.get_message_hash(selected_hash)
17821782
safe_owner_signature = account.unsafe_sign_hash(safe_owner_message_hash)[
17831783
"signature"
17841784
]
@@ -5013,7 +5013,7 @@ def test_export_view_standalone_transfer_priority(self):
50135013

50145014
class TestViewsV141(TestViewsV150):
50155015
"""
5016-
Test views v2 with Safe v1.4.1 contracts.
5016+
Test views with Safe v1.4.1 contracts.
50175017
"""
50185018

50195019
def deploy_test_safe(self, *args, **kwargs) -> Safe:
@@ -5023,3 +5023,31 @@ def deploy_test_safe(self, *args, **kwargs) -> Safe:
50235023
:return: Deploy last available Safe
50245024
"""
50255025
return self.deploy_test_safe_v1_4_1(*args, **kwargs)
5026+
5027+
5028+
class TestViewsV130(TestViewsV150):
5029+
"""
5030+
Test views with Safe v1.3.0 contracts.
5031+
"""
5032+
5033+
def deploy_test_safe(self, *args, **kwargs) -> Safe:
5034+
"""
5035+
:param args:
5036+
:param kwargs:
5037+
:return: Deploy last available Safe
5038+
"""
5039+
return self.deploy_test_safe_v1_3_0(*args, **kwargs)
5040+
5041+
5042+
class TestViewsV111(TestViewsV150):
5043+
"""
5044+
Test views with Safe v1.1.1 contracts.
5045+
"""
5046+
5047+
def deploy_test_safe(self, *args, **kwargs) -> Safe:
5048+
"""
5049+
:param args:
5050+
:param kwargs:
5051+
:return: Deploy last available Safe
5052+
"""
5053+
return self.deploy_test_safe_v1_1_1(*args, **kwargs)

safe_transaction_service/history/tests/test_views_v2.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import eth_abi
1212
from eth_account import Account
1313
from hexbytes import HexBytes
14+
from packaging.version import Version
1415
from rest_framework import status
1516
from rest_framework.exceptions import ErrorDetail
1617
from rest_framework.test import APIRequestFactory, APITestCase, force_authenticate
@@ -26,9 +27,6 @@
2627
from ...contracts.models import ContractQuerySet
2728
from ...contracts.tests.factories import ContractFactory
2829
from ...contracts.tx_decoder import DbTxDecoder
29-
from ...safe_messages.utils import (
30-
select_safe_encoded_message_hash_by_safe_version,
31-
)
3230
from ...tokens.models import Token
3331
from ...tokens.tests.factories import TokenFactory
3432
from ...utils.utils import datetime_to_str
@@ -1535,11 +1533,14 @@ def test_post_multisig_transaction_with_1271_signature(self):
15351533
safe_tx_hash = safe_tx.safe_tx_hash
15361534
safe_tx_hash_preimage = safe_tx.safe_tx_hash_preimage
15371535

1538-
selected_hash = select_safe_encoded_message_hash_by_safe_version(
1539-
safe.get_version(), safe_tx_hash, safe_tx_hash_preimage
1536+
# >= v1.3.0: supports isValidSignature(bytes32, bytes) and isValidSignature(bytes, bytes)
1537+
# < v1.3.0: only isValidSignature(bytes, bytes) with the preimage
1538+
# < v1.5.0: test isValidSignature(bytes, bytes) for backward compatibility
1539+
safe_owner_message_hash = safe_owner.get_message_hash(
1540+
safe_tx_hash
1541+
if Version(safe.get_version()) >= Version("1.5.0")
1542+
else safe_tx_hash_preimage
15401543
)
1541-
1542-
safe_owner_message_hash = safe_owner.get_message_hash(selected_hash)
15431544
safe_owner_signature = account.unsafe_sign_hash(safe_owner_message_hash)[
15441545
"signature"
15451546
]
@@ -2822,3 +2823,17 @@ def deploy_test_safe(self, *args, **kwargs) -> Safe:
28222823
:return: Deploy last available Safe
28232824
"""
28242825
return self.deploy_test_safe_v1_4_1(*args, **kwargs)
2826+
2827+
2828+
class TestViewsV2V130(TestViewsV2V150):
2829+
"""
2830+
Test views v2 with Safe v1.3.0 contracts.
2831+
"""
2832+
2833+
def deploy_test_safe(self, *args, **kwargs) -> Safe:
2834+
"""
2835+
:param args:
2836+
:param kwargs:
2837+
:return: Deploy last available Safe
2838+
"""
2839+
return self.deploy_test_safe_v1_3_0(*args, **kwargs)

safe_transaction_service/safe_messages/serializers.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from safe_eth.eth import get_auto_ethereum_client
1313
from safe_eth.eth.eip712 import eip712_encode
1414
from safe_eth.eth.utils import fast_keccak
15-
from safe_eth.safe.safe import Safe
1615
from safe_eth.safe.safe_signature import SafeSignature, SafeSignatureType
1716
from safe_eth.util.util import to_0x_hex_str
1817

@@ -21,11 +20,7 @@
2120
)
2221

2322
from .models import SIGNATURE_LENGTH, SafeMessage, SafeMessageConfirmation
24-
from .utils import (
25-
get_message_encoded,
26-
get_safe_message_hash_and_preimage_for_message,
27-
select_safe_encoded_message_hash_by_safe_version,
28-
)
23+
from .utils import get_message_encoded, get_safe_message_hash_and_preimage_for_message
2924

3025

3126
# Request serializers
@@ -130,19 +125,10 @@ def validate(self, attrs):
130125
f"Message with hash {to_0x_hex_str(safe_message_hash)} for safe {safe_address} already exists in DB"
131126
)
132127

133-
# Preimage is encoded for the Safe. But if an EIP-1271 signature is used, owner's Safe will be called
134-
# the preimage will be encoded again for the owner Safe. That's what needs to be signed by the user
135-
# So original data -> EIP-191 or EIP-712 encoded -> Safe encoded data -> Owner encoded data
136-
# For v1.5.0+, the isValidSignature(bytes32,bytes) expects the original message_hash (bytes32),
137-
# not the Safe-encoded hash
138-
ethereum_client = get_auto_ethereum_client()
139-
safe = Safe(safe_address, ethereum_client)
140-
safe_message_preimage = select_safe_encoded_message_hash_by_safe_version(
141-
safe.get_version(), safe_message_hash, safe_message_preimage
142-
)
143128
safe_signatures = SafeSignature.parse_signature(
144129
signature, safe_message_hash, safe_hash_preimage=safe_message_preimage
145130
)
131+
146132
owner, signature_type = self.get_valid_owner_from_signatures(
147133
safe_signatures, safe_address, None
148134
)
@@ -185,10 +171,6 @@ def validate(self, attrs):
185171
)
186172
assert to_0x_hex_str(safe_message_hash) == safe_message.message_hash
187173

188-
safe = Safe(safe_address, get_auto_ethereum_client())
189-
safe_message_preimage = select_safe_encoded_message_hash_by_safe_version(
190-
safe.get_version(), safe_message_hash, safe_message_preimage
191-
)
192174
safe_signatures = SafeSignature.parse_signature(
193175
signature, safe_message_hash, safe_hash_preimage=safe_message_preimage
194176
)

safe_transaction_service/safe_messages/tests/test_views.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import eth_abi
99
from eth_account import Account
1010
from hexbytes import HexBytes
11+
from packaging.version import Version
1112
from rest_framework import status
1213
from rest_framework.exceptions import ErrorDetail
1314
from rest_framework.test import APITestCase
@@ -28,11 +29,7 @@
2829
)
2930
from safe_transaction_service.utils.utils import datetime_to_str
3031

31-
from ..utils import (
32-
encode_eip191_message,
33-
encode_eip712_message,
34-
select_safe_encoded_message_hash_by_safe_version,
35-
)
32+
from ..utils import encode_eip191_message, encode_eip712_message
3633
from .mocks import get_eip712_payload_mock
3734

3835
logger = logging.getLogger(__name__)
@@ -299,11 +296,15 @@ def _test_safe_messages_create_using_1271_signature_view(self, safe_deployment_f
299296
fast_keccak(message_encoded)
300297
)
301298

302-
data = select_safe_encoded_message_hash_by_safe_version(
303-
safe.get_version(), safe_message_hash, safe_message_preimage
299+
# >= v1.3.0: supports isValidSignature(bytes32, bytes) and isValidSignature(bytes, bytes)
300+
# < v1.3.0: only isValidSignature(bytes, bytes) with the preimage
301+
# < v1.5.0: test isValidSignature(bytes, bytes) for backward compatibility
302+
safe_owner_message_hash = safe_owner.get_message_hash(
303+
safe_message_hash
304+
if Version(safe.get_version()) >= Version("1.5.0")
305+
else safe_message_preimage
304306
)
305307

306-
safe_owner_message_hash, _ = safe_owner.get_message_hash_and_preimage(data)
307308
safe_owner_signature = account.unsafe_sign_hash(safe_owner_message_hash)[
308309
"signature"
309310
]
@@ -334,6 +335,11 @@ def _test_safe_messages_create_using_1271_signature_view(self, safe_deployment_f
334335
SafeMessageConfirmation.objects.get().owner, safe_owner.address
335336
)
336337

338+
def test_safe_messages_create_using_1271_signature_v1_1_1_view(self):
339+
return self._test_safe_messages_create_using_1271_signature_view(
340+
self.deploy_test_safe_v1_1_1
341+
)
342+
337343
def test_safe_messages_create_using_1271_signature_v1_3_0_view(self):
338344
return self._test_safe_messages_create_using_1271_signature_view(
339345
self.deploy_test_safe_v1_3_0

safe_transaction_service/safe_messages/utils.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from eth_account.messages import encode_defunct
44
from eth_typing import ChecksumAddress, Hash32
5-
from packaging.version import Version
65
from safe_eth.eth import get_auto_ethereum_client
76
from safe_eth.eth.eip712 import eip712_encode
87
from safe_eth.safe import Safe
@@ -35,18 +34,3 @@ def get_safe_message_hash_and_preimage_for_message(
3534
) -> tuple[Hash32, bytes]:
3635
safe = Safe(safe_address, get_auto_ethereum_client())
3736
return safe.get_message_hash_and_preimage(message)
38-
39-
40-
def select_safe_encoded_message_hash_by_safe_version(
41-
safe_version: str, safe_message_hash: bytes, safe_message_preimage: bytes
42-
) -> bytes:
43-
"""
44-
Returns the Safe-encoded message hash for v1.5.0+ Safes, otherwise returns the provided preimage.
45-
46-
:param safe_version: Version of the Safe contract.
47-
:param safe_message_preimage: Safe-encoded message hash.
48-
:return: Hash to be used for signature validation.
49-
"""
50-
if Version(safe_version) >= Version("1.5.0"):
51-
return safe_message_hash
52-
return safe_message_preimage

0 commit comments

Comments
 (0)