Skip to content

Conversation

@aorumbayev
Copy link
Contributor

@aorumbayev aorumbayev commented Dec 15, 2025

Summary

Adds fixed-length byte validation using x-algokit-byte-length vendor extension and restructures block models to align with js-algorand-sdk v3.

Key Changes

Fixed-Length Byte Validation

  • Added x-algokit-byte-length OpenAPI vendor extension support
  • Validates 32-byte fields (genesis_hash, previous_block_hash, transaction roots) during (de)serialization
  • Raises errors on length mismatches

Block Model Restructuring (Breaking)

  • GetBlockBlockResponse
  • BlockHeader fields reorganized into nested dataclasses:
    • TxnCommitments - transaction roots (SHA256/512)
    • RewardState - fee_sink, rewards_pool, rewards_level, etc.
    • UpgradeState - current/next protocol versions
    • UpgradeVote - upgrade proposals
  • Renamed BlockEvalDelta.bytesbytes_value (Python keyword conflict)
  • All block types remain publicly exported for type hints and isinstance checks

AVM Debugger Source Map (Bug Fix)

  • Fixed JSON key: sha512_256hash (restores standard AVM debugger format compatibility)
  • Added Python snapshot tests for AVM debugger format validation

Wire Format

  • Msgpack encoding unchanged - fully backward compatible with nodes
  • Only Python API structure changed

Migration Example

# Before
response: GetBlock = algod.get_block(round)
fee_sink = response.block.header.fee_sink

# After  
response: BlockResponse = algod.get_block(round)
fee_sink = response.block.header.reward_state.fee_sink

See MIGRATION-NOTES.md for complete field mapping.

@aorumbayev aorumbayev force-pushed the decoupling-byte-len-vendor-extension branch from 4724db7 to b75499d Compare December 15, 2025 21:05
…ngth byte validation

- Add byte_length and list_inner_byte_length fields to TypeInfo in builder.py
- Update _build_metadata() to generate fixed-length byte serde helpers
- Add encode_fixed_bytes_base64/decode_fixed_bytes_base64 helpers for 32/64 byte validation
- Add encode_fixed_bytes_sequence/decode_fixed_bytes_sequence for array validation
- Regenerate API clients with fixed-length byte fields (group, lease, signature, etc.)
- Update OAS_BRANCH to fix/byte-len-validation for spec generation
@aorumbayev aorumbayev force-pushed the decoupling-byte-len-vendor-extension branch from b75499d to 9de43f5 Compare December 15, 2025 21:38
@github-actions
Copy link

github-actions bot commented Dec 15, 2025

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/algokit_abi
   _arc32_to_arc56.py104298%109, 126
   _arc56_serde.py108397%31, 36, 154
   abi.py4743193%76–82, 85, 88, 113, 121, 177, 192, 201–204, 225, 258, 279–281, 284, 295, 382, 403, 488, 516, 529, 555, 634, 651, 665
   arc32.py96892%201–210
   arc56.py4753193%87, 100, 155–156, 321, 342, 352, 365–367, 386, 391, 691, 711, 730–732, 747, 750–752, 765–766, 768–769, 808–821
src/algokit_algod_client
   client.py68323466%63, 69, 75, 79, 85, 93, 96–101, 116, 134–147, 182, 249, 275–276, 290, 341, 357, 375, 391, 421, 451, 488, 518, 527–545, 575, 602, 635, 645–668, 698, 709–732, 744–769, 796, 806–826, 853, 880, 907, 917–940, 954–984, 1011, 1038, 1071, 1082–1102, 1112–1132, 1179, 1209, 1253, 1263–1293, 1302–1320, 1337, 1341, 1387, 1392, 1394, 1399, 1403, 1408, 1479, 1492–1497, 1502, 1505–1509, 1516–1528, 1536–1541, 1566–1576, 1582–1584
   exceptions.py431370%14, 18–21, 27, 31–32, 44–48
src/algokit_algod_client/models
   _block.py1593280%49–51, 59–65, 71–73, 82–88, 92–99, 104, 116–118
   _ledger_state_delta.py1741591%48–52, 56–62, 68–70
   _serde_helpers.py1717854%19, 21, 37, 42–45, 52, 65–67, 72, 76–77, 79, 86, 90–91, 100–110, 115–123, 128, 132, 139, 149–156, 160–169, 178–196, 206, 218, 228
src/algokit_common
   address.py26581%9, 12, 17, 23, 31
   source_map.py56591%19, 78, 122, 153–154
src/algokit_common/serde
   _core.py3465484%86, 168, 187, 269–298, 303, 316, 328, 341, 345, 348–349, 391–394, 414, 419, 430–432, 439–440, 447–448, 450, 456–457, 497, 525–526, 563, 571, 577, 586, 592, 601, 607
   _primitives.py732368%5–7, 11–13, 17, 23, 35–37, 41–43, 47–49, 55, 60–61, 122, 126, 130
src/algokit_indexer_client
   client.py67425362%62, 68, 74, 78, 82–84, 91–104, 115, 128–146, 175, 198, 201, 204, 207, 223, 244, 247, 250, 253, 269, 289, 292, 295, 311, 332, 335, 338, 341, 357, 378, 381, 384, 387, 403, 435, 438, 441, 444, 447, 450, 453, 456, 459, 462, 465, 468, 471, 474, 477, 493, 526, 544, 560, 583, 586, 589, 592, 595, 598, 614, 636, 639, 642, 645, 648, 664, 682, 698, 732, 735, 738, 741, 744, 747, 750, 753, 756, 759, 762, 765, 768, 771, 774, 777, 780, 796, 814, 830, 887, 893, 896, 899, 902, 905, 908, 911, 914, 917, 933, 952, 955, 971, 996, 1002, 1018, 1039, 1045, 1048, 1051, 1054, 1057, 1073, 1100, 1103, 1106, 1109, 1112, 1115, 1118, 1121, 1137, 1175, 1181, 1184, 1187, 1193, 1199, 1202, 1205, 1208, 1211, 1214, 1223, 1226, 1245, 1254–1270, 1273–1280, 1350, 1355–1369, 1373, 1376–1380, 1384–1415, 1418–1423, 1427–1456
   exceptions.py431370%14, 18–21, 27, 31–32, 44–48
src/algokit_indexer_client/models
   _serde_helpers.py17112129%18–22, 26, 31, 35–37, 42–45, 52, 57–67, 71–81, 86, 90–91, 100–110, 115–123, 127–134, 139, 149–156, 160–169, 178–196, 205–213, 217–219, 227–230, 238–241
src/algokit_kmd_client
   client.py49532235%61, 67, 73, 77, 81–83, 90–103, 114, 127–145, 187, 197–227, 237–267, 307, 317–347, 357–387, 427, 438–468, 478–508, 518–548, 558–588, 628, 668, 678–708, 736, 749, 789, 799–829, 839–869, 879–909, 919–949, 959–989, 999–1029, 1041–1047, 1050–1054, 1058, 1061–1064, 1134, 1139–1153, 1157, 1160–1164, 1168–1199, 1202–1207, 1211–1240
   exceptions.py433714%13–50, 55–59
src/algokit_kmd_client/models
   _serde_helpers.py17113024%18–22, 26, 31, 35–37, 42–45, 50–53, 57–67, 71–81, 85–93, 100–110, 115–123, 127–134, 139, 149–156, 160–169, 178–196, 205–213, 217–219, 227–230, 238–241
src/algokit_transact
   logicsig.py1076044%59–65, 70, 75, 80, 85–89, 94, 99–101, 104–132, 144–147, 159–160, 172–173, 187–191, 199–220
   signer.py822174%120–124, 127–128, 131–132, 162–164, 169–170, 184–195
src/algokit_transact/codec
   signed.py421076%19, 21, 24, 40, 44, 53–57
   transaction.py41295%16, 65
src/algokit_transact/models
   app_call.py32820438%25, 29, 77–91, 95–98, 106, 108, 111, 124, 129, 135, 142–154, 158–261, 305–308, 322–324, 336, 340–342, 351, 364–365, 371–372, 376, 379–385, 388–399, 402–406, 409–412, 415–423, 426–436, 439–446
   state_proof.py1042180%94, 102, 114, 120, 127–138, 144–150
   transaction.py54198%35
src/algokit_transact/ops
   group.py21290%15, 22
   validate.py209399%60, 74, 76
src/algokit_transact/signing
   multisig.py55885%17, 19, 21, 41, 61, 67, 69, 74
   types.py28389%10, 14, 24
   validation.py221914%36–63
src/algokit_utils
   _debugging.py1592187%43–45, 57, 84, 88, 97, 134, 182, 184, 212, 217, 224, 230, 255–265, 270
   algo25.py220%13–29
   algorand.py1051487%67–68, 80–81, 111–112, 139–140, 175–176, 323, 346, 362, 381
   config.py781877%23, 30–34, 73–74, 100, 105, 111–116, 141, 149, 151
src/algokit_utils/accounts
   account_manager.py2775082%174, 204, 207, 210, 213, 239–243, 259, 262, 265, 268, 291–296, 334–344, 362, 369–371, 388–391, 461, 507, 527–531, 544–545, 615, 633, 636, 639, 642, 813, 916, 990, 997, 1035
   kmd_account_manager.py971881%45–51, 83, 86–90, 115, 119, 155, 193, 206
src/algokit_utils/applications
   abi.py1254762%31, 66, 75–79, 83–84, 104–106, 113–117, 141, 151, 161, 180–181, 193–195, 203–208, 235–244, 259–270
   app_client.py79622372%125, 133, 320–323, 326, 329, 332, 335, 347–350, 353, 356, 359, 362, 374, 383, 392, 395–456, 469–525, 549–551, 568–571, 579–582, 590–593, 601–604, 612–615, 628–631, 644, 740–743, 777, 789, 801, 813, 825, 842, 859, 869, 879, 889, 899, 909, 946–959, 975, 992, 1009, 1026, 1047, 1068, 1158, 1222, 1364, 1430–1431, 1480, 1482, 1488, 1541–1549, 1582–1585, 1588–1591, 1612, 1660, 1725–1727, 1740–1751, 1796, 1813, 1815, 1818, 1820, 1965–1979, 2008, 2021–2023, 2027, 2038–2039, 2073, 2078, 2091–2093, 2096–2109, 2115–2116, 2127–2129, 2131–2132, 2139–2141, 2146–2150, 2157–2162, 2182, 2185
   app_deployer.py2633886%96, 270, 277, 287–292, 295–299, 375–376, 496, 589, 601–615, 627, 632–635, 644, 658, 665, 672, 701, 730–758, 776, 787
   app_factory.py2803089%176, 432, 453, 462, 654, 664, 714, 946, 960–965, 976–977, 1010, 1048, 1066–1067, 1089, 1092, 1120–1136
   app_manager.py2141792%256, 277–278, 347–348, 393–396, 443–444, 476, 504–507, 539, 548
src/algokit_utils/assets
   asset_manager.py1261390%158, 289–290, 299, 305–329, 340
src/algokit_utils/clients
   client_manager.py1785470%77–84, 109, 141–143, 200, 207, 220–221, 232–235, 260, 299, 334–339, 374–376, 408, 429, 450, 495–498, 538–541, 582–585, 622–625, 647–672, 710, 723, 735
   dispenser_api_client.py892078%87, 91, 132–133, 137–140, 181–191, 201–212
src/algokit_utils/errors
   logic_error.py702761%92, 115–160
src/algokit_utils/models
   amount.py1001387%36, 43, 101, 117–118, 150–153, 156–159
src/algokit_utils/transactions
   composer_resources.py2937574%21, 25, 27, 29, 71, 74, 114, 125, 164, 175, 190, 197–198, 202–209, 234–262, 296, 309–311, 317–319, 325, 367–378, 381–392
   transaction_composer.py7749088%146, 393–396, 414–426, 446, 451, 492–495, 552–562, 595, 657–668, 677, 679, 688, 707, 729, 764, 898, 988, 991, 1239, 1256, 1270, 1290, 1310, 1338, 1341, 1350, 1365, 1374, 1381, 1384, 1408–1409, 1411, 1435–1438, 1477–1483, 1503–1521, 1533, 1535, 1540, 1543–1544, 1550–1555, 1571–1574
   transaction_creator.py79791%394, 427, 482, 520, 557, 590, 688
   transaction_sender.py1781790%105–109, 115, 285, 318, 331–332, 440, 734–739, 744–745, 910
src/algokit_utils/transactions/builders
   app.py57296%163–168
   common.py1251390%86, 152, 154, 176, 183, 187–197, 213–214
   keyreg.py461665%75, 77, 80–81, 86, 89, 92–93, 95, 97–103
   method_call.py1323772%260, 262, 269, 294, 299–310, 315, 330–336, 340–346, 350–354, 358–364, 374–375
TOTAL13019262680% 

Tests Skipped Failures Errors Time
843 47 💤 0 ❌ 0 🔥 1m 51s ⏱️

Align Python block model structure with the JavaScript SDK and OpenAPI
spec for cross-SDK consistency.
Structural changes:
- Rename GetBlock -> BlockResponse (matches OAS spec + JS/TS SDKs)
- Add TxnCommitments nested type for transaction roots (txn, txn256)
- Add RewardState nested type for reward fields (fees, rwd, earn, etc.)
- Add UpgradeState nested type for protocol upgrade state
- Add UpgradeVote nested type for upgrade vote parameters
- Refactor BlockHeader to use flattened nested types
- Change BlockEvalDelta.bytes -> bytes_value (avoid Python keyword)
- Fix inner_txns type: SignedTxnInBlock -> SignedTxnWithAD
- Make previous_block_hash and genesis_hash non-optional with defaults
- Fix get_block() to return BlockResponse (typed) instead of Block
- Export typed BlockResponse from _block.py instead of untyped version
BREAKING CHANGE:
- GetBlock removed, use BlockResponse instead
- Field access patterns changed in BlockHeader:
  - header.fee_sink -> header.reward_state.fee_sink
  - header.current_protocol -> header.upgrade_state.current_protocol
  - header.upgrade_propose -> header.upgrade_vote.upgrade_propose
  - header.transactions_root -> header.txn_commitments.transactions_root
- Block response structure: result.header -> result.block.header
@aorumbayev aorumbayev changed the title feat: add x-algokit-byte-length vendor extension support for fixed-length byte validation feat: x-algokit-byte-length support and block model restructuring for cross-SDK alignment Dec 16, 2025
@aorumbayev aorumbayev force-pushed the decoupling-byte-len-vendor-extension branch from cf22d18 to f5d22e5 Compare December 16, 2025 01:45
@aorumbayev aorumbayev marked this pull request as ready for review December 16, 2025 01:45
@aorumbayev aorumbayev force-pushed the decoupling-byte-len-vendor-extension branch from f5d22e5 to 426dd6f Compare December 16, 2025 11:15
Excludes block models from the generated client code to allow separate handling.

This change introduces a mechanism to conditionally include block models during code generation based on a client configuration. It also updates the AVM debugger source map generation by incorporating hashes in the standard AVM debugger format.

Skips tests that depend on msgpack handling until mock server is fixed.
@aorumbayev aorumbayev force-pushed the decoupling-byte-len-vendor-extension branch from 426dd6f to 591b4af Compare December 16, 2025 11:17
Ensures all block-related types (ApplyData, BlockEvalDelta, BlockStateDelta,
SignedTxnWithAD, TxnCommitments, RewardState, UpgradeState, UpgradeVote, etc.)
remain publicly exported from algokit_algod_client.models for type hints,
isinstance checks, and IDE autocomplete. These types are returned by the public
API and must be accessible to users. Aligns with TypeScript SDK behavior.
@aorumbayev aorumbayev merged commit 3072c0e into decoupling Dec 16, 2025
5 checks passed
@aorumbayev aorumbayev deleted the decoupling-byte-len-vendor-extension branch December 16, 2025 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants