Skip to content

Commit 06a057b

Browse files
fix(wallet): reject sub-micro transfer amounts
Co-authored-by: liu971227-sys <[email protected]>
1 parent d3e4262 commit 06a057b

3 files changed

Lines changed: 94 additions & 4 deletions

File tree

node/payout_preflight.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,23 @@ def validate_wallet_transfer_admin(payload: Any) -> PreflightResult:
4444
return PreflightResult(ok=False, error=aerr, details={})
4545
if amount_rtc is None or amount_rtc <= 0:
4646
return PreflightResult(ok=False, error="amount_must_be_positive", details={})
47+
amount_i64 = int(amount_rtc * 1_000_000)
48+
if amount_i64 <= 0:
49+
return PreflightResult(
50+
ok=False,
51+
error="amount_too_small_after_quantization",
52+
details={"amount_rtc": amount_rtc, "min_rtc": 0.000001},
53+
)
4754

4855
return PreflightResult(
4956
ok=True,
5057
error="",
51-
details={"from_miner": str(from_miner), "to_miner": str(to_miner), "amount_rtc": amount_rtc},
58+
details={
59+
"from_miner": str(from_miner),
60+
"to_miner": str(to_miner),
61+
"amount_rtc": amount_rtc,
62+
"amount_i64": amount_i64,
63+
},
5264
)
5365

5466

@@ -70,6 +82,13 @@ def validate_wallet_transfer_signed(payload: Any) -> PreflightResult:
7082
return PreflightResult(ok=False, error=aerr, details={})
7183
if amount_rtc is None or amount_rtc <= 0:
7284
return PreflightResult(ok=False, error="amount_must_be_positive", details={})
85+
amount_i64 = int(amount_rtc * 1_000_000)
86+
if amount_i64 <= 0:
87+
return PreflightResult(
88+
ok=False,
89+
error="amount_too_small_after_quantization",
90+
details={"amount_rtc": amount_rtc, "min_rtc": 0.000001},
91+
)
7392

7493
if not (from_address.startswith("RTC") and len(from_address) == 43):
7594
return PreflightResult(ok=False, error="invalid_from_address_format", details={})
@@ -88,6 +107,12 @@ def validate_wallet_transfer_signed(payload: Any) -> PreflightResult:
88107
return PreflightResult(
89108
ok=True,
90109
error="",
91-
details={"from_address": from_address, "to_address": to_address, "amount_rtc": amount_rtc, "nonce": nonce_int},
110+
details={
111+
"from_address": from_address,
112+
"to_address": to_address,
113+
"amount_rtc": amount_rtc,
114+
"amount_i64": amount_i64,
115+
"nonce": nonce_int,
116+
},
92117
)
93118

node/tests/test_payout_preflight.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ def test_admin_ok(self):
2121
r = validate_wallet_transfer_admin({"from_miner": "a", "to_miner": "b", "amount_rtc": 1})
2222
self.assertTrue(r.ok)
2323

24+
def test_admin_rejects_sub_micro_amount(self):
25+
r = validate_wallet_transfer_admin(
26+
{"from_miner": "a", "to_miner": "b", "amount_rtc": 0.0000001}
27+
)
28+
self.assertFalse(r.ok)
29+
self.assertEqual(r.error, "amount_too_small_after_quantization")
30+
31+
def test_admin_accepts_min_quantized_amount(self):
32+
r = validate_wallet_transfer_admin(
33+
{"from_miner": "a", "to_miner": "b", "amount_rtc": 0.000001}
34+
)
35+
self.assertTrue(r.ok)
36+
self.assertEqual(r.details.get("amount_i64"), 1)
37+
2438
def test_signed_rejects_missing(self):
2539
r = validate_wallet_transfer_signed({"from_address": "RTC" + "a" * 40})
2640
self.assertFalse(r.ok)
@@ -51,6 +65,32 @@ def test_signed_ok_shape(self):
5165
r = validate_wallet_transfer_signed(payload)
5266
self.assertTrue(r.ok)
5367

68+
def test_signed_rejects_sub_micro_amount(self):
69+
payload = {
70+
"from_address": "RTC" + "a" * 40,
71+
"to_address": "RTC" + "b" * 40,
72+
"amount_rtc": 0.0000001,
73+
"nonce": "123",
74+
"signature": "00",
75+
"public_key": "00",
76+
}
77+
r = validate_wallet_transfer_signed(payload)
78+
self.assertFalse(r.ok)
79+
self.assertEqual(r.error, "amount_too_small_after_quantization")
80+
81+
def test_signed_accepts_min_quantized_amount(self):
82+
payload = {
83+
"from_address": "RTC" + "a" * 40,
84+
"to_address": "RTC" + "b" * 40,
85+
"amount_rtc": 0.000001,
86+
"nonce": "123",
87+
"signature": "00",
88+
"public_key": "00",
89+
}
90+
r = validate_wallet_transfer_signed(payload)
91+
self.assertTrue(r.ok)
92+
self.assertEqual(r.details.get("amount_i64"), 1)
93+
5494

5595
if __name__ == "__main__":
5696
unittest.main()

payout_preflight.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,23 @@ def validate_wallet_transfer_admin(payload: Any) -> PreflightResult:
4848
return PreflightResult(ok=False, error=aerr, details={})
4949
if amount_rtc is None or amount_rtc <= 0:
5050
return PreflightResult(ok=False, error="amount_must_be_positive", details={})
51+
amount_i64 = int(amount_rtc * 1_000_000)
52+
if amount_i64 <= 0:
53+
return PreflightResult(
54+
ok=False,
55+
error="amount_too_small_after_quantization",
56+
details={"amount_rtc": amount_rtc, "min_rtc": 0.000001},
57+
)
5158

5259
return PreflightResult(
5360
ok=True,
5461
error="",
55-
details={"from_miner": str(from_miner), "to_miner": str(to_miner), "amount_rtc": amount_rtc},
62+
details={
63+
"from_miner": str(from_miner),
64+
"to_miner": str(to_miner),
65+
"amount_rtc": amount_rtc,
66+
"amount_i64": amount_i64,
67+
},
5668
)
5769

5870

@@ -74,6 +86,13 @@ def validate_wallet_transfer_signed(payload: Any) -> PreflightResult:
7486
return PreflightResult(ok=False, error=aerr, details={})
7587
if amount_rtc is None or amount_rtc <= 0:
7688
return PreflightResult(ok=False, error="amount_must_be_positive", details={})
89+
amount_i64 = int(amount_rtc * 1_000_000)
90+
if amount_i64 <= 0:
91+
return PreflightResult(
92+
ok=False,
93+
error="amount_too_small_after_quantization",
94+
details={"amount_rtc": amount_rtc, "min_rtc": 0.000001},
95+
)
7796

7897
if not (from_address.startswith("RTC") and len(from_address) == 43):
7998
return PreflightResult(ok=False, error="invalid_from_address_format", details={})
@@ -92,6 +111,12 @@ def validate_wallet_transfer_signed(payload: Any) -> PreflightResult:
92111
return PreflightResult(
93112
ok=True,
94113
error="",
95-
details={"from_address": from_address, "to_address": to_address, "amount_rtc": amount_rtc, "nonce": nonce_int},
114+
details={
115+
"from_address": from_address,
116+
"to_address": to_address,
117+
"amount_rtc": amount_rtc,
118+
"amount_i64": amount_i64,
119+
"nonce": nonce_int,
120+
},
96121
)
97122

0 commit comments

Comments
 (0)