Skip to content

fix(validator): SCALE-encode str args in _encode_args (#1374)#1376

Open
jakearmstrong59 wants to merge 1 commit into
entrius:testfrom
jakearmstrong59:fix/register-issue-str-encoding
Open

fix(validator): SCALE-encode str args in _encode_args (#1374)#1376
jakearmstrong59 wants to merge 1 commit into
entrius:testfrom
jakearmstrong59:fix/register-issue-str-encoding

Conversation

@jakearmstrong59
Copy link
Copy Markdown
Contributor

Summary

Fixes #1375

After #1335, gitt issues register routes through IssueCompetitionContractClient.register_issue_exec_contract_raw_encode_args. _encode_args had no str branch and raised ValueError: Unsupported type: str for arg github_url on every register_issue call, before any extrinsic was submitted.

This PR adds SCALE encoding for str: a compact-length prefix (modes 0/1/2 covered by a new _scale_compact_length helper) followed by the UTF-8 bytes — matching how String / Vec<u8> are encoded in SCALE.

Changes

  • gittensor/validator/issue_competitions/contract_client.py
    • New module-level _scale_compact_length(n) covering SCALE compact integer modes 0 (n < 2⁶), 1 (n < 2¹⁴), and 2 (n < 2³⁰). Rejects negative input and values that would require big-integer mode 3 (not reachable for any payload sent by the client).
    • New 'str' branch in _encode_args: type-checks, UTF-8 encodes, prepends compact length.
  • tests/validator/test_contract_client_transactions.py
    • TestScaleCompactLength — parametrized boundary coverage for every mode (0/1/2) plus negative and oversize rejection.
    • TestEncodeArgsStr — byte-level assertion of the full register_issue encoding: short URL (mode 0), long URL ≥64 bytes (mode 1), non-str rejected with a clear message, UTF-8 multibyte URL.

Testing

  • Full suite: pytest tests/892 passed.
  • Targeted: pytest tests/validator/test_contract_client_transactions.py43 passed (28 pre-existing + 15 new).
  • Reproducer from fix(cli): guard miner score _drain_logs against Warning-state crash #1374 verified: raises on fc503f9, succeeds after this change with a 70-byte payload whose layout is byte-checked in the new tests.
  • ruff check and ruff format --check clean repo-wide.

Notes

After entrius#1335, gitt issues register routes through _encode_args, which
had no str branch and raised ValueError for every register_issue call
before any extrinsic was submitted.

Add a SCALE str encoder (compact-length prefix + UTF-8 bytes) and a
module-level _scale_compact_length helper covering modes 0/1/2.
@xiao-xiao-mao xiao-xiao-mao Bot added the bug Something isn't working label May 27, 2026
@anderdc
Copy link
Copy Markdown
Collaborator

anderdc commented May 27, 2026

Can you show me the tests you ran to verify it worked. Local testnet subtensor with locally deployed contract is fine.

@jakearmstrong59
Copy link
Copy Markdown
Contributor Author

Hi @anderdc how are you? Thanks for reviewing. I've tested locally against substrate-contracts-node --dev with a stub contract that has the same register_issue signature + same selector (0x5c056a24). I've run gitt issues register twice - once with a short URL, once with a long one to hit both compact-length branches the PR adds:

gitt issues register --contract 5C9feb... --network local
--repo entrius/gittensor --issue 1375 --bounty 10 --wallet local-test -y
→ ✓ tx 0x91df25dd...826ff4bf (URL = 48 bytes, mode 0)

gitt issues register --contract 5C9feb... --network local
--repo electron-react-boilerplate/electron-react-boilerplate
--issue 3729 --bounty 10 --wallet local-test -y
→ ✓ tx 0x7037c6de...96ad1c93 (URL = 84 bytes, mode 1)

Read back via cargo contract call get_last_registered → both decode byte-perfect:
("#1375", "entrius/gittensor", 1375, 10000000000)
("electron-react-boilerplate/electron-react-boilerplate#3729", ..., 3729, 10000000000)

I used a stub, not the real contract, because the real one needs SubtensorExtension(5001) which stock substrate-contracts-node doesn't have.
The fix is in _encode_args though, which is upstream of any chain extension - the stub still exercises gitt's encoder - Contracts::call extrinsic - pallet-contracts dispatch - ink! decode - storage.
If you want the real contract in the loop, bittensor's public test chain has pallet-contracts + SubtensorExtension(5001), so I can deploy the real unmodified contract there (owned by my test wallet) and redo end-to-end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] gitt issues register cannot encode register_issue string arguments after #1335

2 participants