Skip to content

fix: encode public_key_type fields as 33-byte binary blobs#11

Merged
kuny0707 merged 2 commits into
masterfrom
fix/pubkey-serialization
Jul 7, 2026
Merged

fix: encode public_key_type fields as 33-byte binary blobs#11
kuny0707 merged 2 commits into
masterfrom
fix/pubkey-serialization

Conversation

@ety001

@ety001 ety001 commented Jul 7, 2026

Copy link
Copy Markdown
Member

Problem

public_key_type fields (like block_signing_key in witness_update,
memo_key in account_create/account_update) were serialized as
varint-prefixed strings by the reflection encoder. In Steem's C++ binary
format, public_key_type is a fixed 33-byte blob (1 byte format + 32 bytes
key data), not a variable-length string.

This caused a digest mismatch on every transaction involving public keys:
the SDK computed the digest using a 54-byte varint-string represe ntation,
while steemd expected a 33-byte binary format.

Fix

  • Add steem:"pubkey" struct tag for public_key_type string fields
  • Add encodePubKey() to the encoder: parses STM...wif.PublicKey
    and writes the 33-byte compressed binary
  • Tag BlockSigningKey in WitnessUpdateOperation, and all MemoKey
    fields in AccountCreate, AccountUpdate, CreateClaimedAccount,
    AccountUpdate2, AccountCreateWithDelegation operations
  • Update golden hex in TestWitnessUpdateGoldenHex (131 → 110 bytes)

Verification

$ make test   # all green

Tested with a live witness signing key update on Steem mainnet —
transaction a840f7c70d3549ac53fcd83ca5740f2092364b03 accepted at
block 107590219.

ety001 added 2 commits July 7, 2026 18:09
Steem's public_key_type serializes as a fixed 33-byte blob (1 byte format
+ 32 bytes key data), not as a varint-prefixed string. The reflection
encoder was treating BlockSigningKey/MemoKey as plain strings, producing
54 bytes instead of 33.

Fix:
- Add steem:"pubkey" struct tag for public_key_type string fields
- Add encodePubKey() to encoder: parses STM... string via wif.PublicKey
  and writes the 33-byte compressed binary
- Tag all MemoKey and BlockSigningKey fields in protocol/operations.go
- Update golden hex in TestWitnessUpdateGoldenHex (131→110 bytes)
Add byte-exact golden hex serialization tests for every operation that
contains a public_key_type field (memo_key, block_signing_key):

- TestWitnessUpdateSerialization (block_signing_key)
- TestAccountCreateSerialization (memo_key + plain authorities)
- TestAccountUpdateSerialization (memo_key + optional nil authorities)
- TestAccountUpdate2Serialization (memo_key + optional + extensions)
- TestCreateClaimedAccountSerialization (memo_key + plain + extensions)
- TestAccountCreateWithDelegationSerialization (memo_key + delegation)

Each test hardcodes the expected hex and compares byte-for-byte. The
golden hex values were generated from the fixed encoder and verified
against Steem's C++ FC_REFLECT serialization format.

Also fixes three operations where steem:"pubkey" tag was missing
(CreateClaimedAccount, AccountCreateWithDelegation, AccountUpdate2).
@kuny0707
kuny0707 merged commit 6085934 into master Jul 7, 2026
3 checks passed
@ety001
ety001 deleted the fix/pubkey-serialization branch July 7, 2026 23:08
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.

2 participants