Skip to content

Commit 536bfb6

Browse files
committed
test(solana): CreateAccount/SetAuthority require AdvancedMode; StakeAuthorize clear-signs
CreateAccount (owner+space not shown) and SetAuthority (takeover vector, None case not disclosed) are now gated behind AdvancedMode; StakeAuthorize clear-signs showing the role and new authority.
1 parent 78bd6ca commit 536bfb6

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

tests/test_msg_solana_signtx.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,62 @@ def test_solana_sign_token_approve(self):
309309
self.assertEqual(len(resp.signature), 64)
310310
self.client.apply_policy('AdvancedMode', False)
311311

312+
def test_solana_sign_create_account_requires_advanced_mode(self):
313+
"""SystemProgram CreateAccount assigns the new account's owner program
314+
and space (not shown on-screen), so it is gated behind AdvancedMode."""
315+
self.requires_fullFeature()
316+
self.setup_mnemonic_allallall()
317+
from keepkeylib.client import CallException
318+
from_pubkey = self._get_from_pubkey()
319+
new_account = b'\x55' * 32
320+
instr_data = struct.pack('<I', 0) + struct.pack('<Q', 1000000) # create + lamports
321+
raw_tx = self._build_tx(from_pubkey, [new_account], self.SYSTEM_PROGRAM, instr_data)
322+
tx = messages.SolanaSignTx(
323+
address_n=parse_path("m/44'/501'/0'/0'"), raw_tx=raw_tx)
324+
self.client.apply_policy('AdvancedMode', False)
325+
with self.assertRaises(CallException):
326+
self.client.call(tx)
327+
self.client.apply_policy('AdvancedMode', True)
328+
resp = self.client.call(tx)
329+
self.assertEqual(len(resp.signature), 64)
330+
self.client.apply_policy('AdvancedMode', False)
331+
332+
def test_solana_sign_set_authority_requires_advanced_mode(self):
333+
"""SPL SetAuthority hands over control of a mint/account; the target and
334+
the 'clear authority' (None) case are not fully disclosed, so it is
335+
gated behind AdvancedMode."""
336+
self.requires_fullFeature()
337+
self.setup_mnemonic_allallall()
338+
from keepkeylib.client import CallException
339+
from_pubkey = self._get_from_pubkey()
340+
authority = b'\x66' * 32
341+
instr_data = bytes([6, 2]) # SetAuthority, authority_type=AccountOwner
342+
raw_tx = self._build_tx(from_pubkey, [authority], self.TOKEN_PROGRAM, instr_data)
343+
tx = messages.SolanaSignTx(
344+
address_n=parse_path("m/44'/501'/0'/0'"), raw_tx=raw_tx)
345+
self.client.apply_policy('AdvancedMode', False)
346+
with self.assertRaises(CallException):
347+
self.client.call(tx)
348+
self.client.apply_policy('AdvancedMode', True)
349+
resp = self.client.call(tx)
350+
self.assertEqual(len(resp.signature), 64)
351+
self.client.apply_policy('AdvancedMode', False)
352+
353+
def test_solana_sign_stake_authorize_clearsigns(self):
354+
"""StakeAuthorize clear-signs, showing the role (staker/withdrawer) and
355+
the new authority."""
356+
self.requires_fullFeature()
357+
self.setup_mnemonic_allallall()
358+
from_pubkey = self._get_from_pubkey()
359+
current_auth = b'\x77' * 32
360+
new_auth = b'\x88' * 32
361+
# Authorize (type=1 LE u32) + new authority(32) + StakeAuthorize role (0=staker)
362+
instr_data = struct.pack('<I', 1) + new_auth + struct.pack('<I', 0)
363+
raw_tx = self._build_tx(from_pubkey, [current_auth], self.STAKE_PROGRAM, instr_data)
364+
resp = self.client.call(messages.SolanaSignTx(
365+
address_n=parse_path("m/44'/501'/0'/0'"), raw_tx=raw_tx))
366+
self.assertEqual(len(resp.signature), 64)
367+
312368
def test_solana_sign_stake_delegate(self):
313369
"""Stake delegate — OLED shows 'Delegate stake?'."""
314370
self.requires_fullFeature()

0 commit comments

Comments
 (0)