Skip to content

Fix KMS-005: Convert AckData to use addresses for both player and dealer - #46

Merged
mcclurejt merged 10 commits into
masterfrom
mcclurejt/fix/kms-005
Mar 12, 2026
Merged

Fix KMS-005: Convert AckData to use addresses for both player and dealer#46
mcclurejt merged 10 commits into
masterfrom
mcclurejt/fix/kms-005

Conversation

@mcclurejt

@mcclurejt mcclurejt commented Mar 3, 2026

Copy link
Copy Markdown
Contributor
  • adds test to ensure ProveEquivocation does not always revert

@claude

claude Bot commented Mar 3, 2026

Copy link
Copy Markdown

Claude finished @mcclurejt's task in 3m 56s —— View job


Code Review — Fix KMS-005: AckData Uses Addresses for Player and Dealer

  • Gather context and understand the PR
  • Review core changes (types, crypto, merkle)
  • Review DKG/reshare protocol changes
  • Review node changes
  • Review tests and test utilities
  • Review contract changes
  • Compile final review

Summary

This PR correctly replaces the int64 node ID based identifiers in AckData with common.Address values throughout — the right fix for KMS-005. The consolidation of CreateAcknowledgement into pkg/crypto and the epoch encoding fix (32 bytes → 8 bytes) from prior review feedback are both confirmed and correct. Several issues remain.


Bugs / Issues

1. CreateTestAcknowledgements still uses synthetic addresses (pkg/testutil/helpers.go:52)

The function signature still accepts dealerID int64 and converts it with common.BigToAddress(new(big.Int).SetInt64(dealerID)), producing addresses like 0x0000…0063. All integration test callsites (e.g. merkle_ack_integration_test.go:111) continue to pass raw integers. See inline comment for a suggested fix. Fix this →

2. Latent LeafIndex = 0 bug in VerifyOperatorBroadcast (pkg/node/node.go:2045)

proof := &merkle.MerkleProof{
    Leaf:  leafHash,
    Proof: broadcast.MerkleProof,
    // LeafIndex defaults to 0
}

When Phase 7 wires in the actual merkle.VerifyProof call, this will silently pass only for the operator whose address sorts first in SortAcknowledgements, and fail for everyone else. The correct index must be found by locating n.OperatorAddress in the sorted slice before constructing the proof struct. This is already filed as an inline comment. Fix this →

3. Merkle proof is not cryptographically verified (pkg/node/node.go:2053-2055)

if len(proof.Proof) == 0 {
    return fmt.Errorf("merkle proof is empty")
}

The proof is only checked for non-emptiness, not verified against the root. The comment says "Phase 7 will add on-chain root from contract" — that's fine as a phased approach, but the function should be clearly marked incomplete (e.g. a TODO(phase-7) comment) so it doesn't get shipped as-is. Without this check, a dealer can send any non-nil proof and pass verification.


Code Quality

4. Field-order asymmetry between signing message and merkle leaf

buildAcknowledgementSigningMessage packs dealer || player || epoch || ..., while HashAcknowledgementForMerkle packs player || dealer || epoch || .... The comment in types.go:82 documents the signing order; the Solidity contract documents the leaf order. Both are correct for their purpose. A short inline comment in each function (e.g. "Note: dealer precedes player here, matching types.Acknowledgement.Signature doc") would prevent future confusion for contributors implementing new verification paths.

5. SendDKGShare and SendReshareShare are near-identical (pkg/transport/client.go)

The two functions differ only in the path string (/dkg/share vs /reshare/share) and SessionTimestamp field source, but share 30+ lines of retry logic. Not a blocker, but extracting a private sendShare(path string, ...) helper would improve maintainability. Fix this →


Testing

6. Integration test still passes synthetic dealer address (internal/tests/integration/merkle_ack_integration_test.go:111)

acks := testutil.CreateTestAcknowledgements(t, 3, 5, 99) // epoch=5, dealerID=99

Blocked on issue #1 above.

7. TestAcknowledgementSorting does not verify ordering correctness (pkg/merkle/merkle_test.go:156)

The test verifies determinism across two calls to SortAcknowledgements, but never asserts the actual sort order is ascending. Two calls of an identity function would also pass. A simple assertion like require.True(t, sorted[i].PlayerAddress.Hex() <= sorted[i+1].PlayerAddress.Hex()) for each consecutive pair would catch regressions. Fix this →


Positives

  • The epoch encoding fix (8 bytes, matching abi.encodePacked(uint64)) is confirmed correct.
  • HashAcknowledgement wrapper has been eliminated; crypto.HashAcknowledgementForMerkle is now the single canonical implementation used everywhere.
  • CreateAcknowledgement is canonically in pkg/crypto, removing the dkg/reshare duplication.
  • The BroadcastCommitmentsWithProofs fix in transport/client.go (sorting acks before iterating to find the correct leafIndex) is correct and important — without this, the leaf index would have been wrong for any non-trivial sort order.
  • The new test_ProveEquivocation_Success Solidity test correctly exercises the full equivocation proof path end-to-end, confirming the on-chain encoding and OZ merkle verification work as expected.

@mcclurejt mcclurejt changed the title Fixes KMS-005: Convert address player to uint64 playerID Fixes KMS-005: Convert AckData address player to uint64 playerID Mar 3, 2026
@mcclurejt mcclurejt changed the title Fixes KMS-005: Convert AckData address player to uint64 playerID Fix KMS-005: Convert AckData address player to uint64 playerID Mar 3, 2026
Comment thread pkg/merkle/merkle.go Outdated
@mcclurejt
mcclurejt marked this pull request as ready for review March 3, 2026 18:30
Comment thread pkg/merkle/merkle.go Outdated
@mcclurejt
mcclurejt force-pushed the mcclurejt/fix/kms-005 branch from 8f775a3 to ae78778 Compare March 3, 2026 19:37
@mcclurejt mcclurejt changed the title Fix KMS-005: Convert AckData address player to uint64 playerID Fix KMS-005: Convert AckData to use addresses for both player and dealer Mar 3, 2026
Comment thread pkg/merkle/merkle.go
Comment thread pkg/merkle/merkle.go Outdated
Comment thread contracts/test/EigenKMSCommitmentRegistry.t.sol
Comment thread pkg/crypto/bls.go
Comment thread pkg/reshare/reshare.go Outdated
Comment thread pkg/testutil/helpers.go
@mcclurejt
mcclurejt force-pushed the mcclurejt/fix/kms-005 branch from 9184d2f to 03de1ed Compare March 3, 2026 20:03
Comment thread pkg/testutil/helpers.go
Comment thread pkg/testutil/helpers.go Outdated
Comment thread pkg/node/node.go
Comment thread pkg/node/node.go Outdated
seanmcgary
seanmcgary previously approved these changes Mar 5, 2026
@seanmcgary
seanmcgary requested a review from anupsv March 5, 2026 15:50
@mcclurejt
mcclurejt changed the base branch from master to fixing-zero-commitment-new-op March 10, 2026 22:45
@mcclurejt
mcclurejt changed the base branch from fixing-zero-commitment-new-op to master March 10, 2026 22:56
@mcclurejt
mcclurejt dismissed seanmcgary’s stale review March 10, 2026 22:56

The base branch was changed.

@mcclurejt
mcclurejt force-pushed the mcclurejt/fix/kms-005 branch 2 times, most recently from f673608 to 899e2f6 Compare March 10, 2026 23:11
… AckData

The AckData struct used `address player` but `uint64 dealerID` in Solidity,
while Go used `int64 PlayerID`/`DealerID` with mismatched byte encoding for
epoch (32 bytes vs 8 bytes). This caused proveEquivocation() to always revert
with Ack1Invalid, making it impossible to slash a malicious operator.

- Change `uint64 dealerID` to `address dealer` in Solidity AckData struct
- Change Go Acknowledgement fields from int64 IDs to common.Address values
- Fix epoch encoding to use 8-byte uint64 (matching Solidity) in Go hash functions
- Update merkle leaf hash: keccak256(player_20B || dealer_20B || epoch_8B || shareHash || commitmentHash)
- Update ABI binding, node signing, transport routing, and persistence to use addresses
- Add happy-path test for proveEquivocation that constructs a valid merkle proof

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mcclurejt and others added 8 commits March 12, 2026 12:10
…dgementForMerkle

Remove the duplicate hash implementation in pkg/merkle and delegate to the
canonical crypto.HashAcknowledgementForMerkle to prevent the two from
diverging silently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dgementMerkleTree

pkg/reshare had byte-for-byte copies of both functions from pkg/dkg.
Delegate to the canonical dkg implementations, following the same pattern
used for merkle.HashAcknowledgement -> crypto.HashAcknowledgementForMerkle.

Also replace the local threshold() helper in reshare_fuzz_test.go with
dkg.CalculateThreshold to avoid the same formula existing in two places.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…AcknowledgementForMerkle directly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nical implementation

Remove the copies from pkg/dkg and pkg/reshare and update all callers
(node.go, tests, integration tests) to use crypto.CreateAcknowledgement directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update comment to say "by player address" instead of "by player ID"
to match the actual sort key used in SortAcknowledgements.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mcclurejt
mcclurejt force-pushed the mcclurejt/fix/kms-005 branch from 899e2f6 to 2874e89 Compare March 12, 2026 17:43
1. Fix epoch encoding mismatch in HashAcknowledgementForMerkle: use 8-byte
   uint64 encoding to match Solidity's abi.encodePacked(uint64), not 32-byte
   uint256. This was causing Go-computed merkle leaves to never match on-chain
   verification in proveEquivocation.

2. Fix port string bug in CreateTestOperators: string(rune(9000+i)) produces
   Unicode characters, not decimal port strings. Use fmt.Sprintf instead.

3. Remove unused senderNodeID parameter from verifyAcknowledgement. The
   function validates using PlayerAddress/DealerAddress from the ack struct
   and no longer needs the int64 sender ID.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread pkg/testutil/helpers.go
@mcclurejt
mcclurejt merged commit 5024f3a into master Mar 12, 2026
16 checks passed
@mcclurejt
mcclurejt deleted the mcclurejt/fix/kms-005 branch March 12, 2026 18:47
@anupsv

anupsv commented Mar 12, 2026

Copy link
Copy Markdown
Contributor

lgtm

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