Skip to content

Commit b8b8c64

Browse files
authored
feat: bind validator PoP to chainId and registrantAddress (#186)
1 parent f598a4b commit b8b8c64

13 files changed

Lines changed: 178 additions & 41 deletions

‎crypto/exceptions.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@ class ArkInvalidTransaction(ArkCryptoException):
1212

1313
class InvalidUsernameException(Exception):
1414
"""Raised when username is invalid"""
15+
16+
17+
class InvalidProofOfPossessionException(ArkCryptoException):
18+
"""Raised when a proof of possession can't be built from the given input"""

‎crypto/identity/proof_of_possession.py‎

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44

55
sys.path.append(os.path.join(dirname(dirname(__file__)), 'thirdparty/bls-signatures/python-impl'))
66

7-
from schemes import PopSchemeMPL, PrivateKey as BLSSchemePrivateKey
7+
from schemes import PrivateKey as BLSSchemePrivateKey, core_sign_mpl
88

9+
from crypto.configuration.network import Network
10+
from crypto.exceptions import InvalidProofOfPossessionException
11+
from crypto.identity.address import Address
912
from crypto.identity.bls_private_key import BLSPrivateKey
1013

14+
POP_DST = b'MAINSAIL_BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_'
15+
1116

1217
class ProofOfPossession:
1318
@staticmethod
@@ -21,33 +26,63 @@ def derive_bls_public_key(cls, passphrase: str) -> str:
2126
sk = BLSSchemePrivateKey.from_bytes(cls.derive_bls_private_key(passphrase))
2227
return bytes(sk.get_g1()).hex()
2328

29+
@staticmethod
30+
def build_message(chain_id: int, registrant_address: str, public_key: bytes) -> bytes:
31+
"""abi.encodePacked(uint256 chainId, address registrantAddress, bytes blsPublicKey)"""
32+
return chain_id.to_bytes(32, 'big') + bytes.fromhex(registrant_address[2:]) + public_key
33+
34+
@staticmethod
35+
def validate_registrant_address(registrant_address: str) -> None:
36+
if not isinstance(registrant_address, str) or not Address.validate(registrant_address):
37+
raise InvalidProofOfPossessionException(
38+
f'Invalid registrant address: {registrant_address}'
39+
)
40+
41+
hex_part = registrant_address[2:]
42+
is_single_case = hex_part == hex_part.lower() or hex_part == hex_part.upper()
43+
44+
checksum_address = Address.get_checksum_address(registrant_address)
45+
46+
if not is_single_case and checksum_address != registrant_address:
47+
raise InvalidProofOfPossessionException(
48+
f'Invalid registrant address checksum: {registrant_address}'
49+
)
50+
2451
@classmethod
25-
def build_proof_of_possession(cls, private_key_bytes: bytes) -> dict:
26-
"""Builds proof of possession for a given private key.
52+
def build_proof_of_possession(cls, private_key_bytes: bytes, registrant_address: str) -> dict:
53+
"""Builds a proof of possession bound to the registrant address and the configured
54+
network chain ID.
2755
2856
Args:
2957
private_key_bytes: 32-byte BLS private key
58+
registrant_address: address submitting the registration or update
3059
3160
Returns:
3261
dict with 'pk' (hex, 48 bytes G1) and 'pop' (hex, 96 bytes G2)
3362
3463
Raises:
3564
ValueError: if the key is not exactly 32 bytes or is the zero scalar
65+
InvalidProofOfPossessionException: if the registrant address is invalid
3666
"""
3767
if int.from_bytes(private_key_bytes, 'big') == 0:
3868
raise ValueError('BLS secret key must not be zero')
3969

40-
sk = BLSSchemePrivateKey.from_bytes(private_key_bytes)
41-
pk = bytes(sk.get_g1()).hex()
42-
pop = bytes(PopSchemeMPL.pop_prove(sk)).hex()
70+
cls.validate_registrant_address(registrant_address)
71+
72+
sk = BLSSchemePrivateKey.from_bytes(private_key_bytes)
73+
pk = bytes(sk.get_g1())
74+
message = cls.build_message(Network.get_network().chain_id(), registrant_address, pk)
75+
pop = bytes(core_sign_mpl(sk, message, POP_DST))
4376

44-
return {'pk': pk, 'pop': pop}
77+
return {'pk': pk.hex(), 'pop': pop.hex()}
4578

4679
@classmethod
47-
def from_passphrase(cls, passphrase: str) -> dict:
80+
def from_passphrase(cls, passphrase: str, registrant_address: str) -> dict:
4881
"""Convenience: derives private key from mnemonic and builds PoP.
4982
5083
Returns:
5184
dict with 'pk' (hex, 48 bytes G1) and 'pop' (hex, 96 bytes G2)
5285
"""
53-
return cls.build_proof_of_possession(cls.derive_bls_private_key(passphrase))
86+
return cls.build_proof_of_possession(
87+
cls.derive_bls_private_key(passphrase), registrant_address
88+
)

‎crypto/transactions/builder/validator_registration_builder.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ def __init__(self, data: dict):
99
super().__init__(data)
1010
self.to(ContractAddresses.CONSENSUS.value)
1111

12-
def validator_passphrase(self, passphrase: str):
13-
bls = ProofOfPossession.from_passphrase(passphrase)
12+
def validator_proof(self, passphrase: str, registrant_address: str):
13+
bls = ProofOfPossession.from_passphrase(passphrase, registrant_address)
1414
self.transaction.data['validatorPublicKey'] = '0x' + bls['pk']
1515
self.transaction.data['validatorProof'] = '0x' + bls['pop']
1616
self.transaction.refresh_payload_data()

‎crypto/transactions/builder/validator_update_builder.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ def __init__(self, data: dict):
99
super().__init__(data)
1010
self.to(ContractAddresses.CONSENSUS.value)
1111

12-
def validator_passphrase(self, passphrase: str):
13-
bls = ProofOfPossession.from_passphrase(passphrase)
12+
def validator_proof(self, passphrase: str, registrant_address: str):
13+
bls = ProofOfPossession.from_passphrase(passphrase, registrant_address)
1414
self.transaction.data['validatorPublicKey'] = '0x' + bls['pk']
1515
self.transaction.data['validatorProof'] = '0x' + bls['pop']
1616
self.transaction.refresh_payload_data()

‎crypto/utils/transaction_data_encoder.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ def multi_payment(recipients, amounts):
1212
)
1313

1414
@staticmethod
15-
def update_validator(passphrase: str):
16-
bls = ProofOfPossession.from_passphrase(passphrase)
15+
def update_validator(passphrase: str, registrant_address: str):
16+
bls = ProofOfPossession.from_passphrase(passphrase, registrant_address)
1717
return AbiEncoder(ContractAbiType.CONSENSUS).encode_function_call_hex(
1818
AbiFunction.UPDATE_VALIDATOR.value, ['0x' + bls['pk'], '0x' + bls['pop']]
1919
)
@@ -31,8 +31,8 @@ def username_resignation():
3131
)
3232

3333
@staticmethod
34-
def validator_registration(passphrase: str):
35-
bls = ProofOfPossession.from_passphrase(passphrase)
34+
def validator_registration(passphrase: str, registrant_address: str):
35+
bls = ProofOfPossession.from_passphrase(passphrase, registrant_address)
3636
return AbiEncoder(ContractAbiType.CONSENSUS).encode_function_call_hex(
3737
AbiFunction.VALIDATOR_REGISTRATION.value, ['0x' + bls['pk'], '0x' + bls['pop']]
3838
)

‎setup.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
'binary-helpers',
99
'coincurve',
1010
'pycryptodomex',
11-
'btclib',
11+
'btclib==2023.7.12',
1212
'cryptography',
1313
]
1414

‎tests/fixtures/transactions/transaction-data-encoder.json‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
"Username": "test",
33
"Address": "0xA5cc0BfEB09742C5e4C610f2EBaaB82Eb142Ca10",
44
"ValidatorPassphrase": "bless organ december boring ill obvious unaware dinosaur broccoli build hamster rebuild skin airport stay entry denial agent october thought duck trouble decorate way",
5+
"RegistrantAddress": "0x1E6747BEAa5B4076a6A98D735DF8c35a70D18Bdd",
56
"Amount": "1000000000000",
67
"Encoded": {
7-
"UpdateValidator": "0x8f062626000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a8bb7c80d24ee79cf3f141eae774b7575466d68631834c29433036ac84eb4904b8f071167cccd5bcc9d11e7c187d6fc70b87ce6e046a750b07f6a8a5985e76bf005bb55b8c70c1cefaccd4c37c314ce69ddfd2eb4a21f8775e01da02e77590b3",
8+
"UpdateValidator": "0x8f062626000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb61100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006097ec59b22ef8232c90bf875c21f8e4452fef8f99f49bc0fc3bbcd2647c64d57fdcade7949ef2c9f0e3fe74553aca02880a2940ff0203523d790fd858f5a70c72c16c5718f1ca92bba37c1c9efbce445d3e071eb1fc8df5a7b1a2d54055939d8c",
89
"UsernameRegistration": "0x36a94134000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000",
910
"UsernameResignation": "0xebed6dab",
10-
"ValidatorRegistration": "0x226f2645000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a8bb7c80d24ee79cf3f141eae774b7575466d68631834c29433036ac84eb4904b8f071167cccd5bcc9d11e7c187d6fc70b87ce6e046a750b07f6a8a5985e76bf005bb55b8c70c1cefaccd4c37c314ce69ddfd2eb4a21f8775e01da02e77590b3",
11+
"ValidatorRegistration": "0x226f2645000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb61100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006097ec59b22ef8232c90bf875c21f8e4452fef8f99f49bc0fc3bbcd2647c64d57fdcade7949ef2c9f0e3fe74553aca02880a2940ff0203523d790fd858f5a70c72c16c5718f1ca92bba37c1c9efbce445d3e071eb1fc8df5a7b1a2d54055939d8c",
1112
"ValidatorResignation": "0xb85f5da2",
1213
"TokenTransfer": "0xa9059cbb000000000000000000000000a5cc0bfeb09742c5e4c610f2ebaab82eb142ca10000000000000000000000000000000000000000000000000000000e8d4a51000",
1314
"MultiPayment": "0x084ce708000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a5cc0bfeb09742c5e4c610f2ebaab82eb142ca10000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000003e8"

‎tests/fixtures/transactions/validator-registration.json‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
"gasPrice": 5000000000,
66
"gasLimit": 200000,
77
"nonce": "1",
8-
"data": "226f2645000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a8bb7c80d24ee79cf3f141eae774b7575466d68631834c29433036ac84eb4904b8f071167cccd5bcc9d11e7c187d6fc70b87ce6e046a750b07f6a8a5985e76bf005bb55b8c70c1cefaccd4c37c314ce69ddfd2eb4a21f8775e01da02e77590b3",
8+
"data": "226f2645000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb61100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006097ec59b22ef8232c90bf875c21f8e4452fef8f99f49bc0fc3bbcd2647c64d57fdcade7949ef2c9f0e3fe74553aca02880a2940ff0203523d790fd858f5a70c72c16c5718f1ca92bba37c1c9efbce445d3e071eb1fc8df5a7b1a2d54055939d8c",
99
"to": "0x535B3D7A252fa034Ed71F0C53ec0C6F784cB64E1",
1010
"validatorPublicKey": "0xb0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb611",
11-
"validatorProof": "0xa8bb7c80d24ee79cf3f141eae774b7575466d68631834c29433036ac84eb4904b8f071167cccd5bcc9d11e7c187d6fc70b87ce6e046a750b07f6a8a5985e76bf005bb55b8c70c1cefaccd4c37c314ce69ddfd2eb4a21f8775e01da02e77590b3",
11+
"validatorProof": "0x97ec59b22ef8232c90bf875c21f8e4452fef8f99f49bc0fc3bbcd2647c64d57fdcade7949ef2c9f0e3fe74553aca02880a2940ff0203523d790fd858f5a70c72c16c5718f1ca92bba37c1c9efbce445d3e071eb1fc8df5a7b1a2d54055939d8c",
1212
"v": 0,
13-
"r": "d44a597b3b2b14f9770abcdabd73b3c12d0a5ad1a289ac71f8f7a54212cf035d",
14-
"s": "7a111e447b0b28462b7973020f6b8fa9e3c0aac6f5dd71ec1e1d6eb342e153c0",
15-
"hash": "879559d0f2deed36c3e03fc513ba7f0940f3e1370f3c4750453266efc9066941"
13+
"r": "9859f5cf72a93cfc2893e00915e288d668f867dbd4b4352809f6f2b560330552",
14+
"s": "34b1ed8fb81832dd7ccd1f19e2b5d8b46d878974fe4a0b193876f2db6711abca",
15+
"hash": "0b2e7b0e36333975114b7e27262edd9078027f87cc857ca9a8605be26f007a5a"
1616
},
17-
"serialized": "f901960185012a05f20083030d4094535b3d7a252fa034ed71f0c53ec0c6f784cb64e1890d8d726b7177a80000b90124226f2645000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a8bb7c80d24ee79cf3f141eae774b7575466d68631834c29433036ac84eb4904b8f071167cccd5bcc9d11e7c187d6fc70b87ce6e046a750b07f6a8a5985e76bf005bb55b8c70c1cefaccd4c37c314ce69ddfd2eb4a21f8775e01da02e77590b3825c6ba0d44a597b3b2b14f9770abcdabd73b3c12d0a5ad1a289ac71f8f7a54212cf035da07a111e447b0b28462b7973020f6b8fa9e3c0aac6f5dd71ec1e1d6eb342e153c0",
18-
"validatorPassphrase": "bless organ december boring ill obvious unaware dinosaur broccoli build hamster rebuild skin airport stay entry denial agent october thought duck trouble decorate way"
17+
"serialized": "f901960185012a05f20083030d4094535b3d7a252fa034ed71f0c53ec0c6f784cb64e1890d8d726b7177a80000b90124226f2645000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb61100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006097ec59b22ef8232c90bf875c21f8e4452fef8f99f49bc0fc3bbcd2647c64d57fdcade7949ef2c9f0e3fe74553aca02880a2940ff0203523d790fd858f5a70c72c16c5718f1ca92bba37c1c9efbce445d3e071eb1fc8df5a7b1a2d54055939d8c825c6ba09859f5cf72a93cfc2893e00915e288d668f867dbd4b4352809f6f2b560330552a034b1ed8fb81832dd7ccd1f19e2b5d8b46d878974fe4a0b193876f2db6711abca",
18+
"validatorPassphrase": "bless organ december boring ill obvious unaware dinosaur broccoli build hamster rebuild skin airport stay entry denial agent october thought duck trouble decorate way",
19+
"registrantAddress": "0x1E6747BEAa5B4076a6A98D735DF8c35a70D18Bdd"
1920
}

‎tests/fixtures/transactions/validator-update.json‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
"gasPrice": 5000000000,
66
"gasLimit": 200000,
77
"nonce": "1",
8-
"data": "8f062626000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a8bb7c80d24ee79cf3f141eae774b7575466d68631834c29433036ac84eb4904b8f071167cccd5bcc9d11e7c187d6fc70b87ce6e046a750b07f6a8a5985e76bf005bb55b8c70c1cefaccd4c37c314ce69ddfd2eb4a21f8775e01da02e77590b3",
8+
"data": "8f062626000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb61100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006097ec59b22ef8232c90bf875c21f8e4452fef8f99f49bc0fc3bbcd2647c64d57fdcade7949ef2c9f0e3fe74553aca02880a2940ff0203523d790fd858f5a70c72c16c5718f1ca92bba37c1c9efbce445d3e071eb1fc8df5a7b1a2d54055939d8c",
99
"to": "0x535B3D7A252fa034Ed71F0C53ec0C6F784cB64E1",
1010
"validatorPublicKey": "0xb0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb611",
11-
"validatorProof": "0xa8bb7c80d24ee79cf3f141eae774b7575466d68631834c29433036ac84eb4904b8f071167cccd5bcc9d11e7c187d6fc70b87ce6e046a750b07f6a8a5985e76bf005bb55b8c70c1cefaccd4c37c314ce69ddfd2eb4a21f8775e01da02e77590b3",
12-
"v": 0,
13-
"r": "583edde415ec3f61643b5e2a18c34c4113eb67434adfc4d3633a1469a6fe3895",
14-
"s": "165b3ec00a56227ab3931865a3a63e5e5dbb79e4e42985abe394f8eb74acbc58",
15-
"hash": "917fb0ebbdfdeb2785db0e3d67bb68bf655a6381a529f22676a7a16e07278e1c"
11+
"validatorProof": "0x97ec59b22ef8232c90bf875c21f8e4452fef8f99f49bc0fc3bbcd2647c64d57fdcade7949ef2c9f0e3fe74553aca02880a2940ff0203523d790fd858f5a70c72c16c5718f1ca92bba37c1c9efbce445d3e071eb1fc8df5a7b1a2d54055939d8c",
12+
"v": 1,
13+
"r": "d25b02f2b2af965d1c21bc88a168b9194b7d52f8ed497fe8fccdaa445cac9c2b",
14+
"s": "301c1977071c3f8169ddbf306219fcebdafe25fe5b392f7dca819bb8d80aee0b",
15+
"hash": "1fe4693b1b89acdead9cc7e3fcf11bc4e5970736946d4916335d09f3b48248a0"
1616
},
17-
"serialized": "f9018d0185012a05f20083030d4094535b3d7a252fa034ed71f0c53ec0c6f784cb64e180b901248f062626000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a8bb7c80d24ee79cf3f141eae774b7575466d68631834c29433036ac84eb4904b8f071167cccd5bcc9d11e7c187d6fc70b87ce6e046a750b07f6a8a5985e76bf005bb55b8c70c1cefaccd4c37c314ce69ddfd2eb4a21f8775e01da02e77590b3825c6ba0583edde415ec3f61643b5e2a18c34c4113eb67434adfc4d3633a1469a6fe3895a0165b3ec00a56227ab3931865a3a63e5e5dbb79e4e42985abe394f8eb74acbc58",
18-
"validatorPassphrase": "bless organ december boring ill obvious unaware dinosaur broccoli build hamster rebuild skin airport stay entry denial agent october thought duck trouble decorate way"
17+
"serialized": "f9018d0185012a05f20083030d4094535b3d7a252fa034ed71f0c53ec0c6f784cb64e180b901248f062626000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030b0093ac8f37588e15df7cfb04d0722dc5486cec062233136d3b6a16d41946577a1f332c4c29c0601ccefac1905dbb61100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006097ec59b22ef8232c90bf875c21f8e4452fef8f99f49bc0fc3bbcd2647c64d57fdcade7949ef2c9f0e3fe74553aca02880a2940ff0203523d790fd858f5a70c72c16c5718f1ca92bba37c1c9efbce445d3e071eb1fc8df5a7b1a2d54055939d8c825c6ca0d25b02f2b2af965d1c21bc88a168b9194b7d52f8ed497fe8fccdaa445cac9c2ba0301c1977071c3f8169ddbf306219fcebdafe25fe5b392f7dca819bb8d80aee0b",
18+
"validatorPassphrase": "bless organ december boring ill obvious unaware dinosaur broccoli build hamster rebuild skin airport stay entry denial agent october thought duck trouble decorate way",
19+
"registrantAddress": "0x1E6747BEAa5B4076a6A98D735DF8c35a70D18Bdd"
1920
}

0 commit comments

Comments
 (0)