Skip to content

feat: go sdk#58

Merged
lightsing merged 48 commits intodev/m2from
feat/go-sdk
Mar 12, 2026
Merged

feat: go sdk#58
lightsing merged 48 commits intodev/m2from
feat/go-sdk

Conversation

@lightsing
Copy link
Copy Markdown
Owner

No description provided.

- Initialize go module as github.com/uts-dot/sdk-go
- Add go-ethereum v1.17.1 dependency
- Add package documentation in doc.go
Add comprehensive error types for the Go SDK:
- ErrorCode type and constants for all error variants
- SDKError struct with Code, Message, and Context
- DecodeError with constructors for all variants (BadMagic, BadVersion,
  LEB128Overflow, BadOpCode, etc.)
- EncodeError with constructors (UsizeOverflow, InvalidUriChar, UriTooLong)
- VerifyError with constructors (NoValue, Pending, BadAttestationTag, Decode)
- EASVerifierError with constructors and IsFatal/ShouldRetry methods
- RemoteError for network/remote operation failures
Define core timestamp types for Go SDK:
- Op type with all operation constants (APPEND, PREPEND, SHA256, etc.)
- Step interface with Op() method
- Concrete step types: AppendStep, PrependStep, ReverseStep, HexlifyStep
- Digest step types: SHA256Step, Keccak256Step, SHA1Step, RIPEMD160Step
- ForkStep with nested Timestamp slice
- AttestationStep wrapping Attestation interface
- Timestamp as []Step slice
- Define DigestOp constants with output sizes (SHA1/RIPEMD160: 20 bytes, SHA256/KECCAK256: 32 bytes)
- Define DigestHeader with Kind and Digest fields
- Define DetachedTimestamp with Header and Timestamp
- Define AttestationStatusKind constants: VALID, INVALID, PENDING, UNKNOWN
- Define AttestationStatus with attestation, status, error, and info fields
- Define VerifyStatus constants: VALID, PARTIAL_VALID, INVALID, PENDING
- Define UpgradeStatus constants: UPGRADED, PENDING, FAILED
- Define UpgradeResult and VerificationResult structs
Add encoder with methods for writing bytes, LEB128 integers, headers,
steps (append/prepend/hash/fork/attestation), and full timestamps.
Add crypto package with hash function wrappers for the UTS protocol.
Includes SHA256 using standard library and Keccak256 using go-ethereum.
Add EthereumClient for connecting to Ethereum RPC endpoints and interacting
with EAS contracts. Includes chain-specific address configuration and
contract call methods for attestation and timestamp retrieval.
- Add VerifyBitcoin function with RPC client interface
- Implement merkle root comparison with byte reversal
- Add comprehensive test coverage for success and error cases
- Create package documentation explaining Bitcoin verification process
- Add VerifyEASAttestation for validating EAS attestations
- Add VerifyEASTimestamped for timestamp-based verification
- Verify schema ID matches UTS schema
- Check attestation is not revocable
- Validate attested hash matches expected digest
- Include comprehensive tests for all verification paths
- Create sdk.go with SDK struct, options, and core methods
- Implement Stamp: generates nonces, builds Merkle tree, submits to calendars
- Implement Verify: executes steps and verifies attestations
- Implement Upgrade: upgrades pending attestations from calendars
- Move errors to separate package to break import cycle
- Update codec package imports to use new errors package
- Add tests for SDK constructor and options (NewSDK, WithCalendars, WithBitcoinRPC, WithEthereumRPC, WithTimeout, WithQuorum, WithNonceSize, WithHashAlgorithm)
- Add tests for Stamp method with mock calendar server
- Add tests for Verify method with various attestation types (pending, bitcoin, unknown)
- Add tests for Upgrade method with mock upgrade server
- Add tests for executeStep helper (AppendStep, PrependStep, ReverseStep, HexlifyStep, SHA256Step, Keccak256Step)
- Add tests for aggregateResult helper
- Add tests for edge cases (context cancellation, invalid URLs, malformed responses)
- Add tests for VerificationResult
- Test coverage: 76.9% for SDK package
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new Go SDK (packages/sdk-go) for the Universal Timestamps (UTS) protocol, including core timestamp types, encoding/decoding, cryptographic primitives, attestation verification, an HTTP-based SDK client, and runnable examples.

Changes:

  • Add uts.SDK with Stamp/Verify/Upgrade workflows, calendar communication, and quorum handling.
  • Implement UTS/OpenTimestamps-compatible codec (encoder/decoder, LEB128), crypto (hashes + Merkle tree), and RPC helpers.
  • Add types + attestation verification logic, documentation, examples, and extensive tests.

Reviewed changes

Copilot reviewed 41 out of 42 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
packages/sdk-go/types/timestamp_test.go Tests for opcode/step/timestamp primitives.
packages/sdk-go/types/timestamp.go Defines ops/steps/timestamp structures and formatting.
packages/sdk-go/types/status.go Verification/upgrade status types and helpers.
packages/sdk-go/types/header_test.go Tests for digest header and detached timestamp.
packages/sdk-go/types/header.go Digest header + detached timestamp types.
packages/sdk-go/types/doc.go Package documentation for timestamp types.
packages/sdk-go/types/attestation_test.go Tests for attestation types and URI validation.
packages/sdk-go/types/attestation.go Attestation types (Bitcoin, EAS, pending, unknown) + URI validation.
packages/sdk-go/sdk_test.go End-to-end and unit tests for SDK behaviors.
packages/sdk-go/sdk.go Core SDK implementation: stamping, verifying, upgrading.
packages/sdk-go/rpc/ethereum.go Ethereum RPC client wrapper for EAS contract calls.
packages/sdk-go/rpc/doc.go RPC package documentation.
packages/sdk-go/rpc/bitcoin.go Bitcoin JSON-RPC client + byte-reversal utilities.
packages/sdk-go/go.mod Go module definition and dependencies.
packages/sdk-go/examples/verify/main.go Example CLI for verifying a timestamp file.
packages/sdk-go/examples/upgrade/main.go Example CLI for upgrading pending attestations.
packages/sdk-go/examples/stamp/main.go Example CLI for stamping a file/sample data.
packages/sdk-go/errors/errors.go Structured SDK error types and constructors.
packages/sdk-go/errors.go Re-exports error codes/types at top-level package.
packages/sdk-go/doc.go Top-level SDK package documentation.
packages/sdk-go/crypto/hash_test.go Tests for SHA256/Keccak256 wrappers.
packages/sdk-go/crypto/hash.go Hash wrappers (SHA256, Keccak256) used across SDK.
packages/sdk-go/crypto/doc.go Crypto package documentation.
packages/sdk-go/crypto/bmt_test.go Tests for Merkle tree construction/proofs/serialization.
packages/sdk-go/crypto/bmt.go Merkle tree implementation + proof generation/verification.
packages/sdk-go/codec/leb128_test.go Tests for LEB128 encode/decode helpers.
packages/sdk-go/codec/leb128.go LEB128 encoding/decoding implementation.
packages/sdk-go/codec/encoder_test.go Tests for encoding headers/steps/timestamps.
packages/sdk-go/codec/encoder.go Timestamp encoder implementation.
packages/sdk-go/codec/doc.go Codec package documentation.
packages/sdk-go/codec/decoder_test.go Tests for decoding timestamps and error handling.
packages/sdk-go/codec/decoder.go Timestamp decoder implementation.
packages/sdk-go/codec/constants.go Codec constants (magic bytes, opcodes, tags).
packages/sdk-go/attestation/verify_test.go Tests for attestation verification dispatcher.
packages/sdk-go/attestation/verify.go Attestation verification dispatcher.
packages/sdk-go/attestation/eas_test.go Tests for EAS attestation verification.
packages/sdk-go/attestation/eas.go EAS verification logic (schema, revocable, data checks).
packages/sdk-go/attestation/doc.go Attestation package documentation.
packages/sdk-go/attestation/bitcoin_test.go Tests for Bitcoin attestation verification.
packages/sdk-go/attestation/bitcoin.go Bitcoin verification logic against block headers.
packages/sdk-go/README.md SDK README with install + usage overview.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

lightsing and others added 4 commits March 12, 2026 07:48
@lightsing lightsing requested a review from Copilot March 12, 2026 05:14
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 49 out of 50 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (9)

packages/sdk-go/sdk.go:1

  • calendars: DefaultCalendars assigns the global slice directly, and the subsequent in-place normalization mutates the underlying array—effectively modifying the package-level DefaultCalendars at runtime. Clone the slice when initializing the SDK (e.g., copy into a new slice) before normalizing.
    packages/sdk-go/sdk.go:1
  • The “too large” detection can’t work as written: io.ReadAll typically returns err == nil when it reaches EOF, including when reading from an io.LimitReader. This means oversized responses will be truncated to 1MB and treated as valid input (likely leading to confusing decode errors or partial parsing). Read limit+1 bytes and error if more than limit bytes are present, or use an approach that can reliably detect truncation.
    packages/sdk-go/sdk.go:1
  • Same truncation/oversize detection issue as in requestAttestation: the code won’t reliably detect that the response exceeded the 1MB limit. Use a limit+1 read or another mechanism that can distinguish “exactly limit bytes read” from “response ended within limit.”
    packages/sdk-go/sdk.go:1
  • AddChain returns an error, but it’s ignored here, so RPC misconfiguration or dial failures become silent and can surface later as “no client configured” / unexpected verification failures. Consider changing the option/config pattern so NewSDK can surface initialization failures (e.g., Option func(*SDK) error and NewSDK(...)(*SDK, error)), or make AddChain lazy (store URL now, dial on first use) and log/record the error deterministically when dialing fails.
    packages/sdk-go/types/header.go:1
  • dt.Timestamp is a types.Timestamp (a slice), but the format string uses %s. This will produce "%!s(...)" output instead of a meaningful timestamp string. Either implement func (t Timestamp) String() string and use %s with it, or change formatting to %v and format steps explicitly.
    packages/sdk-go/types/header.go:1
  • DigestBytes() returns the internal slice, allowing callers to mutate the header digest after construction (even though NewDigestHeader copies the input). To preserve immutability and prevent subtle bugs, return a defensive copy (or document clearly that the returned slice must be treated as read-only).
    packages/sdk-go/sdk.go:1
  • Returning the internal slice allows callers to mutate SDK configuration (calendars) without using options, which can lead to hard-to-track behavior (and potential data races if used concurrently). Return a copy of the slice to keep the SDK state encapsulated.
    packages/sdk-go/sdk.go:1
  • These branches return plain fmt.Errorf errors, while executeStep returns structured errors.SDError for unsupported algorithms. This inconsistency makes error handling harder for SDK consumers. Prefer returning the same structured error type (e.g., errors.NewSDKError(errors.ErrCodeUnsupported, "...", nil)) in all unsupported-hash paths.
    packages/sdk-go/sdk.go:1
  • The HTTP request/response handling (especially response size limiting and non-200 status handling) is security/robustness-sensitive but currently has no unit tests in this PR. Add tests using httptest.Server to cover: (1) oversized response (>1MB) correctly detected, (2) exact-limit response, (3) non-200 responses, and (4) invalid timestamp bytes returning an expected decode error.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lightsing lightsing merged commit 4cd11ab into dev/m2 Mar 12, 2026
@lightsing lightsing deleted the feat/go-sdk branch March 12, 2026 05:44
@lightsing lightsing added this to the L1 Anchoring milestone Mar 17, 2026
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