Skip to content

New DKG flow#115

Open
JesseAbram wants to merge 12 commits into
jesse/Orbis-modulefrom
new-dkg-flow
Open

New DKG flow#115
JesseAbram wants to merge 12 commits into
jesse/Orbis-modulefrom
new-dkg-flow

Conversation

@JesseAbram
Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 864150be-3f63-41a5-9d7c-03fef390fb09

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 25, 2026

Codecov Report

❌ Patch coverage is 68.26087% with 73 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.68%. Comparing base (ad1a75a) to head (657081a).

Files with missing lines Patch % Lines
x/orbis/keeper/validation.go 46.66% 15 Missing and 9 partials ⚠️
x/orbis/keeper/msg_server.go 79.51% 7 Missing and 10 partials ⚠️
x/orbis/types/message_create_ring.go 0.00% 11 Missing ⚠️
x/orbis/types/message_finalize_ring.go 0.00% 8 Missing ⚠️
x/orbis/keeper/acp.go 84.61% 3 Missing and 3 partials ⚠️
x/orbis/keeper/grpc_query.go 0.00% 5 Missing ⚠️
x/orbis/types/message_store_document.go 0.00% 1 Missing ⚠️
x/orbis/types/message_store_key_derivation.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@                  Coverage Diff                   @@
##           jesse/Orbis-module     #115      +/-   ##
======================================================
+ Coverage               48.16%   48.68%   +0.52%     
======================================================
  Files                     301      302       +1     
  Lines                   17423    17471      +48     
======================================================
+ Hits                     8392     8506     +114     
+ Misses                   8174     8089      -85     
- Partials                  857      876      +19     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JesseAbram JesseAbram marked this pull request as ready for review May 29, 2026 18:33
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
x/orbis/keeper/reshare_sign_bytes_test.go (1)

40-72: ⚡ Quick win

Consider a negative case to guard the canonicalization.

The test only asserts equality for canonically-identical states. An implementation that over-collapses (or returns a constant) would still pass. Adding an assertion that a genuine sign-state change (e.g., a different Threshold or XNewThreshold) yields different bytes would meaningfully harden this test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@x/orbis/keeper/reshare_sign_bytes_test.go` around lines 40 - 72, Add a
negative-case assertion to ensure the canonicalization isn't collapsing distinct
states: create a variant of the existing test state (use
ringForReshareFinalization and ringReshareFinalizeSignBytes) but modify a
meaningful field such as Threshold or XNewThreshold (e.g., change Threshold from
2 to 3 or NewThreshold from 1 to 2), compute its finalized sign bytes via
ringReshareFinalizeSignBytes and assert that these bytes are not equal to the
original signBytes (use require.NotEqual) to verify different sign-states
produce different canonical bytes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/sourcehub/orbis/query.pulsar.go`:
- Line 7405: The protobuf field number 1 was reused for Pagination (Pagination
*v1beta1.PageRequest `protobuf:"bytes,1...`) after removing namespace which
breaks wire compatibility; update the protobuf definition so Pagination (and the
related id/pagination fields) use the original field number 2 instead of 1, and
explicitly reserve the removed namespace tag 1 (e.g., add a reserved 1 entry) in
the .proto to prevent reuse; apply the same change for the other occurrences
referenced (the other Pagination/id fields at the indicated locations) so no
removed tag is reassigned.

In `@proto/sourcehub/orbis/tx.proto`:
- Around line 61-66: The PR incorrectly claims a protobuf compile blocker for
MsgFinalizeRing — remove that claim and instead add non-empty doc comments for
the messages required by buf lint: MsgFinalizeRing, MsgFinalizeRingResponse,
MsgFinalizeRingReshareByThresholdSignature, and
MsgFinalizeRingReshareByThresholdSignatureResponse; ensure each message has a
short descriptive comment above it, and verify that numeric field tags for
MsgCreateRing, RingReshareFinalizeSignDoc, MsgStoreDocument, and
MsgStoreKeyDerivation were not changed (restore original tags if they were) to
avoid a public API break.

In `@x/orbis/keeper/msg_server.go`:
- Around line 186-192: Update UpdateRingByAcp flow to enforce that every key in
msg.NewPeerNodeKeys has registered node info via k.GetNodeInfo(...) before
accepting/copying them (similar invariant enforced in CreateRing); specifically,
inside the UpdateRingByAcp handler call validateRingUpdate/validateRing as
before but add an existence check: iterate msg.NewPeerNodeKeys and call
k.GetNodeInfo(ctx, pkHex) for each, returning an error if any are missing, then
proceed to set ring.NewPeerNodeKeys = append(...). Also update FinalizeRing
authorization to consult k.GetNodeInfo(...) when validating signerPublicKeyHex
against ring.PeerNodeKeys (or otherwise fail) so unregistered keys cannot
confirm; reference functions/paths: UpdateRingByAcp, validateRingUpdate,
validateRing, FinalizeRing, CreateRing, and k.GetNodeInfo.
- Around line 119-130: The handler currently deletes the ring then returns
types.ErrRingPkConflict which causes KV writes to be rolled back; change the
conflict branch so after emitting EventRingDeleted and calling k.DeleteRing you
do NOT return types.ErrRingPkConflict but instead return a successful response
(i.e., a non-error result for the Msg confirm handler) so the deletion persists.
Update the branch that iterates ring.Confirmations (checking c.RingPk vs
msg.RingPk), the ctx.EventManager().EmitTypedEvent(types.EventRingDeleted) call,
and k.DeleteRing invocation to return a successful MsgConfirm response (and nil
error) rather than ErrRingPkConflict.

In `@x/orbis/keeper/validation.go`:
- Around line 66-76: The current guard only compares new_peer_node_keys vs
newThreshold when both are provided, allowing a threshold-only reshare to set
newThreshold larger than the existing committee; add a check in the validation
path (same function where newThreshold and newPeerNodeKeys are inspected) that
if newPeerNodeKeys is empty and newThreshold != nil you validate *newThreshold
<= uint32(len(existing.PeerNodeKeys)) and return
errorsmod.Wrapf(types.ErrInvalidRing, "new_threshold (%d) cannot exceed existing
committee size (%d)", *newThreshold, len(existing.PeerNodeKeys)) when it
violates this; this prevents ringForReshareFinalization/validateRing from later
rejecting the change and leaving ErrReshareInProgress.

---

Nitpick comments:
In `@x/orbis/keeper/reshare_sign_bytes_test.go`:
- Around line 40-72: Add a negative-case assertion to ensure the
canonicalization isn't collapsing distinct states: create a variant of the
existing test state (use ringForReshareFinalization and
ringReshareFinalizeSignBytes) but modify a meaningful field such as Threshold or
XNewThreshold (e.g., change Threshold from 2 to 3 or NewThreshold from 1 to 2),
compute its finalized sign bytes via ringReshareFinalizeSignBytes and assert
that these bytes are not equal to the original signBytes (use require.NotEqual)
to verify different sign-states produce different canonical bytes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b96f86cd-f5da-4e62-b6e8-e817de93e980

📥 Commits

Reviewing files that changed from the base of the PR and between ad1a75a and fc81b8a.

⛔ Files ignored due to path filters (13)
  • api/sourcehub/orbis/document.pb.go is excluded by !**/*.pb.go
  • api/sourcehub/orbis/query_grpc.pb.go is excluded by !**/*.pb.go
  • api/sourcehub/orbis/ring.pb.go is excluded by !**/*.pb.go
  • api/sourcehub/orbis/tx.pb.go is excluded by !**/*.pb.go
  • api/sourcehub/orbis/tx_grpc.pb.go is excluded by !**/*.pb.go
  • x/orbis/types/document.pb.go is excluded by !**/*.pb.go
  • x/orbis/types/events.pb.go is excluded by !**/*.pb.go
  • x/orbis/types/key_derivation.pb.go is excluded by !**/*.pb.go
  • x/orbis/types/node_info.pb.go is excluded by !**/*.pb.go
  • x/orbis/types/query.pb.go is excluded by !**/*.pb.go
  • x/orbis/types/query.pb.gw.go is excluded by !**/*.pb.gw.go
  • x/orbis/types/ring.pb.go is excluded by !**/*.pb.go
  • x/orbis/types/tx.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (30)
  • api/sourcehub/orbis/events.pulsar.go
  • api/sourcehub/orbis/key_derivation.pulsar.go
  • api/sourcehub/orbis/node_info.pulsar.go
  • api/sourcehub/orbis/query.pulsar.go
  • proto/sourcehub/orbis/document.proto
  • proto/sourcehub/orbis/events.proto
  • proto/sourcehub/orbis/key_derivation.proto
  • proto/sourcehub/orbis/node_info.proto
  • proto/sourcehub/orbis/query.proto
  • proto/sourcehub/orbis/ring.proto
  • proto/sourcehub/orbis/tx.proto
  • x/orbis/keeper/acp.go
  • x/orbis/keeper/grpc_query.go
  • x/orbis/keeper/keeper.go
  • x/orbis/keeper/msg_server.go
  • x/orbis/keeper/msg_server_test.go
  • x/orbis/keeper/optional.go
  • x/orbis/keeper/reshare_sign_bytes.go
  • x/orbis/keeper/reshare_sign_bytes_test.go
  • x/orbis/keeper/store.go
  • x/orbis/keeper/validation.go
  • x/orbis/module/autocli.go
  • x/orbis/types/acp.go
  • x/orbis/types/errors.go
  • x/orbis/types/keys.go
  • x/orbis/types/keys_test.go
  • x/orbis/types/message_create_ring.go
  • x/orbis/types/message_finalize_ring.go
  • x/orbis/types/message_store_document.go
  • x/orbis/types/message_store_key_derivation.go
💤 Files with no reviewable changes (2)
  • x/orbis/types/keys_test.go
  • x/orbis/keeper/keeper.go
📜 Review details
🧰 Additional context used
🪛 Buf (1.69.0)
proto/sourcehub/orbis/query.proto

[error] 31-31: cannot find google.api.http in this scope

(COMPILE)


[error] 36-36: cannot find google.api.http in this scope

(COMPILE)


[error] 41-41: cannot find google.api.http in this scope

(COMPILE)


[error] 46-46: cannot find google.api.http in this scope

(COMPILE)


[error] 51-51: cannot find google.api.http in this scope

(COMPILE)


[error] 80-80: cannot find cosmos.base.query.v1beta1.PageRequest in this scope

(COMPILE)


[error] 96-96: cannot find Document in this scope

(COMPILE)


[error] 100-100: cannot find cosmos.base.query.v1beta1.PageRequest in this scope

(COMPILE)


[error] 116-116: cannot find KeyDerivation in this scope

(COMPILE)


[error] 120-120: cannot find cosmos.base.query.v1beta1.PageRequest in this scope

(COMPILE)

proto/sourcehub/orbis/tx.proto

[error] 62-62: cannot find cosmos.msg.v1.signer in this scope

(COMPILE)


[error] 71-71: cannot find cosmos.msg.v1.signer in this scope

(COMPILE)


[error] 115-115: cannot find cosmos.msg.v1.signer in this scope

(COMPILE)


[error] 165-165: cannot find cosmos.msg.v1.signer in this scope

(COMPILE)

🔇 Additional comments (26)
x/orbis/keeper/msg_server_test.go (1)

54-177: LGTM!

Also applies to: 179-538, 540-616, 618-808, 810-837, 839-1017, 1019-1093

proto/sourcehub/orbis/events.proto (1)

9-10: LGTM!

Also applies to: 15-16, 21-22, 27-28, 43-47

proto/sourcehub/orbis/key_derivation.proto (1)

9-14: Confirm no persisted/consumed KeyDerivation data relies on the old field numbers.

Renumbering existing tags (creator_did 3→2, ring_id 4→3, …) changes the wire format. Any previously serialized KeyDerivation records or external decoders would misread these fields. If this module is already deployed or has downstream consumers, prefer reserving the removed tag and keeping stable numbers instead of shifting:

message KeyDerivation {
  string id = 1;
  reserved 2; // formerly namespace
  string creator_did = 3;
  string ring_id = 4;
  string derivation = 5;
  string policy_id = 6;
  string resource = 7;
  string permission = 8;
}

If the module is still pre-release with no persisted state or consumers, the renumbering is fine to keep.

proto/sourcehub/orbis/node_info.proto (1)

10-10: LGTM!

proto/sourcehub/orbis/query.proto (1)

29-52: LGTM!

Also applies to: 79-120

x/orbis/types/message_create_ring.go (1)

11-34: LGTM!

x/orbis/types/message_finalize_ring.go (1)

9-22: LGTM!

x/orbis/types/message_store_document.go (1)

11-21: LGTM!

x/orbis/types/message_store_key_derivation.go (1)

11-20: LGTM!

proto/sourcehub/orbis/document.proto (1)

9-19: 🏗️ Heavy lift

Don’t renumber Document fields here; current tags are already stable.

proto/sourcehub/orbis/document.proto currently defines creator_did = 2, ring_id = 3, … timestamp = 10 with no namespace field (and no reserved declarations). The generated x/orbis/types/document.pb.go matches these same tag numbers, so the proposed direction that reserves field 2 and renumbers would actually change wire tags (e.g., creator_did 2→3) and risk incompatibility.

			> Likely an incorrect or invalid review comment.
proto/sourcehub/orbis/ring.proto (1)

9-20: 🏗️ Heavy lift

Ring field numbers are already preserved; the claimed wire-format tag renumbering doesn’t match this schema.

proto/sourcehub/orbis/ring.proto currently defines Ring with tags creator_did=2, ring_pk=3, peer_node_keys=4, threshold=5, new_peer_node_keys=6, new_threshold=7, pss_interval=8, block_number_nonce=9, policy_id=10, and confirmations=11, with no namespace field in Ring. The protobuf compatibility break described (e.g., old tag 3/4 decoding into different fields) is not supported for this message as written.

			> Likely an incorrect or invalid review comment.
proto/sourcehub/orbis/tx.proto (1)

45-55: 🏗️ Heavy lift

Preserve protobuf field numbers in public tx messages when removing namespace.

proto/sourcehub/orbis/tx.proto no longer contains a namespace field in MsgCreateRing (45-55), RingReshareFinalizeSignDoc (93-101), or MsgStoreDocument/MsgStoreKeyDerivation (114-141), and there are no reserved entries to keep old field tags unused. If namespace was removed previously, the old field number(s) must be left unused/reserved and the remaining fields must not be compacted/renumbered, since protobuf wire compatibility (including signed tx payloads) is driven by field numbers.

api/sourcehub/orbis/key_derivation.pulsar.go (1)

838-844: 🏗️ Heavy lift

Re-evaluate KeyDerivation wire-compatibility claim (no namespace field in current schema).

proto/sourcehub/orbis/key_derivation.proto defines KeyDerivation as id=1, creator_did=2, ring_id=3, derivation=4, policy_id=5, resource=6, permission=7, and api/sourcehub/orbis/key_derivation.pulsar.go matches those field numbers. This repo’s current proto/generated code contains no namespace field, so the “fields shifted down after removing namespace” premise isn’t supported here. The compatibility impact for already-persisted KeyDerivation records must be checked against the proto used by the previously deployed/encoded data; only if an earlier release actually had a namespace field number should it be reserved in the source proto and regeneration performed.

x/orbis/keeper/acp.go (1)

13-72: LGTM!

x/orbis/keeper/validation.go (1)

12-52: LGTM!

Also applies to: 81-177

x/orbis/types/acp.go (1)

1-10: LGTM!

x/orbis/types/errors.go (1)

28-34: LGTM!

x/orbis/module/autocli.go (1)

25-43: LGTM!

Also applies to: 60-62, 79-87

x/orbis/keeper/msg_server.go (2)

28-81: LGTM!


215-256: LGTM!

Also applies to: 258-308, 310-382, 406-450

x/orbis/keeper/grpc_query.go (1)

41-61: LGTM!

Also applies to: 63-77, 79-99, 101-115, 130-150

x/orbis/keeper/store.go (1)

33-45: LGTM!

Also applies to: 47-65, 75-93

x/orbis/types/keys.go (2)

42-73: LGTM!


31-39: Clarify intended semantics for peer-node key ordering vs. ring ID and reshare signing

GenerateRingID hashes peerNodeKeys in the caller-provided order (x/orbis/types/keys.go), and validateRing only enforces uniqueness/format (x/orbis/keeper/validation.go)—so the same peer set in a different order can produce a different ringID and bypass the ErrRingAlreadyExists check (x/orbis/keeper/msg_server.go). Meanwhile, ringReshareSignState sorts PeerNodeKeys/NewPeerNodeKeys before hashing sign state (x/orbis/keeper/reshare_sign_bytes.go), making reshare sign-state order-insensitive.

Confirm whether peer ordering is semantically meaningful (e.g. share/committee index assignment):

  • If not meaningful, GenerateRingID should canonicalize order too.
  • If meaningful, sorting in ringReshareSignState should be removed or the index mapping should be encoded in the sign state/hash.
x/orbis/keeper/optional.go (1)

13-19: LGTM!

x/orbis/keeper/reshare_sign_bytes.go (1)

12-77: Ensure off-chain threshold signers match the updated ring reshare sign-bytes

  • ringReshareFinalizeSignBytes now signs a RingReshareFinalizeSignDoc where CurrentRingSha256/FinalizedRingSha256 are sha256 of the canonical RingReshareSignState (with PeerNodeKeys/NewPeerNodeKeys sorted).
  • RingReshareFinalizeSignDoc in this repo has no Namespace field; external signers must reproduce the exact protobuf-marshaled bytes of the new doc.
  • In-repo tests cover the new construction, but the external/off-chain signer code is not present here—needs manual lockstep update.


Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Pagination *v1beta1.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"`
Pagination *v1beta1.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"`
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Avoid reusing removed protobuf field number 1 (wire compatibility break).

These requests now reuse tag 1 for different fields after removing namespace. That is a breaking protobuf change: older payloads can be misdecoded (namespace interpreted as id) or fail decode (namespace parsed as PageRequest). Keep existing field numbers (id/pagination as 2) and reserve removed namespace = 1 in the source .proto definitions.

Also applies to: 7483-7483, 7553-7553, 7631-7631, 7701-7701

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/sourcehub/orbis/query.pulsar.go` at line 7405, The protobuf field number
1 was reused for Pagination (Pagination *v1beta1.PageRequest
`protobuf:"bytes,1...`) after removing namespace which breaks wire
compatibility; update the protobuf definition so Pagination (and the related
id/pagination fields) use the original field number 2 instead of 1, and
explicitly reserve the removed namespace tag 1 (e.g., add a reserved 1 entry) in
the .proto to prevent reuse; apply the same change for the other occurrences
referenced (the other Pagination/id fields at the indicated locations) so no
removed tag is reassigned.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not live yet no need for backwards compatability

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JesseAbram, got it — if this API/schema hasn’t gone live yet, then there’s no backwards-compatibility requirement here. Reusing the removed namespace tag for the new id/pagination fields is fine in that context, and this shouldn’t block the PR.

🐇💭

Comment on lines +61 to +66
message MsgFinalizeRing {
option (cosmos.msg.v1.signer) = "creator";
string creator = 1;
string ring_id = 2;
string ring_pk = 3;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="proto/sourcehub/orbis/tx.proto"

echo "== tx.proto imports + MsgFinalizeRing (lines ~50-90) =="
nl -ba "$FILE" | sed -n '1,120p'

echo
echo "== Search for cosmos.msg.v1.signer usage in repo =="
rg -n "cosmos\.msg\.v1\.signer" -S .

echo
echo "== Show tx.proto git diff hunks for the mentioned messages =="
git diff -U5 -- "$FILE" | sed -n '/MsgFinalizeRing/,+40p'
echo "----"
git diff -U5 -- "$FILE" | sed -n '/MsgCreateRing/,+80p'
echo "----"
git diff -U5 -- "$FILE" | sed -n '/RingReshareFinalizeSignDoc/,+120p'
echo "----"
git diff -U5 -- "$FILE" | sed -n '/MsgStoreDocument/,+120p'
echo "----"
git diff -U5 -- "$FILE" | sed -n '/MsgStoreKeyDerivation/,+120p'

Repository: sourcenetwork/sourcehub

Length of output: 184


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="proto/sourcehub/orbis/tx.proto"

echo "== Show tx.proto imports + MsgFinalizeRing context =="
awk 'NR>=1 && NR<=140 {printf "%d:%s\n", NR, $0}' "$FILE"

echo
echo "== Search for cosmos.msg.v1.signer usage in repo =="
rg -n "cosmos\.msg\.v1\.signer" -S . || true

echo
echo "== Show git diff hunks for the mentioned messages (if any) =="
git diff -U5 -- "$FILE" | sed -n '1,240p' || true
echo "----"
git diff -U5 -- "$FILE" | rg -n "(MsgFinalizeRing|MsgCreateRing|RingReshareFinalizeSignDoc|MsgStoreDocument|MsgStoreKeyDerivation)" -n || true

Repository: sourcenetwork/sourcehub

Length of output: 8367


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== List buf config files =="
fd -t f "buf.*(ya?ml)" . | head -n 50 || true

echo
echo "== Search buf config for cosmos proto modules/extensions =="
rg -n "buf\.build|cosmos\/msg\/v1\/msg\.proto|cosmos\.msg\.v1\.signer|module:" -S . || true

echo
echo "== Search for compilation/CI scripts that might mention signer resolution =="
fd -t f "(Makefile|CI*|*.sh|*.yml|*.yaml)" . | head -n 200 || true
rg -n "buf (build|lint|generate|check)|buf\.lock|protovalidate|protoc|signer" -S . || true

Repository: sourcenetwork/sourcehub

Length of output: 50878


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== proto/buf.yaml =="
sed -n '1,200p' proto/buf.yaml

echo
echo "== proto/buf.work.yaml =="
sed -n '1,200p' proto/buf.work.yaml

echo
echo "== proto/buf.gen.*.yaml (summaries) =="
for f in proto/buf.gen.*.yaml; do
  echo "--- $f ---"
  sed -n '1,120p' "$f"
done

echo
echo "== Check if buf CLI is available =="
command -v buf >/dev/null && buf --version || echo "buf not found"

echo
echo "== Locate cosmos/msg/v1/msg.proto in local cache (GOPATH pkg/mod) =="
GOPATH="$(go env GOPATH 2>/dev/null || true)"
if [ -n "$GOPATH" ]; then
  echo "GOPATH=$GOPATH"
  # find proto file candidates
  rg -n "option \\(cosmos\\.msg\\.v1\\.signer\\)" -S "$GOPATH/pkg/mod" --no-mmap --hidden --glob '*.proto' --glob '*msg.proto' 2>/dev/null | head -n 20 || true
  # find any file containing the signer extension symbol
  rg -n "cosmos\\.msg\\.v1\\.signer" -S "$GOPATH/pkg/mod" --no-mmap --hidden 2>/dev/null | head -n 50 || true
else
  echo "go not available / GOPATH not found"
fi

Repository: sourcenetwork/sourcehub

Length of output: 699


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== root buf.work.yaml =="
[ -f buf.work.yaml ] && sed -n '1,200p' buf.work.yaml || echo "buf.work.yaml not found"

echo
echo "== Check buf CLI =="
command -v buf >/dev/null && buf --version || echo "buf not found"

echo
echo "== Check Go toolchain (for module/proto cache search) =="
command -v go >/dev/null && go version || echo "go not found"

echo
echo "== Locate cosmos/msg/v1/msg.proto in buf module cache (protodeps) if present =="
# Try protodeps cache locations used by buf; ignore if missing.
for d in "${HOME}/.cache/buf" "${HOME}/.buf" "${HOME}/.local/share/buf" "/tmp"; do
  if [ -d "$d" ]; then
    echo "-- search base: $d --"
    rg -n "message Msg" "$d" >/dev/null 2>&1 || true
  fi
done

echo
echo "== Directly search for the signer extension definition in local filesystem =="
# This is best-effort; keep output small.
rg -n "extension\\s+google\\.protobuf\\.MessageOptions\\s*\\{[[:space:][:graph:]]*signer" -S "$HOME" 2>/dev/null | head -n 20 || true
rg -n "cosmos\\.msg\\.v1\\.signer" -S "$HOME" 2>/dev/null | head -n 20 || true

echo
echo "== If buf is available: run buf lint (output filtered to signer error) =="
if command -v buf >/dev/null; then
  # Use workspace file if present; otherwise default.
  # Filter output to lines mentioning "signer" or the reported file/line.
  buf lint --error-format=compact 2>&1 | rg -n "tx\.proto:6[1-9]|cosmos\.msg\.v1\.signer|signer in this scope|MsgFinalizeRing" || true
fi

Repository: sourcenetwork/sourcehub

Length of output: 2836


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== buf build (filter errors relevant to signer / orbis/tx.proto) =="
buf build 2>&1 | rg -n "orbis/tx\.proto|cosmos\.msg\.v1\.signer|cannot find|in this scope|signer" || true

echo
echo "== buf lint (filter errors relevant to signer / orbis/tx.proto) =="
buf lint --error-format=compact 2>&1 | rg -n "orbis/tx\.proto|cosmos\.msg\.v1\.signer|cannot find|in this scope|signer" || true

echo
echo "== git status / diff summary =="
git status --porcelain || true
git diff --stat || true
git diff --name-only || true

Repository: sourcenetwork/sourcehub

Length of output: 236


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== git status =="
git status --porcelain -b || true

echo
echo "== buf build exit code + stderr head =="
set +e
buf build 2> /tmp/buf_build_err.txt
rc=$?
set -e
echo "buf build rc=$rc"
wc -l /tmp/buf_build_err.txt 2>/dev/null || true
head -n 80 /tmp/buf_build_err.txt 2>/dev/null || true
echo "--- last 80 lines ---"
tail -n 80 /tmp/buf_build_err.txt 2>/dev/null || true

echo
echo "== buf lint exit code + stderr head =="
set +e
buf lint --error-format=compact 2> /tmp/buf_lint_err.txt
rc2=$?
set -e
echo "buf lint rc=$rc2"
wc -l /tmp/buf_lint_err.txt 2>/dev/null || true
head -n 80 /tmp/buf_lint_err.txt 2>/dev/null || true
echo "--- last 80 lines ---"
tail -n 80 /tmp/buf_lint_err.txt 2>/dev/null || true

echo
echo "== git diff name-only (if any) =="
git diff --name-only || true
echo
echo "== git diff --stat (if any) =="
git diff --stat || true

Repository: sourcenetwork/sourcehub

Length of output: 2921


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== buf lint (scoped to orbis tx.proto) =="
set +e
buf lint --path proto/sourcehub/orbis/tx.proto 2>&1 | rg -n "MsgFinalizeRing|cosmos\.msg\.v1\.signer|cannot find|in this scope|signer" || true
echo "rc=$?"
set -e

echo
echo "== buf build (scoped to orbis tx.proto) =="
set +e
buf build --path proto/sourcehub/orbis/tx.proto 2>&1 | rg -n "MsgFinalizeRing|cosmos\.msg\.v1\.signer|cannot find|in this scope|signer" || true
echo "rc=$?"
set -e

Repository: sourcenetwork/sourcehub

Length of output: 697


Remove the “MsgFinalizeRing protobuf compile blocker” claim and fix lint docs

  • proto/sourcehub/orbis/tx.proto builds successfully with buf build; (cosmos.msg.v1.signer) is accepted on MsgFinalizeRing (lines 61-66), so there’s no compile-time signer option failure.
  • buf lint requires non-empty documentation comments for MsgFinalizeRing, MsgFinalizeRingResponse, MsgFinalizeRingReshareByThresholdSignature, MsgFinalizeRingReshareByThresholdSignatureResponse (lines 61, 68, 83, 91).
  • If this PR changed numeric field tags for MsgCreateRing, RingReshareFinalizeSignDoc, MsgStoreDocument, or MsgStoreKeyDerivation, keep them stable to avoid a public API break.
🧰 Tools
🪛 Buf (1.69.0)

[error] 62-62: cannot find cosmos.msg.v1.signer in this scope

(COMPILE)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proto/sourcehub/orbis/tx.proto` around lines 61 - 66, The PR incorrectly
claims a protobuf compile blocker for MsgFinalizeRing — remove that claim and
instead add non-empty doc comments for the messages required by buf lint:
MsgFinalizeRing, MsgFinalizeRingResponse,
MsgFinalizeRingReshareByThresholdSignature, and
MsgFinalizeRingReshareByThresholdSignatureResponse; ensure each message has a
short descriptive comment above it, and verify that numeric field tags for
MsgCreateRing, RingReshareFinalizeSignDoc, MsgStoreDocument, and
MsgStoreKeyDerivation were not changed (restore original tags if they were) to
avoid a public API break.

Comment on lines +119 to +130
// Check for a conflicting ring_pk from a prior confirmation by a
// different node. This is a genuine BFT violation — delete the ring.
for _, c := range ring.Confirmations {
if c.RingPk != msg.RingPk {
_ = ctx.EventManager().EmitTypedEvent(&types.EventRingDeleted{
RingId: ring.Id,
Reason: "ring_pk_conflict",
})
k.DeleteRing(goCtx, ring.Id)
return nil, types.ErrRingPkConflict
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In Cosmos SDK v0.50, are state changes (KVStore writes) made inside a message handler rolled back if the handler returns an error?

💡 Result:

Yes, in Cosmos SDK v0.50, state changes (KVStore writes) made inside a message handler are automatically rolled back if the handler returns an error [1]. The Cosmos SDK is designed to ensure atomicity for transaction execution [1]. When a transaction is processed, the state changes are applied to a cached or branched version of the store [1]. If the message handler successfully completes (returns nil error), these changes are committed to the persistent state [2][1]. If the handler returns an error, those pending state changes are discarded, effectively rolling back the operation [1]. This mechanism provides a safety guarantee for developers, ensuring that failed transactions do not leave the chain in a partial or inconsistent state [1]. Note that this error-handling protection applies specifically to message execution and does not extend to other lifecycle hooks like BeginBlocker or EndBlocker, where panics or errors may have different impacts on chain stability [1].

Citations:


Fix ring deletion on ring_pk conflict: returning types.ErrRingPkConflict rolls back the state change in Cosmos SDK v0.50.

In Cosmos SDK v0.50, KVStore writes performed during message execution (cached/brached context) are discarded when the handler returns an error, so k.DeleteRing(goCtx, ring.Id) cannot persist if you return types.ErrRingPkConflict. Make the conflict path return success to commit the deletion.

🐛 Proposed fix: commit the deletion by returning success
 	for _, c := range ring.Confirmations {
 		if c.RingPk != msg.RingPk {
-			_ = ctx.EventManager().EmitTypedEvent(&types.EventRingDeleted{
+			k.DeleteRing(goCtx, ring.Id)
+			if err := ctx.EventManager().EmitTypedEvent(&types.EventRingDeleted{
 				RingId: ring.Id,
 				Reason: "ring_pk_conflict",
-			})
-			k.DeleteRing(goCtx, ring.Id)
-			return nil, types.ErrRingPkConflict
+			}); err != nil {
+				return nil, err
+			}
+			return &types.MsgFinalizeRingResponse{}, nil
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@x/orbis/keeper/msg_server.go` around lines 119 - 130, The handler currently
deletes the ring then returns types.ErrRingPkConflict which causes KV writes to
be rolled back; change the conflict branch so after emitting EventRingDeleted
and calling k.DeleteRing you do NOT return types.ErrRingPkConflict but instead
return a successful response (i.e., a non-error result for the Msg confirm
handler) so the deletion persists. Update the branch that iterates
ring.Confirmations (checking c.RingPk vs msg.RingPk), the
ctx.EventManager().EmitTypedEvent(types.EventRingDeleted) call, and k.DeleteRing
invocation to return a successful MsgConfirm response (and nil error) rather
than ErrRingPkConflict.

Comment on lines +186 to 192
if err := validateRingUpdate(msg.NewPeerNodeKeys, newThreshold, ring); err != nil {
return nil, err
}

if len(msg.NewPeerIds) > 0 {
ring.NewPeerIds = append([]string(nil), msg.NewPeerIds...)
if len(msg.NewPeerNodeKeys) > 0 {
ring.NewPeerNodeKeys = append([]string(nil), msg.NewPeerNodeKeys...)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect validateRingUpdate and whether it checks node info existence for new peer keys.
rg -nP --type=go -C4 'func\s+validateRingUpdate\s*\(' 
# Also check whether GetNodeInfo is referenced from validation.go
rg -nP --type=go -C3 'GetNodeInfo' -g 'x/orbis/keeper/validation.go'

Repository: sourcenetwork/sourcehub

Length of output: 721


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect full validateRingUpdate body
echo "---- x/orbis/keeper/validation.go: validateRingUpdate ----"
nl -ba x/orbis/keeper/validation.go | sed -n '35,160p'

# 2) Search for node-info related checks in validation.go (broaden beyond GetNodeInfo)
echo "---- rg in x/orbis/keeper/validation.go for likely node-info terms ----"
rg -n --hidden --no-ignore --type=go 'NodeInfo|node info|peer node|registered|registered node|GetNodeInfo' x/orbis/keeper/validation.go || true

# 3) Inspect msg_server.go around CreateRing and UpdateRingByAcp to see what invariants are enforced in update path
echo "---- x/orbis/keeper/msg_server.go: around CreateRing & UpdateRingByAcp ----"
nl -ba x/orbis/keeper/msg_server.go | sed -n '1,260p'

# 4) Search msg_server.go for validateRingUpdate call site + any node-info enforcement in update handler
echo "---- rg in msg_server.go for validateRingUpdate and node-info terms ----"
rg -n --type=go 'validateRingUpdate|UpdateRingByAcp|CreateRing|GetNodeInfo|NodeInfo|node info|registered' x/orbis/keeper/msg_server.go

Repository: sourcenetwork/sourcehub

Length of output: 187


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Helper to print numbered lines using awk (since nl isn't available)
print_range() {
  local file="$1"
  local start="$2"
  local end="$3"
  awk -v s="$start" -v e="$end" '{if(NR>=s && NR<=e) printf "%d:%s\n", NR, $0}' "$file"
}

echo "---- validation.go: inspect validateRingUpdate body (w/ line numbers) ----"
print_range x/orbis/keeper/validation.go 35 200

echo "---- validation.go: broader node-info related searches ----"
rg -n --type=go 'node info|NodeInfo|GetNodeInfo|registered|registration|peer node|PeerNodeKeys' x/orbis/keeper/validation.go || true

echo "---- msg_server.go: inspect msg_server around CreateRing & UpdateRingByAcp ----"
print_range x/orbis/keeper/msg_server.go 1 260

echo "---- msg_server.go: search for validateRingUpdate call sites and node-info terms ----"
rg -n --type=go 'validateRingUpdate|UpdateRingByAcp|CreateRing|NodeInfo|GetNodeInfo|node info|registered|registration|peer node|PeerNodeKeys' x/orbis/keeper/msg_server.go || true

Repository: sourcenetwork/sourcehub

Length of output: 17974


🏁 Script executed:

#!/bin/bash
set -euo pipefail
awk 'NR>=1 && NR<=120 {print NR ":" $0}' x/orbis/keeper/validation.go

Repository: sourcenetwork/sourcehub

Length of output: 4240


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "---- locate signerPublicKeyHex ----"
rg -n --type=go 'func\s+signerPublicKeyHex\s*\(' x/orbis/keeper || true

echo "---- locate GetNodeInfo usage in finalize / reshare paths ----"
rg -n --type=go 'GetNodeInfo|FinalizeRing|FinalizeRingReshare' x/orbis/keeper/msg_server.go x/orbis/keeper -S || true

echo "---- show signerPublicKeyHex implementation (if found) ----"
# If signerPublicKeyHex exists, print a small surrounding window
f="$(rg -l --type=go 'func\s+signerPublicKeyHex\s*\(' x/orbis/keeper || true | head -n 1)"
if [ -n "${f:-}" ]; then
  rg -n --type=go -C5 'func\s+signerPublicKeyHex\s*\(' "$f"
fi

Repository: sourcenetwork/sourcehub

Length of output: 7599


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Print full signerPublicKeyHex
awk 'NR>=360 && NR<=430 {print NR ":" $0}' x/orbis/keeper/msg_server.go

# Locate and print verifyThresholdSignatureForRingUpdate
rg -n --type=go 'verifyThresholdSignatureForRingUpdate|ringReshareFinalizeSignBytes|ringReshare' x/orbis/keeper || true
vf="$(rg -l --type=go 'func\s+verifyThresholdSignatureForRingUpdate\s*\(' x/orbis/keeper || true | head -n 1)"
if [ -n "${vf:-}" ]; then
  echo "---- verifyThresholdSignatureForRingUpdate body ----"
  awk 'NR>=1 && NR<=260 {print NR ":" $0}' "$vf"
fi

# Search for GetNodeInfo usage anywhere in keepers (beyond those already found)
echo "---- GetNodeInfo usage across x/orbis/keeper (broad) ----"
rg -n --type=go 'GetNodeInfo' x/orbis/keeper || true

Repository: sourcenetwork/sourcehub

Length of output: 8748


Ensure ring update/reshare new peer node keys require registered node info

  • CreateRing rejects any msg.PeerNodeKeys without k.GetNodeInfo(...).
  • UpdateRingByAcp validates/copies msg.NewPeerNodeKeys via validateRingUpdate + validateRing only (format/uniqueness/threshold); neither path checks GetNodeInfo for the new keys.
  • FinalizeRing authorizes confirmations by comparing the tx signer’s public key (signerPublicKeyHex) to ring.PeerNodeKeys; it does not consult GetNodeInfo, so missing node-info registration alone doesn’t block confirmations in this code path.

Enforce the same node-info existence check for msg.NewPeerNodeKeys during UpdateRingByAcp (or document why this invariant is intentionally not required for reshare-installed peers).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@x/orbis/keeper/msg_server.go` around lines 186 - 192, Update UpdateRingByAcp
flow to enforce that every key in msg.NewPeerNodeKeys has registered node info
via k.GetNodeInfo(...) before accepting/copying them (similar invariant enforced
in CreateRing); specifically, inside the UpdateRingByAcp handler call
validateRingUpdate/validateRing as before but add an existence check: iterate
msg.NewPeerNodeKeys and call k.GetNodeInfo(ctx, pkHex) for each, returning an
error if any are missing, then proceed to set ring.NewPeerNodeKeys =
append(...). Also update FinalizeRing authorization to consult
k.GetNodeInfo(...) when validating signerPublicKeyHex against ring.PeerNodeKeys
(or otherwise fail) so unregistered keys cannot confirm; reference
functions/paths: UpdateRingByAcp, validateRingUpdate, validateRing,
FinalizeRing, CreateRing, and k.GetNodeInfo.

Comment on lines 66 to 76
if newThreshold != nil && *newThreshold < 1 {
return errorsmod.Wrap(types.ErrInvalidRing, "new_threshold must be at least 1")
}
if len(newPeerIDs) > 0 && newThreshold != nil && uint32(len(newPeerIDs)) < *newThreshold {
if len(newPeerNodeKeys) > 0 && newThreshold != nil && uint32(len(newPeerNodeKeys)) < *newThreshold {
return errorsmod.Wrapf(
types.ErrInvalidRing,
"new_peer_ids count (%d) is less than new_threshold (%d)",
len(newPeerIDs),
"new_peer_node_keys count (%d) is less than new_threshold (%d)",
len(newPeerNodeKeys),
*newThreshold,
)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate newThreshold against existing committee size for threshold-only reshares.

The count-vs-threshold guard only fires when both newPeerNodeKeys and newThreshold are provided. A threshold-only reshare (membership unchanged) can set newThreshold greater than len(existing.PeerNodeKeys). This passes here, but at finalization ringForReshareFinalization keeps the existing committee and validateRing then rejects threshold > committee size, leaving the ring unfinalizable and blocked from starting another reshare (ErrReshareInProgress).

🛡️ Proposed guard for threshold-only reshare
 	if len(newPeerNodeKeys) > 0 && newThreshold != nil && uint32(len(newPeerNodeKeys)) < *newThreshold {
 		return errorsmod.Wrapf(
 			types.ErrInvalidRing,
 			"new_peer_node_keys count (%d) is less than new_threshold (%d)",
 			len(newPeerNodeKeys),
 			*newThreshold,
 		)
 	}
+	if len(newPeerNodeKeys) == 0 && newThreshold != nil && uint32(len(existing.PeerNodeKeys)) < *newThreshold {
+		return errorsmod.Wrapf(
+			types.ErrInvalidRing,
+			"new_threshold (%d) exceeds existing committee size (%d)",
+			*newThreshold,
+			len(existing.PeerNodeKeys),
+		)
+	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if newThreshold != nil && *newThreshold < 1 {
return errorsmod.Wrap(types.ErrInvalidRing, "new_threshold must be at least 1")
}
if len(newPeerIDs) > 0 && newThreshold != nil && uint32(len(newPeerIDs)) < *newThreshold {
if len(newPeerNodeKeys) > 0 && newThreshold != nil && uint32(len(newPeerNodeKeys)) < *newThreshold {
return errorsmod.Wrapf(
types.ErrInvalidRing,
"new_peer_ids count (%d) is less than new_threshold (%d)",
len(newPeerIDs),
"new_peer_node_keys count (%d) is less than new_threshold (%d)",
len(newPeerNodeKeys),
*newThreshold,
)
}
if len(newPeerNodeKeys) > 0 && newThreshold != nil && uint32(len(newPeerNodeKeys)) < *newThreshold {
return errorsmod.Wrapf(
types.ErrInvalidRing,
"new_peer_node_keys count (%d) is less than new_threshold (%d)",
len(newPeerNodeKeys),
*newThreshold,
)
}
if len(newPeerNodeKeys) == 0 && newThreshold != nil && uint32(len(existing.PeerNodeKeys)) < *newThreshold {
return errorsmod.Wrapf(
types.ErrInvalidRing,
"new_threshold (%d) exceeds existing committee size (%d)",
*newThreshold,
len(existing.PeerNodeKeys),
)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@x/orbis/keeper/validation.go` around lines 66 - 76, The current guard only
compares new_peer_node_keys vs newThreshold when both are provided, allowing a
threshold-only reshare to set newThreshold larger than the existing committee;
add a check in the validation path (same function where newThreshold and
newPeerNodeKeys are inspected) that if newPeerNodeKeys is empty and newThreshold
!= nil you validate *newThreshold <= uint32(len(existing.PeerNodeKeys)) and
return errorsmod.Wrapf(types.ErrInvalidRing, "new_threshold (%d) cannot exceed
existing committee size (%d)", *newThreshold, len(existing.PeerNodeKeys)) when
it violates this; this prevents ringForReshareFinalization/validateRing from
later rejecting the change and leaving ErrReshareInProgress.

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