mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-02 17:31:39 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
866468c002 | ||
|
|
7f3aa01bd5 | ||
|
|
2f65b1c283 | ||
|
|
48f7b5d5cc | ||
|
|
d26d3d7b4d | ||
|
|
807b2e86ec | ||
|
|
9bd5e41fa0 | ||
|
|
2ae32b2f64 | ||
|
|
ef7c33a011 | ||
|
|
ac8250557d | ||
|
|
8764e93437 | ||
|
|
8224fd3683 | ||
|
|
a5dd620b17 | ||
|
|
57bce7d50e | ||
|
|
5c5e909ffd | ||
|
|
0cf308016b | ||
|
|
9787394d5a | ||
|
|
a90111907d | ||
|
|
7c8fa0045c | ||
|
|
0eb5530422 | ||
|
|
a90a553222 | ||
|
|
aee9af7b34 | ||
|
|
571fb6100b | ||
|
|
0a7b7d9fe2 | ||
|
|
afc6343c21 | ||
|
|
bb0e8495d3 | ||
|
|
26a322a5ea | ||
|
|
014ce98359 | ||
|
|
ddf2f6232a | ||
|
|
2486ff3c94 | ||
|
|
9b0a78adda | ||
|
|
b727a52193 | ||
|
|
e0d4427153 | ||
|
|
356093d08a | ||
|
|
b0a91ddf14 | ||
|
|
aa8f8c004f | ||
|
|
d8e5bc9f37 | ||
|
|
75adb6200d | ||
|
|
92df0375dd | ||
|
|
d6f6023d8b | ||
|
|
3c450ad795 | ||
|
|
4ce9a45912 | ||
|
|
68aa232368 | ||
|
|
2545ab5748 | ||
|
|
a5c17cb3db | ||
|
|
280b441a4b | ||
|
|
145499e1e4 | ||
|
|
0ccfa47e7b | ||
|
|
e2735d5cd1 | ||
|
|
5eb1f0d0a9 | ||
|
|
a3652e3f2f | ||
|
|
7d344ef854 | ||
|
|
378d259895 | ||
|
|
3bbec0ebed | ||
|
|
4c9919f0a0 | ||
|
|
c77bf5d1ea | ||
|
|
143053e355 | ||
|
|
47c3a53080 | ||
|
|
0ec2f7d86a | ||
|
|
398864fc6b | ||
|
|
630e4ad7f0 | ||
|
|
7e50d7f76d | ||
|
|
9dfb8634bc | ||
|
|
9556faabb9 | ||
|
|
c9cc4042db | ||
|
|
fc9995dd40 | ||
|
|
5cc450c170 | ||
|
|
d3cfd27f5a | ||
|
|
30c984fd90 | ||
|
|
4d6a8628af | ||
|
|
59b561d2d9 | ||
|
|
77fe287a0b | ||
|
|
d69c2a9d53 | ||
|
|
c9004e75df | ||
|
|
52041fe3d6 | ||
|
|
b9ad8e1e78 | ||
|
|
920703c0c7 | ||
|
|
77298c79af | ||
|
|
9d86dad38d | ||
|
|
36191d2bd4 | ||
|
|
265aec187e | ||
|
|
6072f6ecfa | ||
|
|
fc001216a8 | ||
|
|
354fdabdc4 | ||
|
|
7c4586ce90 | ||
|
|
6d27b926f6 | ||
|
|
f74bdc1d79 | ||
|
|
8522cb8d47 | ||
|
|
30475b9fbd | ||
|
|
1388a673e5 | ||
|
|
ac8c153b28 | ||
|
|
ee12bf684e |
@@ -2,7 +2,7 @@
|
||||
name = "cz_conventional_commits"
|
||||
tag_format = "v$version"
|
||||
version_scheme = "semver"
|
||||
version = "0.5.25"
|
||||
version = "0.6.2"
|
||||
update_changelog_on_bump = true
|
||||
major_version_zero = true
|
||||
changelog_file = "./docs/docs/changelog/index.md"
|
||||
changelog_file = "CHANGELOG.md"
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
FROM jetpackio/devbox:latest
|
||||
|
||||
# Installing your devbox project
|
||||
WORKDIR /code
|
||||
USER root:root
|
||||
RUN mkdir -p /code && chown ${DEVBOX_USER}:${DEVBOX_USER} /code
|
||||
USER ${DEVBOX_USER}:${DEVBOX_USER}
|
||||
|
||||
# Copy devbox configuration files
|
||||
COPY --chown=${DEVBOX_USER}:${DEVBOX_USER} devbox.json devbox.json
|
||||
COPY --chown=${DEVBOX_USER}:${DEVBOX_USER} devbox.lock devbox.lock
|
||||
|
||||
RUN devbox run -- echo "Installed Packages."
|
||||
RUN devbox shellenv --init-hook >> ~/.profile
|
||||
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
{
|
||||
"name": "Devbox Remote Container",
|
||||
"build": {
|
||||
"dockerfile": "./Dockerfile",
|
||||
"context": ".."
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {},
|
||||
"extensions": [
|
||||
"jetpack-io.devbox"
|
||||
]
|
||||
}
|
||||
},
|
||||
"remoteUser": "devbox",
|
||||
"forwardPorts": [
|
||||
1317,
|
||||
26657,
|
||||
9090,
|
||||
3000,
|
||||
80,
|
||||
5000
|
||||
],
|
||||
"portsAttributes": {
|
||||
"1317": {
|
||||
"label": "sonr-api",
|
||||
"onAutoForward": "notify"
|
||||
},
|
||||
"26657": {
|
||||
"label": "sonr-rpc",
|
||||
"onAutoForward": "notify"
|
||||
},
|
||||
"9090": {
|
||||
"label": "sonr-grpc",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"3000": {
|
||||
"label": "hway-frontend",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"80": {
|
||||
"label": "ipfs-gateway",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"5000": {
|
||||
"label": "ipfs-api",
|
||||
"onAutoForward": "silent"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"ghcr.io/michidk/devcontainers-features/bun:1": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/cirolosapio/devcontainers-features/alpine-ohmyzsh:0": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/guiyomh/features/golangci-lint:0": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/meaningful-ooo/devcontainer-features/homebrew:2": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/docker-in-docker:2": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/github-cli:1": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/go:1": {
|
||||
"version": "latest",
|
||||
"go": "1.23"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/rust:1": {
|
||||
"version": "latest",
|
||||
"rust": "1.73"
|
||||
},
|
||||
"ghcr.io/jpawlowski/devcontainer-features/codespaces-dotfiles:1": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/duduribeiro/devcontainer-features/neovim:1": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/dlouwers/devcontainer-features/devbox:1": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/sshd:1": {
|
||||
"version": "latest"
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
You are an expert in Cosmos SDK data modeling and state management, specializing in building efficient and scalable data models using the Cosmos SDK ORM system with Protocol Buffers.
|
||||
|
||||
Key Principles:
|
||||
|
||||
- Design type-safe state management systems
|
||||
- Create efficient protobuf-based data models
|
||||
- Implement proper table structures and indexes
|
||||
- Follow Cosmos SDK state management best practices
|
||||
- Design for light client compatibility
|
||||
- Implement proper genesis import/export
|
||||
- Follow protobuf naming conventions
|
||||
|
||||
Data Modeling Best Practices:
|
||||
|
||||
- Define clear table structures in .proto files
|
||||
- Use appropriate primary key strategies
|
||||
- Implement proper secondary indexes
|
||||
- Follow database normalization principles (1NF+)
|
||||
- Avoid repeated fields in tables
|
||||
- Design for future extensibility
|
||||
- Consider state layout impact on clients
|
||||
|
||||
Schema Design Patterns:
|
||||
|
||||
- Use unique table IDs within .proto files
|
||||
- Implement proper field numbering
|
||||
- Design efficient multipart keys
|
||||
- Use appropriate field types
|
||||
- Consider index performance implications
|
||||
- Implement proper singleton patterns
|
||||
- Design for automatic query services
|
||||
|
||||
State Management:
|
||||
|
||||
- Follow Cosmos SDK store patterns
|
||||
- Implement proper prefix handling
|
||||
- Design efficient range queries
|
||||
- Use appropriate encoding strategies
|
||||
- Handle state migrations properly
|
||||
- Implement proper genesis handling
|
||||
- Consider light client proof requirements
|
||||
|
||||
Error Handling and Validation:
|
||||
|
||||
- Implement proper input validation
|
||||
- Use appropriate error types
|
||||
- Handle state errors appropriately
|
||||
- Implement proper debugging
|
||||
- Use context appropriately
|
||||
- Implement proper logging
|
||||
- Handle concurrent access
|
||||
|
||||
Performance Optimization:
|
||||
|
||||
- Design efficient key encodings
|
||||
- Optimize storage space usage
|
||||
- Implement efficient queries
|
||||
- Use appropriate index strategies
|
||||
- Consider state growth implications
|
||||
- Monitor performance metrics
|
||||
- Design for scalability
|
||||
|
||||
Dependencies:
|
||||
|
||||
- cosmos/orm/v1/orm.proto
|
||||
- [google.golang.org/protobuf](http://google.golang.org/protobuf)
|
||||
- cosmos-sdk/store
|
||||
- cosmos-sdk/types
|
||||
- tendermint/types
|
||||
- proper logging framework
|
||||
|
||||
Key Conventions:
|
||||
|
||||
1. Use consistent protobuf naming
|
||||
2. Implement proper documentation
|
||||
3. Follow schema versioning practices
|
||||
4. Use proper table ID management
|
||||
5. Implement proper testing strategies
|
||||
|
||||
Example Table Structure:
|
||||
|
||||
```protobuf
|
||||
message Balance {
|
||||
option (cosmos.orm.v1.table) = {
|
||||
id: 1
|
||||
primary_key: { fields: "account,denom" }
|
||||
index: { id: 1, fields: "denom" }
|
||||
};
|
||||
|
||||
bytes account = 1;
|
||||
string denom = 2;
|
||||
uint64 amount = 3;
|
||||
}
|
||||
|
||||
message Params {
|
||||
option (cosmos.orm.v1.singleton) = {
|
||||
id: 2
|
||||
};
|
||||
|
||||
google.protobuf.Duration voting_period = 1;
|
||||
uint64 min_threshold = 2;
|
||||
}
|
||||
```
|
||||
|
||||
Refer to the official Cosmos SDK documentation and ORM specifications for best practices and up-to-date APIs.
|
||||
@@ -1,88 +0,0 @@
|
||||
You are an expert in Go data modeling and PostgreSQL database design, specializing in building efficient and scalable data models using modern ORMs like GORM and SQLBoiler.
|
||||
|
||||
Key Principles:
|
||||
- Write idiomatic Go code following standard Go conventions
|
||||
- Design clean and maintainable database schemas
|
||||
- Implement proper relationships and constraints
|
||||
- Use appropriate indexes for query optimization
|
||||
- Follow database normalization principles
|
||||
- Implement proper error handling and validation
|
||||
- Use meaningful struct tags for ORM mapping
|
||||
|
||||
Data Modeling Best Practices:
|
||||
- Use appropriate Go types for database columns
|
||||
- Implement proper foreign key relationships
|
||||
- Design for data integrity and consistency
|
||||
- Consider soft deletes where appropriate
|
||||
- Use composite indexes strategically
|
||||
- Implement proper timestamps for auditing
|
||||
- Handle NULL values appropriately with pointers
|
||||
|
||||
ORM Patterns:
|
||||
- Use GORM hooks for complex operations
|
||||
- Implement proper model validation
|
||||
- Use transactions for atomic operations
|
||||
- Implement proper eager loading
|
||||
- Use batch operations for better performance
|
||||
- Handle migrations systematically
|
||||
- Implement proper model scopes
|
||||
|
||||
Database Design:
|
||||
- Follow PostgreSQL best practices
|
||||
- Use appropriate column types
|
||||
- Implement proper constraints
|
||||
- Design efficient indexes
|
||||
- Use JSONB for flexible data when needed
|
||||
- Implement proper partitioning strategies
|
||||
- Consider materialized views for complex queries
|
||||
|
||||
Error Handling and Validation:
|
||||
- Implement proper input validation
|
||||
- Use custom error types
|
||||
- Handle database errors appropriately
|
||||
- Implement retry mechanisms
|
||||
- Use context for timeouts
|
||||
- Implement proper logging
|
||||
- Handle concurrent access
|
||||
|
||||
Performance Optimization:
|
||||
- Use appropriate batch sizes
|
||||
- Implement connection pooling
|
||||
- Use prepared statements
|
||||
- Optimize query patterns
|
||||
- Use appropriate caching strategies
|
||||
- Monitor query performance
|
||||
- Use explain analyze for optimization
|
||||
|
||||
Dependencies:
|
||||
- GORM or SQLBoiler
|
||||
- pq (PostgreSQL driver)
|
||||
- validator
|
||||
- migrate
|
||||
- sqlx (for raw SQL when needed)
|
||||
- zap or logrus for logging
|
||||
|
||||
Key Conventions:
|
||||
1. Use consistent naming conventions
|
||||
2. Implement proper documentation
|
||||
3. Follow database migration best practices
|
||||
4. Use version control for schema changes
|
||||
5. Implement proper testing strategies
|
||||
|
||||
Example Model Structure:
|
||||
```go
|
||||
type User struct {
|
||||
ID uint `gorm:"primarykey"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
|
||||
Name string `gorm:"type:varchar(100);not null"`
|
||||
Email string `gorm:"type:varchar(100);uniqueIndex;not null"`
|
||||
Profile Profile
|
||||
Orders []Order
|
||||
}
|
||||
```
|
||||
|
||||
Refer to the official documentation of GORM, PostgreSQL, and Go for best practices and up-to-date APIs.
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
You are a technical lead specializing in decentralized identity systems and security architecture, with expertise in W3C standards, Cosmos SDK, and blockchain security patterns.
|
||||
|
||||
Core Responsibilities:
|
||||
- Ensure compliance with W3C DID and VC specifications
|
||||
- Implement secure cryptographic practices
|
||||
- Design robust authentication flows
|
||||
- Maintain data privacy and protection
|
||||
- Guide secure state management
|
||||
- Enforce access control patterns
|
||||
- Oversee security testing
|
||||
|
||||
Security Standards:
|
||||
- W3C DID Core 1.0
|
||||
- W3C Verifiable Credentials
|
||||
- W3C WebAuthn Level 2
|
||||
- OAuth 2.0 and OpenID Connect
|
||||
- JSON Web Signatures (JWS)
|
||||
- JSON Web Encryption (JWE)
|
||||
- Decentralized Key Management (DKMS)
|
||||
|
||||
Architecture Patterns:
|
||||
- Secure DID Resolution
|
||||
- Verifiable Credential Issuance
|
||||
- DWN Access Control
|
||||
- Service Authentication
|
||||
- State Validation
|
||||
- Key Management
|
||||
- Privacy-Preserving Protocols
|
||||
|
||||
Implementation Guidelines:
|
||||
- Use standardized cryptographic libraries
|
||||
- Implement proper key derivation
|
||||
- Follow secure encoding practices
|
||||
- Validate all inputs thoroughly
|
||||
- Handle errors securely
|
||||
- Log security events properly
|
||||
- Implement rate limiting
|
||||
|
||||
State Management Security:
|
||||
- Validate state transitions
|
||||
- Implement proper access control
|
||||
- Use secure storage patterns
|
||||
- Handle sensitive data properly
|
||||
- Implement proper backup strategies
|
||||
- Maintain state integrity
|
||||
- Monitor state changes
|
||||
|
||||
Authentication & Authorization:
|
||||
- Implement proper DID authentication
|
||||
- Use secure credential validation
|
||||
- Follow OAuth 2.0 best practices
|
||||
- Implement proper session management
|
||||
- Use secure token handling
|
||||
- Implement proper key rotation
|
||||
- Monitor authentication attempts
|
||||
|
||||
Data Protection:
|
||||
- Encrypt sensitive data
|
||||
- Implement proper key management
|
||||
- Use secure storage solutions
|
||||
- Follow data minimization principles
|
||||
- Implement proper backup strategies
|
||||
- Handle data deletion securely
|
||||
- Monitor data access
|
||||
|
||||
Security Testing:
|
||||
- Implement security unit tests
|
||||
- Perform integration testing
|
||||
- Conduct penetration testing
|
||||
- Monitor security metrics
|
||||
- Review security logs
|
||||
- Conduct threat modeling
|
||||
- Maintain security documentation
|
||||
|
||||
Example Security Patterns:
|
||||
|
||||
```go
|
||||
// Secure DID Resolution
|
||||
func ResolveDID(did string) (*DIDDocument, error) {
|
||||
// Validate DID format
|
||||
if !ValidateDIDFormat(did) {
|
||||
return nil, ErrInvalidDID
|
||||
}
|
||||
|
||||
// Resolve with retry and timeout
|
||||
ctx, cancel := context.WithTimeout(context.Background(), resolveTimeout)
|
||||
defer cancel()
|
||||
|
||||
doc, err := resolver.ResolveWithContext(ctx, did)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolution failed: %w", err)
|
||||
}
|
||||
|
||||
// Validate document structure
|
||||
if err := ValidateDIDDocument(doc); err != nil {
|
||||
return nil, fmt.Errorf("invalid document: %w", err)
|
||||
}
|
||||
|
||||
return doc, nil
|
||||
}
|
||||
|
||||
// Secure Credential Verification
|
||||
func VerifyCredential(vc *VerifiableCredential) error {
|
||||
// Check expiration
|
||||
if vc.IsExpired() {
|
||||
return ErrCredentialExpired
|
||||
}
|
||||
|
||||
// Verify proof
|
||||
if err := vc.VerifyProof(trustRegistry); err != nil {
|
||||
return fmt.Errorf("invalid proof: %w", err)
|
||||
}
|
||||
|
||||
// Verify status
|
||||
if err := vc.CheckRevocationStatus(); err != nil {
|
||||
return fmt.Errorf("revocation check failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
Security Checklist:
|
||||
1. All DIDs follow W3C specification
|
||||
2. Credentials implement proper proofs
|
||||
3. Keys use proper derivation/rotation
|
||||
4. State changes are validated
|
||||
5. Access control is enforced
|
||||
6. Data is properly encrypted
|
||||
7. Logging captures security events
|
||||
|
||||
Refer to W3C specifications, Cosmos SDK security documentation, and blockchain security best practices for detailed implementation guidance.
|
||||
@@ -1,11 +0,0 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gomod" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -1,5 +1,3 @@
|
||||
"@pr/feature": ["feature/*", "feat/*"]
|
||||
"@pr/fix": fix/*
|
||||
"@pr/chore": chore/*
|
||||
"@pr/docs": docs/*
|
||||
"@pr/refactor": refactor/*
|
||||
"feature": ["feature/*", "feat/*"]
|
||||
"bugfix": fix/*
|
||||
"enhancement": enhancement/*
|
||||
|
||||
+249
-427
@@ -1,427 +1,249 @@
|
||||
[
|
||||
{
|
||||
"name": "app/cosmos-sdk",
|
||||
"path": "app",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [
|
||||
"module",
|
||||
"cosmos"
|
||||
],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/module-manager"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"protobuf",
|
||||
"cosmos"
|
||||
],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/messages-and-queries"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"rpc",
|
||||
"protobuf",
|
||||
"service",
|
||||
"cosmos"
|
||||
],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/msg-services"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"protobuf",
|
||||
"rpc",
|
||||
"cosmos",
|
||||
"query"
|
||||
],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/query-services"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"cosmos",
|
||||
"depinject",
|
||||
"sdk"
|
||||
],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/depinject"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "app/ibc",
|
||||
"path": "app",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [
|
||||
"cosmos",
|
||||
"interchain",
|
||||
"accounts"
|
||||
],
|
||||
"url": "https://ibc.cosmos.network/v8/apps/interchain-accounts/overview/"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://ibc.cosmos.network/v8/apps/transfer/overview/"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.osmosis.zone/osmosis-core/asset-info/"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.osmosis.zone/osmosis-core/modules/tokenfactory"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"usdc",
|
||||
"mint",
|
||||
"cosmos",
|
||||
"noble"
|
||||
],
|
||||
"url": "https://docs.noble.xyz/cctp/mint"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"usdc"
|
||||
],
|
||||
"url": "https://docs.noble.xyz/cctp/mint_forward"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.evmos.org/protocol/modules/erc20"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.nomic.io/nbtc"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "crypto/mpc",
|
||||
"path": "crypto/mpc",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [
|
||||
"mpc",
|
||||
"wallet",
|
||||
"security",
|
||||
"advanced cryptography"
|
||||
],
|
||||
"url": "https://csrc.nist.gov/CSRC/media/Events/NTCW19/papers/paper-DKLS.pdf"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "crypto/ucan",
|
||||
"path": "crypto/ucan",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://raw.githubusercontent.com/ucan-wg/spec/refs/heads/main/README.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "crypto/zkp",
|
||||
"path": "crypto/accumulator",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://eprint.iacr.org/2021/1672.pdf"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gateway/handlers",
|
||||
"path": "pkg/gateway/handlers",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://echo.labstack.com/docs/cookbook/sse"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://echo.labstack.com/docs/cookbook/websocket"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://echo.labstack.com/docs/cookbook/subdomain"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gateway/database",
|
||||
"path": "pkg/gateway/internal/database",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.tigerbeetle.com/coding/data-modeling"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.tigerbeetle.com/coding/two-phase-transfers"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.tigerbeetle.com/coding/reliable-transaction-submission"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"currency"
|
||||
],
|
||||
"url": "https://docs.tigerbeetle.com/coding/recipes/currency-exchange"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"balance"
|
||||
],
|
||||
"url": "https://docs.tigerbeetle.com/coding/recipes/balance-conditional-transfers"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.tigerbeetle.com/reference/account"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.tigerbeetle.com/reference/transfer"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.substreams.dev/documentation/consume/packages"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.substreams.dev/documentation/consume/sql/deployable-services/local-service"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.substreams.dev/tutorials/cosmos/injective/foundational"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vault/handlers",
|
||||
"path": "pkg/vault/handlers",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://echo.labstack.com/docs/cookbook/jwt"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://echo.labstack.com/docs/middleware/secure"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vault/database",
|
||||
"path": "pkg/vault/internal/database",
|
||||
"docs": [
|
||||
"https://dexie.org/docs/ExportImport/dexie-export-import",
|
||||
"https://dexie.org/docs/API-Reference#quick-reference",
|
||||
"https://templ.guide/syntax-and-usage/script-templates"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pkl/ipfs",
|
||||
"path": "pkl/ipfs.net",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://github.com/ipfs/kubo/blob/master/docs/config.md"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://pkl-lang.org/main/current/language-reference/index.html"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pkl/matrix",
|
||||
"path": "pkl/matrix.net",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://pkl-lang.org/main/current/language-reference/index.html"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pkl/chain",
|
||||
"path": "pkl/sonr.chain",
|
||||
"docs": [
|
||||
"https://tutorials.cosmos.network/tutorials/9-path-to-prod/5-network.html",
|
||||
"https://tutorials.cosmos.network/tutorials/9-path-to-prod/4-genesis.html",
|
||||
"https://pkl-lang.org/main/current/language-reference/index.html",
|
||||
"https://docs.cosmos.network/v0.50/user/run-node/run-testnet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pkl/hway",
|
||||
"path": "pkl/sonr.hway",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://pkl-lang.org/main/current/language-reference/index.html"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pkl/motr",
|
||||
"path": "pkl/sonr.motr",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://pkl-lang.org/main/current/language-reference/index.html"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://web.dev/learn/pwa/service-workers/"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x/did",
|
||||
"path": "proto/did",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/packages/orm"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/protobuf-annotations"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/auth"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/packages/collections"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/bank"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x/dwn",
|
||||
"path": "proto/dwn",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/protobuf-annotations"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/packages/orm"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/authz"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/packages/collections"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/gov"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/staking"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x/svc",
|
||||
"path": "proto/svc",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/packages/collections"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/protobuf-annotations"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/packages/orm"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/group"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/nft"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "repo/ci-cd",
|
||||
"path": "deploy",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/tooling/cosmovisor"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://f1bonacc1.github.io/process-compose/configuration/"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://docs.nomic.io/network/ibc-relayer"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://www.jetify.com/docs/devbox"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://taskfile.dev/reference/cli"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://taskfile.dev/reference/schema"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://taskfile.dev/reference/templating/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "repo/docs",
|
||||
"path": "docs",
|
||||
"docs": [
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://squidfunk.github.io/mkdocs-material/reference/"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://github.com/mkdocs/catalog/blob/main/README.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
{
|
||||
"scopes": [
|
||||
"core-chain",
|
||||
"core-ibc",
|
||||
"x-did",
|
||||
"x-dwn",
|
||||
"x-svc",
|
||||
"security-mpc",
|
||||
"security-ucan",
|
||||
"security-zkp",
|
||||
"ci-cd",
|
||||
"dev-ops"
|
||||
],
|
||||
"docs": [
|
||||
{
|
||||
"keywords": ["github", "actions", "workflows", "syntax"],
|
||||
"url": "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "tooling", "cosmovisor"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/tooling/cosmovisor"
|
||||
},
|
||||
{
|
||||
"keywords": ["process-compose", "configuration"],
|
||||
"url": "https://f1bonacc1.github.io/process-compose/configuration/"
|
||||
},
|
||||
{
|
||||
"keywords": ["taskfile", "cli", "reference"],
|
||||
"url": "https://taskfile.dev/reference/cli"
|
||||
},
|
||||
{
|
||||
"keywords": [],
|
||||
"url": "https://taskfile.dev/reference/schema"
|
||||
},
|
||||
{
|
||||
"keywords": ["taskfile", "templating", "reference"],
|
||||
"url": "https://taskfile.dev/reference/templating/"
|
||||
},
|
||||
{
|
||||
"keywords": ["mkdocs", "material", "reference"],
|
||||
"url": "https://squidfunk.github.io/mkdocs-material/reference/"
|
||||
},
|
||||
{
|
||||
"keywords": ["pkl", "language", "reference"],
|
||||
"url": "https://pkl-lang.org/main/current/language-reference/index.html"
|
||||
},
|
||||
{
|
||||
"keywords": ["pwa", "service-workers", "web"],
|
||||
"url": "https://web.dev/learn/pwa/service-workers/"
|
||||
},
|
||||
{
|
||||
"keywords": ["service-workers", "web", "api"],
|
||||
"url": "https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API"
|
||||
},
|
||||
{
|
||||
"keywords": ["web-authentication", "web", "api"],
|
||||
"url": "https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API"
|
||||
},
|
||||
{
|
||||
"keywords": ["sdk", "modules", "cosmos", "manager"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/module-manager"
|
||||
},
|
||||
{
|
||||
"keywords": ["sdk", "modules", "cosmos", "messages", "queries"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/messages-and-queries"
|
||||
},
|
||||
{
|
||||
"keywords": ["sdk", "modules", "messages", "service", "cosmos"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/msg-services"
|
||||
},
|
||||
{
|
||||
"keywords": ["sdk", "modules", "services", "cosmos", "query"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/query-services"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "depinject", "modules", "sdk"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/depinject"
|
||||
},
|
||||
{
|
||||
"keywords": ["ibc", "apps", "sdk", "interchain-accounts"],
|
||||
"url": "https://ibc.cosmos.network/v8/apps/interchain-accounts/overview/"
|
||||
},
|
||||
{
|
||||
"keywords": ["ibc", "apps", "sdk", "transfer"],
|
||||
"url": "https://ibc.cosmos.network/v8/apps/transfer/overview/"
|
||||
},
|
||||
{
|
||||
"keywords": ["osmosis", "modules", "ibc", "assets"],
|
||||
"url": "https://docs.osmosis.zone/osmosis-core/asset-info/"
|
||||
},
|
||||
{
|
||||
"keywords": ["ibc", "osmosis", "tokenfactory", "modules", "assets"],
|
||||
"url": "https://docs.osmosis.zone/osmosis-core/modules/tokenfactory"
|
||||
},
|
||||
{
|
||||
"keywords": ["ibc", "mint", "cctp", "noble", "assets"],
|
||||
"url": "https://docs.noble.xyz/cctp/mint"
|
||||
},
|
||||
{
|
||||
"keywords": ["ibc", "relayer", "nomic", "assets"],
|
||||
"url": "https://docs.nomic.io/network/ibc-relayer"
|
||||
},
|
||||
{
|
||||
"keywords": ["ibc", "cctp", "noble", "mint_forward", "assets"],
|
||||
"url": "https://docs.noble.xyz/cctp/mint_forward"
|
||||
},
|
||||
{
|
||||
"keywords": ["evmos", "erc20", "assets"],
|
||||
"url": "https://docs.evmos.org/protocol/modules/erc20"
|
||||
},
|
||||
{
|
||||
"keywords": ["nomic", "nbtc", "assets"],
|
||||
"url": "https://docs.nomic.io/nbtc"
|
||||
},
|
||||
{
|
||||
"keywords": ["mpc", "wallet", "cryptography", "capability", "invokation"],
|
||||
"url": "https://csrc.nist.gov/CSRC/media/Events/NTCW19/papers/paper-DKLS.pdf"
|
||||
},
|
||||
{
|
||||
"keywords": ["ucan", "spec", "cryptography", "authorization"],
|
||||
"url": "https://raw.githubusercontent.com/ucan-wg/spec/refs/heads/main/README.md"
|
||||
},
|
||||
{
|
||||
"keywords": ["zero-knowledge", "proofs", "cryptography", "privacy"],
|
||||
"url": "https://eprint.iacr.org/2021/1672.pdf"
|
||||
},
|
||||
{
|
||||
"keywords": ["gateway", "http", "sse"],
|
||||
"url": "https://echo.labstack.com/docs/cookbook/sse"
|
||||
},
|
||||
{
|
||||
"keywords": ["gateway", "http", "websocket"],
|
||||
"url": "https://echo.labstack.com/docs/cookbook/websocket"
|
||||
},
|
||||
{
|
||||
"keywords": ["gateway", "http", "subdomain"],
|
||||
"url": "https://echo.labstack.com/docs/cookbook/subdomain"
|
||||
},
|
||||
{
|
||||
"keywords": ["tigerbeetle", "models", "oracle"],
|
||||
"url": "https://docs.tigerbeetle.com/coding/data-modeling"
|
||||
},
|
||||
{
|
||||
"keywords": ["tigerbeetle", "two=phase", "transfers", "oracle"],
|
||||
"url": "https://docs.tigerbeetle.com/coding/two-phase-transfers"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"tigerbeetle",
|
||||
"oracle",
|
||||
"reliable",
|
||||
"transaction",
|
||||
"submission"
|
||||
],
|
||||
"url": "https://docs.tigerbeetle.com/coding/reliable-transaction-submission"
|
||||
},
|
||||
{
|
||||
"keywords": ["currency", "exchange", "tigerbeetle", "oracle"],
|
||||
"url": "https://docs.tigerbeetle.com/coding/recipes/currency-exchange"
|
||||
},
|
||||
{
|
||||
"keywords": [
|
||||
"balance",
|
||||
"tigerbeetle",
|
||||
"oracle",
|
||||
"conditional",
|
||||
"transfers"
|
||||
],
|
||||
"url": "https://docs.tigerbeetle.com/coding/recipes/balance-conditional-transfers"
|
||||
},
|
||||
{
|
||||
"keywords": ["tigerbeetle", "account", "oracle"],
|
||||
"url": "https://docs.tigerbeetle.com/reference/account"
|
||||
},
|
||||
{
|
||||
"keywords": ["tigerbeetle", "transfer", "oracle"],
|
||||
"url": "https://docs.tigerbeetle.com/reference/transfer"
|
||||
},
|
||||
{
|
||||
"keywords": ["substreams", "packages", "consumer", "oracle"],
|
||||
"url": "https://docs.substreams.dev/documentation/consume/packages"
|
||||
},
|
||||
{
|
||||
"keywords": ["substreams", "deploy", "service", "oracle"],
|
||||
"url": "https://docs.substreams.dev/documentation/consume/sql/deployable-services/local-service"
|
||||
},
|
||||
{
|
||||
"keywords": ["substreams", "tutorial", "cosmos", "injective"],
|
||||
"url": "https://docs.substreams.dev/tutorials/cosmos/injective/foundational"
|
||||
},
|
||||
{
|
||||
"keywords": ["worker", "http", "jwt"],
|
||||
"url": "https://echo.labstack.com/docs/cookbook/jwt"
|
||||
},
|
||||
{
|
||||
"keywords": ["worker", "http", "secure"],
|
||||
"url": "https://echo.labstack.com/docs/middleware/secure"
|
||||
},
|
||||
{
|
||||
"keywords": ["worker", "http", "service-workers", "web", "api"],
|
||||
"url": "https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API"
|
||||
},
|
||||
{
|
||||
"keywords": ["synapse", "matrix", "configuration", "usage"],
|
||||
"url": "https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "protobuf", "orm", "sdk"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/packages/orm"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "sdk", "modules", "auth"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/auth"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "sdk", "modules", "bank"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/bank"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "modules", "authz", "sdk"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/authz"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "protobuf", "collections", "sdk"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/packages/collections"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "modules", "gov", "sdk"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/gov"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "modules", "staking", "sdk"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/staking"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "protobuf", "annotations", "sdk"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/building-modules/protobuf-annotations"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "sdk", "modules", "group"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/group"
|
||||
},
|
||||
{
|
||||
"keywords": ["cosmos", "sdk", "modules", "nft"],
|
||||
"url": "https://docs.cosmos.network/v0.50/build/modules/nft"
|
||||
}
|
||||
],
|
||||
"next-milestone": "34"
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
ROOT_DIR=$(git rev-parse --show-toplevel)
|
||||
|
||||
# Extract scope name and path using jq, and pass it to fzf for selection
|
||||
SCOPE=$(cat "$ROOT_DIR/.github/scopes.json" | jq -r '.[] | "\(.name)"' | fzf --prompt "Select scope:")
|
||||
DOCS=$(cat "$ROOT_DIR/.github/scopes.json" | jq -r ".[] | select(.name == \"$SCOPE\") | .docs[].url")
|
||||
|
||||
# Write Title
|
||||
TITLE=$(gum input --placeholder "Issue Title...")
|
||||
|
||||
# Write Goal
|
||||
GOAL=$(mods --role "determine-issue-goal" "$SCOPE $TITLE")
|
||||
|
||||
# Input Requirements
|
||||
REQUIREMENTS=()
|
||||
while true; do
|
||||
if [ ${#REQUIREMENTS[@]} -ge 2 ]; then
|
||||
if ! gum confirm "Do you want to add another requirement?"; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
REQUIREMENT=$(gum input --placeholder "Add a requirement...")
|
||||
if [ -n "$REQUIREMENT" ]; then
|
||||
REQUIREMENTS+=("$REQUIREMENT")
|
||||
else
|
||||
echo "Requirement cannot be empty. Please enter a valid requirement."
|
||||
fi
|
||||
done
|
||||
|
||||
create_body() {
|
||||
echo "### Goal(s):"
|
||||
echo "$GOAL"
|
||||
echo "### Requirements:"
|
||||
for i in "${!REQUIREMENTS[@]}"; do
|
||||
echo "$(($i + 1)). ${REQUIREMENTS[$i]}"
|
||||
done
|
||||
echo "### Resources:"
|
||||
while IFS= read -r doc; do
|
||||
echo "- $doc"
|
||||
done <<< "$DOCS"
|
||||
}
|
||||
|
||||
ISSUE_BODY=$(create_body)
|
||||
|
||||
# Function to collect output
|
||||
preview_output() {
|
||||
echo "# ($SCOPE) $TITLE"
|
||||
echo "$ISSUE_BODY"
|
||||
}
|
||||
|
||||
# Display the formatted output
|
||||
preview_output | gum format
|
||||
|
||||
# Confirm to create a GitHub issue
|
||||
if gum confirm "Do you want to create a new GitHub issue with this information?"; then
|
||||
# Create a new GitHub issue using the gh CLI
|
||||
gh issue create --repo onsonr/sonr --title "($SCOPE) $TITLE" --body "$ISSUE_BODY"
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,39 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
ROOT_DIR=$(git rev-parse --show-toplevel)
|
||||
|
||||
# Package the PKL projects
|
||||
bunx pkl project package $ROOT_DIR/pkl/*/
|
||||
|
||||
# Process each directory in .out
|
||||
for dir in .out/*/; do
|
||||
# Get the folder name and version
|
||||
folder=$(basename "$dir")
|
||||
version=$(echo "$folder" | grep -o '@.*' | sed 's/@//')
|
||||
new_folder=$(echo "$folder" | sed 's/@[0-9.]*$//')
|
||||
|
||||
# Create new directory without version
|
||||
mkdir -p ".out/$new_folder/$version"
|
||||
|
||||
# Copy contents to versioned subdirectory
|
||||
cp -r "$dir"* ".out/$new_folder/$version/"
|
||||
|
||||
# Find and copy only .pkl files from the original package
|
||||
pkg_dir="$ROOT_DIR/pkl/$new_folder"
|
||||
if [ -d "$pkg_dir" ]; then
|
||||
# Copy only .pkl files to version directory
|
||||
find "$pkg_dir" -name "*.pkl" -exec cp {} ".out/$new_folder/$version/" \;
|
||||
fi
|
||||
|
||||
# Remove old versioned directory
|
||||
rm -rf "$dir"
|
||||
|
||||
# Upload to R2 with new structure
|
||||
rclone copy ".out/$new_folder" "r2:pkljar/$new_folder"
|
||||
done
|
||||
|
||||
# Cleanup .out directory
|
||||
rm -rf .out
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
name: Check PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
|
||||
permissions:
|
||||
contents: read # for TimonVS/pr-labeler-action to read config file
|
||||
pull-requests: write # for TimonVS/pr-labeler-action to add labels in PR
|
||||
|
||||
jobs:
|
||||
verify-pr:
|
||||
name: Test Lints
|
||||
if: github.event_name == 'pull_request'
|
||||
permissions:
|
||||
contents: read # for TimonVS/pr-labeler-action to read config file
|
||||
pull-requests: write # for TimonVS/pr-labeler-action to add labels in PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Required to fetch all history for merging
|
||||
|
||||
- uses: TimonVS/pr-labeler-action@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
configuration-path: .github/pr-labeler.yml # optional, .github/pr-labeler.yml is the default value
|
||||
- name: Trunk Check
|
||||
uses: trunk-io/trunk-action@v1
|
||||
|
||||
test-builds:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
name: Test Builds
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: onsonr/sonr
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- name: Run Sonrd Build
|
||||
run: make build
|
||||
|
||||
test-unit:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
name: Test Unit
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: onsonr/sonr
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- run: make test-unit
|
||||
|
||||
validate-release:
|
||||
if: github.event_name == 'merge_group' || github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
name: Test Version
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: onsonr/sonr
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Version Check
|
||||
run: make validate-tag
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check GoReleaser Config
|
||||
run: make release-check
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Deploy Networks
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
branches:
|
||||
- develop
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
reboot-devnet:
|
||||
name: Devnet Deploy
|
||||
runs-on: goliath
|
||||
environment: "Devnet"
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
branch: develop
|
||||
|
||||
- name: Stop Existing Network
|
||||
continue-on-error: true
|
||||
run: |
|
||||
make stop-uds
|
||||
make clean
|
||||
|
||||
- name: Start Updated Network
|
||||
run: |
|
||||
make start-uds
|
||||
@@ -1,19 +0,0 @@
|
||||
name: PR Labeler
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
pr-labeler:
|
||||
permissions:
|
||||
contents: read # for TimonVS/pr-labeler-action to read config file
|
||||
pull-requests: write # for TimonVS/pr-labeler-action to add labels in PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: TimonVS/pr-labeler-action@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
configuration-path: .github/pr-labeler.yml # optional, .github/pr-labeler.yml is the default value
|
||||
@@ -1,33 +0,0 @@
|
||||
name: Publish Docs via GitHub Pages
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- "docs/**"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Configure Git Credentials
|
||||
run: |
|
||||
git config user.name github-actions[bot]
|
||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
key: mkdocs-material-${{ env.cache_id }}
|
||||
path: .cache
|
||||
restore-keys: |
|
||||
mkdocs-material-
|
||||
- run: pip install mkdocs-material
|
||||
- run: cd docs && mkdocs gh-deploy --force
|
||||
@@ -1,30 +1,17 @@
|
||||
name: Run Tests
|
||||
name: Merge Group
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
|
||||
permissions:
|
||||
contents: read # for TimonVS/pr-labeler-action to read config file
|
||||
pull-requests: write # for TimonVS/pr-labeler-action to add labels in PR
|
||||
|
||||
jobs:
|
||||
test-unit:
|
||||
runs-on: ubuntu-latest
|
||||
name: Run Unit Tests
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: onsonr/sonr
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- run: make test-unit
|
||||
|
||||
test-race:
|
||||
runs-on: ubuntu-latest
|
||||
name: Run Race Tests
|
||||
if: github.event_name == 'merge_group'
|
||||
name: Test Race
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -42,8 +29,8 @@ jobs:
|
||||
|
||||
test-cover:
|
||||
runs-on: ubuntu-latest
|
||||
name: Run Coverage Tests
|
||||
continue-on-error: true
|
||||
if: github.event_name == 'merge_group'
|
||||
name: Test Coverage
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -57,3 +44,25 @@ jobs:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- run: make test-cover
|
||||
|
||||
test-release:
|
||||
runs-on: ubuntu-latest
|
||||
name: Test Release
|
||||
if: github.event_name == 'merge_group'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: onsonr/sonr
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
|
||||
- name: Release Dry Run
|
||||
run: make release-dry
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,34 @@
|
||||
name: Post Merge
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
bump-version:
|
||||
name: Cz Bump
|
||||
if: |
|
||||
github.event.pull_request.merged == true &&
|
||||
github.event.pull_request.user.login != 'dependabot[bot]' &&
|
||||
github.event.pull_request.user.login != 'dependabot-preview[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ssh-key: "${{ secrets.COMMIT_KEY }}"
|
||||
|
||||
- name: Create bump and changelog
|
||||
uses: commitizen-tools/commitizen-action@master
|
||||
with:
|
||||
push: false
|
||||
increment: patch
|
||||
branch: main
|
||||
|
||||
- name: Push using ssh
|
||||
run: |
|
||||
git push origin main --tags
|
||||
@@ -0,0 +1,66 @@
|
||||
name: New Release
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
buf_push:
|
||||
name: Publish Protobufs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Run `git checkout`
|
||||
- uses: actions/checkout@v4
|
||||
# Install the `buf` CLI
|
||||
- uses: bufbuild/buf-setup-action@v1
|
||||
# Push only the Input in `proto` to the BSR
|
||||
- uses: bufbuild/buf-push-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
input: proto
|
||||
buf_token: ${{ secrets.BUF_TOKEN }}
|
||||
|
||||
container-push:
|
||||
name: Publish Docker Images
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ghcr.io/onsonr/sonr:latest
|
||||
|
||||
docs-push:
|
||||
runs-on: ubuntu-latest
|
||||
name: Publish Tech Docs
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Configure Git Credentials
|
||||
run: |
|
||||
git config user.name github-actions[bot]
|
||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
key: mkdocs-material-${{ env.cache_id }}
|
||||
path: .cache
|
||||
restore-keys: |
|
||||
mkdocs-material-
|
||||
- run: pip install mkdocs-material
|
||||
- run: mkdocs gh-deploy --force
|
||||
@@ -0,0 +1,51 @@
|
||||
name: New Tag
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
new-release:
|
||||
name: Create Release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
permissions: write-all
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: onsonr/sonr
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Run GoReleaser
|
||||
run: make release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_RELEASER_TOKEN }}
|
||||
GITHUB_PERSONAL_AUTH_TOKEN: ${{ secrets.GH_RELEASER_TOKEN }}
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
|
||||
REDDIT_APP_ID: ${{ secrets.REDDIT_APP_ID }}
|
||||
REDDIT_SECRET: ${{ secrets.REDDIT_SECRET }}
|
||||
REDDIT_USERNAME: ${{ secrets.REDDIT_USERNAME }}
|
||||
REDDIT_PASSWORD: ${{ secrets.REDDIT_PASSWORD }}
|
||||
@@ -1,25 +0,0 @@
|
||||
name: Publish Versioned Assets
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
buf_push_core:
|
||||
name: Publish to buf.build/onsonr/sonr
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Run `git checkout`
|
||||
- uses: actions/checkout@v3
|
||||
# Install the `buf` CLI
|
||||
- uses: bufbuild/buf-setup-action@v1
|
||||
# Push only the Input in `proto` to the BSR
|
||||
- uses: bufbuild/buf-push-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
input: proto
|
||||
buf_token: ${{ secrets.BUF_TOKEN }}
|
||||
@@ -1,93 +0,0 @@
|
||||
name: Versioned Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
branches: ["develop"]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
check-release:
|
||||
name: Check Existing Release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
release_exists: ${{ steps.check.outputs.release_exists }}
|
||||
is_tag: ${{ steps.check-ref.outputs.is_tag }}
|
||||
ref_name: ${{ steps.check-ref.outputs.ref_name }}
|
||||
steps:
|
||||
- name: Determine ref type and name
|
||||
id: check-ref
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
echo "is_tag=true" >> "$GITHUB_OUTPUT"
|
||||
echo "ref_name=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "is_tag=false" >> "$GITHUB_OUTPUT"
|
||||
echo "ref_name=${GITHUB_REF#refs/heads/}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Check if release exists
|
||||
id: check
|
||||
if: steps.check-ref.outputs.is_tag == 'true'
|
||||
run: |
|
||||
RELEASE_EXISTS=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"https://api.github.com/repos/onsonr/sonr/releases/tags/${GITHUB_REF#refs/tags/}" \
|
||||
| jq -r 'if .message == "Not Found" then "false" else "true" end')
|
||||
echo "release_exists=$RELEASE_EXISTS" >> "$GITHUB_OUTPUT"
|
||||
|
||||
goreleaser:
|
||||
name: Run GoReleaser
|
||||
needs: check-release
|
||||
if: |
|
||||
(needs.check-release.outputs.is_tag == 'true' && needs.check-release.outputs.release_exists == 'false') ||
|
||||
(needs.check-release.outputs.is_tag == 'false')
|
||||
permissions: write-all
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: onsonr/sonr
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Set up release configuration
|
||||
id: setup
|
||||
run: |
|
||||
if [[ "${{ needs.check-release.outputs.is_tag }}" == "true" ]]; then
|
||||
echo "Using tag configuration"
|
||||
git checkout ${{ needs.check-release.outputs.ref_name }}
|
||||
echo "args=release --clean" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "Using snapshot configuration"
|
||||
echo "args=release --snapshot --clean" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Release
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser-pro
|
||||
version: latest
|
||||
args: ${{ steps.setup.outputs.args }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_RELEASER_TOKEN }}
|
||||
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||
GITHUB_PERSONAL_AUTH_TOKEN: ${{ secrets.GH_RELEASER_TOKEN }}
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
|
||||
CLOUDSMITH_TOKEN: ${{ secrets.CLOUDSMITH_TOKEN }}
|
||||
@@ -1,39 +0,0 @@
|
||||
name: Update Version
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
run-tests:
|
||||
name: "Run tests"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23"
|
||||
check-latest: true
|
||||
- name: Run tests
|
||||
run: make test
|
||||
|
||||
bump-version:
|
||||
needs: [run-tests]
|
||||
runs-on: ubuntu-latest
|
||||
name: "Bump Version"
|
||||
if: ${{ !startsWith(github.event.head_commit.message, 'bump:') }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
- name: Create bump and changelog
|
||||
uses: commitizen-tools/commitizen-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
increment: "PATCH"
|
||||
+14
-4
@@ -1,4 +1,9 @@
|
||||
# Aider related generated files
|
||||
.aider-context
|
||||
|
||||
# Binaries
|
||||
.task
|
||||
no
|
||||
.data
|
||||
schemas
|
||||
*.db
|
||||
@@ -60,10 +65,7 @@ override.tf.json
|
||||
|
||||
.terraformrc
|
||||
terraform.rc
|
||||
|
||||
Taskfile.yml
|
||||
|
||||
!deploy/**/Taskfile.yml
|
||||
flake.lock
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
@@ -89,6 +91,7 @@ buildenv*
|
||||
node_modules
|
||||
cmd/gateway/node_modules
|
||||
pkg/nebula/node_modules
|
||||
configs/logs.json
|
||||
|
||||
mprocs.yaml
|
||||
build
|
||||
@@ -98,4 +101,11 @@ sonr.wiki
|
||||
!buf.lock
|
||||
|
||||
.air.toml
|
||||
mprocs.yaml
|
||||
mprocs.log
|
||||
tools-stamp
|
||||
sonr.log
|
||||
deploy/conf
|
||||
|
||||
interchaintest-downloader
|
||||
.haptic
|
||||
|
||||
+11
-82
@@ -2,12 +2,14 @@
|
||||
version: 2
|
||||
project_name: sonr
|
||||
|
||||
before:
|
||||
hooks:
|
||||
- echo "Release date is {{ .Env.RELEASE_DATE }}"
|
||||
|
||||
builds:
|
||||
- id: sonr
|
||||
main: ./cmd/sonrd
|
||||
binary: sonrd
|
||||
builder: go
|
||||
gobinary: go
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
goos:
|
||||
- linux
|
||||
@@ -30,47 +32,11 @@ builds:
|
||||
- netgo
|
||||
- ledger
|
||||
|
||||
- id: hway
|
||||
main: ./cmd/hway
|
||||
binary: hway
|
||||
builder: go
|
||||
gobinary: go
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
flags:
|
||||
- -mod=readonly
|
||||
- -trimpath
|
||||
goamd64:
|
||||
- v1
|
||||
tags:
|
||||
- netgo
|
||||
ldflags:
|
||||
- -X main.version={{.Version}}
|
||||
- -X main.commit={{.Commit}}
|
||||
- -X main.date={{.Date}}
|
||||
archives:
|
||||
- id: sonr
|
||||
builds: [sonr]
|
||||
name_template: >-
|
||||
sonr_{{ .Version }}_
|
||||
{{- title .Os }}_{{- if eq .Arch "amd64" }}x86_64
|
||||
{{- else if eq .Arch "386" }}i386
|
||||
{{- else }}{{ .Arch }}{{ end }}
|
||||
format: tar.gz
|
||||
files:
|
||||
- src: README*
|
||||
wrap_in_directory: true
|
||||
|
||||
- id: hway
|
||||
builds: [hway]
|
||||
name_template: >-
|
||||
hway_{{ .Version }}_
|
||||
{{- title .Os }}_{{- if eq .Arch "amd64" }}x86_64
|
||||
sonr_{{ .Os }}_{{- if eq .Arch "amd64" }}x86_64
|
||||
{{- else if eq .Arch "386" }}i386
|
||||
{{- else }}{{ .Arch }}{{ end }}
|
||||
format: tar.gz
|
||||
@@ -79,32 +45,9 @@ archives:
|
||||
wrap_in_directory: true
|
||||
|
||||
nfpms:
|
||||
- id: hway
|
||||
package_name: hway
|
||||
file_name_template: "{{ .ConventionalFileName }}"
|
||||
builds: [hway]
|
||||
vendor: Sonr
|
||||
homepage: "https://onsonr.dev"
|
||||
maintainer: "Sonr <support@onsonr.dev>"
|
||||
description: "Sonr Highway is a decentralized, permissionless, and censorship-resistant identity network proxy."
|
||||
license: "Apache 2.0"
|
||||
formats:
|
||||
- rpm
|
||||
- deb
|
||||
- apk
|
||||
dependencies:
|
||||
- ipfs
|
||||
contents:
|
||||
- src: README*
|
||||
dst: /usr/share/doc/hway
|
||||
bindir: /usr/bin
|
||||
section: net
|
||||
priority: optional
|
||||
# Add these lines to match build config
|
||||
|
||||
- id: sonr
|
||||
package_name: sonrd
|
||||
file_name_template: "{{ .ConventionalFileName }}"
|
||||
file_name_template: "sonrd_{{ .Os }}_{{ .Arch }}{{ .ConventionalExtension }}"
|
||||
builds: [sonr]
|
||||
vendor: Sonr
|
||||
homepage: "https://onsonr.dev"
|
||||
@@ -126,23 +69,6 @@ nfpms:
|
||||
# Add these lines to match build config
|
||||
|
||||
brews:
|
||||
- name: hway
|
||||
ids: [hway]
|
||||
commit_author:
|
||||
name: goreleaserbot
|
||||
email: bot@goreleaser.com
|
||||
directory: Formula
|
||||
caveats: "Run a local hway node and access it with the hway proxy"
|
||||
homepage: "https://onsonr.dev"
|
||||
description: "Sonr is a decentralized, permissionless, and censorship-resistant identity network."
|
||||
dependencies:
|
||||
- name: ipfs
|
||||
repository:
|
||||
owner: onsonr
|
||||
name: homebrew-tap
|
||||
branch: master
|
||||
token: "{{ .Env.GITHUB_PERSONAL_AUTH_TOKEN }}"
|
||||
|
||||
- name: sonr
|
||||
ids: [sonr]
|
||||
commit_author:
|
||||
@@ -150,7 +76,7 @@ brews:
|
||||
email: bot@goreleaser.com
|
||||
directory: Formula
|
||||
caveats: "Run a local sonr node and access it with the hway proxy"
|
||||
homepage: "https://onsonr.dev"
|
||||
homepage: "https://onson.dev"
|
||||
description: "Sonr is a decentralized, permissionless, and censorship-resistant identity network."
|
||||
dependencies:
|
||||
- name: ipfs
|
||||
@@ -164,12 +90,15 @@ release:
|
||||
github:
|
||||
owner: onsonr
|
||||
name: sonr
|
||||
name_template: "Release {{.Version}}"
|
||||
name_template: "{{ .Tag }} | {{ .Env.RELEASE_DATE }}"
|
||||
draft: false
|
||||
replace_existing_draft: true
|
||||
replace_existing_artifacts: true
|
||||
extra_files:
|
||||
- glob: ./README*
|
||||
- glob: ./scripts/install.sh
|
||||
- glob: ./scripts/test_node.sh
|
||||
- glob: ./scripts/test_ics_node.sh
|
||||
|
||||
announce:
|
||||
telegram:
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
*out
|
||||
*logs
|
||||
*actions
|
||||
*notifications
|
||||
*tools
|
||||
plugins
|
||||
user_trunk.yaml
|
||||
user.yaml
|
||||
tmp
|
||||
@@ -0,0 +1,27 @@
|
||||
linters:
|
||||
disable:
|
||||
- unused # Disables unreachable code checking
|
||||
|
||||
run:
|
||||
# Exclude test files from analysis
|
||||
tests: false
|
||||
|
||||
# Define which files and directories to exclude
|
||||
issues:
|
||||
exclude-rules:
|
||||
# Exclude all test files
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- all
|
||||
|
||||
# Exclude specific directories
|
||||
exclude-dirs:
|
||||
- api/did/v1
|
||||
- api/dwn/v1
|
||||
- api/svc/v1
|
||||
- internal
|
||||
|
||||
# Exclude specific file patterns
|
||||
exclude-files:
|
||||
- ".*\\.pb\\.go$"
|
||||
- ".*_templ\\.go$"
|
||||
@@ -0,0 +1,4 @@
|
||||
# Following source doesn't work in most setups
|
||||
ignored:
|
||||
- SC1090
|
||||
- SC1091
|
||||
@@ -0,0 +1,2 @@
|
||||
# Prettier friendly markdownlint config (all formatting rules disabled)
|
||||
extends: markdownlint/style/prettier
|
||||
@@ -0,0 +1 @@
|
||||
edition = "2021"
|
||||
@@ -0,0 +1,7 @@
|
||||
enable=all
|
||||
source-path=SCRIPTDIR
|
||||
disable=SC2154
|
||||
|
||||
# If you're having issues with shellcheck following source, disable the errors via:
|
||||
# disable=SC1090
|
||||
# disable=SC1091
|
||||
@@ -0,0 +1,7 @@
|
||||
rules:
|
||||
quoted-strings:
|
||||
required: only-when-needed
|
||||
extra-allowed: ["{|}"]
|
||||
key-duplicates: {}
|
||||
octal-values:
|
||||
forbid-implicit-octal: true
|
||||
@@ -0,0 +1,41 @@
|
||||
# This file controls the behavior of Trunk: https://docs.trunk.io/cli
|
||||
# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
|
||||
version: 0.1
|
||||
cli:
|
||||
version: 1.22.8
|
||||
# Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins)
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.6.6
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
# Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes)
|
||||
runtimes:
|
||||
enabled:
|
||||
- go@1.23.0
|
||||
- node@18.20.5
|
||||
- python@3.10.8
|
||||
# This is the section where you manage your linters. (https://docs.trunk.io/check/configuration)
|
||||
lint:
|
||||
enabled:
|
||||
- actionlint@1.7.6
|
||||
- checkov@3.2.347
|
||||
- clippy@1.65.0
|
||||
- git-diff-check
|
||||
- gofmt@1.20.4
|
||||
- golangci-lint@1.62.2
|
||||
- hadolint@2.12.1-beta
|
||||
# - markdownlint@0.43.0
|
||||
- osv-scanner@1.9.2
|
||||
- prettier@3.4.2
|
||||
- rustfmt@1.65.0
|
||||
# - shellcheck@0.10.0
|
||||
# - shfmt@3.6.0
|
||||
- taplo@0.9.3
|
||||
- trufflehog@3.88.0
|
||||
actions:
|
||||
enabled:
|
||||
- trunk-announce
|
||||
- trunk-check-pre-push
|
||||
- trunk-fmt-pre-commit
|
||||
- trunk-upgrade-available
|
||||
+684
@@ -0,0 +1,684 @@
|
||||
## v0.6.2 (2025-01-06)
|
||||
|
||||
### Refactor
|
||||
|
||||
- simplify release process and remove unnecessary tasks
|
||||
- remove devcontainer configuration
|
||||
|
||||
## v0.6.1 (2024-12-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- convert highway sink schema to SQLite
|
||||
- **scopes**: add Web Authentication API documentation
|
||||
- add install script for Sonr binaries
|
||||
|
||||
### Fix
|
||||
|
||||
- Handle only 500 errors in ErrorHandler
|
||||
- Return only on 500 errors in error handler
|
||||
- update sqlc queries to match schema and use SQLite conventions
|
||||
- Rename DecodeWasmContext to decodeWasmContext
|
||||
- resolve lint errors in WASMMiddleware function
|
||||
- prevent automatic version bumps from dependabot
|
||||
- correct merge workflow to increment patch version
|
||||
|
||||
### Refactor
|
||||
|
||||
- remove outdated scopes
|
||||
- remove unnecessary seed message
|
||||
- Update sqlc queries to match schema and sqlite conventions
|
||||
- move gateway and vault components to new locations
|
||||
- **scopes**: simplify scopes.json structure
|
||||
- **scopes**: rename and reorganize scopes
|
||||
- **api**: remove unused Allocate RPC from Query service
|
||||
- remove postgresql tasks
|
||||
- remove unused AI PR body generator step
|
||||
- simplify Taskfile and remove unused chain configurations
|
||||
|
||||
## v0.6.0 (2024-12-24)
|
||||
|
||||
### Feat
|
||||
|
||||
- Add option to create draft issues from the new-issue script
|
||||
|
||||
### Refactor
|
||||
|
||||
- rename DID, DWN, and SVC modules to core-dids, core-dwns, and core-svcs respectively
|
||||
- rename MsgInitialize to MsgSpawn for clarity
|
||||
- rename scopes in .github/scopes.json for better clarity
|
||||
|
||||
## v0.5.28 (2024-12-22)
|
||||
|
||||
### Fix
|
||||
|
||||
- Sink
|
||||
|
||||
### Refactor
|
||||
|
||||
- update testnet configuration
|
||||
- optimize GitHub Actions workflow triggers (#1204)
|
||||
- Move embed
|
||||
|
||||
## v0.1.6 (2024-12-16)
|
||||
|
||||
## v0.5.26 (2024-12-13)
|
||||
|
||||
## v0.5.25 (2024-12-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- enable GoReleaser releases on tags and snapshots
|
||||
- automate release on tag and workflow dispatch
|
||||
|
||||
### Fix
|
||||
|
||||
- Correct regular expression for version tags in release workflow
|
||||
|
||||
## v0.5.24 (2024-12-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- prevent duplicate releases
|
||||
|
||||
## v0.5.23 (2024-12-11)
|
||||
|
||||
### Refactor
|
||||
|
||||
- rename scheduled release workflow to versioned release
|
||||
- remove changelog from release artifacts
|
||||
|
||||
## v0.5.22 (2024-12-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- Implement passkey-based authentication and registration flow
|
||||
- allow manual triggering of deployment workflow
|
||||
- add start-tui command for interactive mode
|
||||
- add coin selection and update passkey input in registration form
|
||||
- add hway command for Sonr DID gateway
|
||||
- Conditionally install process-compose only if binary not found
|
||||
- Add process-compose support with custom start and down commands
|
||||
- implement passkey registration flow
|
||||
- Improve createProfile form layout with wider max-width and enhanced spacing
|
||||
- improve index page UI with new navigation buttons and remove redundant settings buttons
|
||||
- Make input rows responsive with grid layout for mobile and desktop
|
||||
- enhance index page with additional settings buttons and style adjustments
|
||||
- implement passkey-based authentication
|
||||
- add support for Cloudsmith releases
|
||||
- add go dependency and enhance devbox environment variables
|
||||
- update create profile form placeholders and handle
|
||||
- add DID-based authentication middleware
|
||||
- Add validation for human verification slider sum in CreateProfile form
|
||||
- implement passkey registration flow
|
||||
- Update WebAuthn credential handling with modern browser standards
|
||||
- Streamline passkey registration with automatic form submission
|
||||
- Add credential parsing and logging in register finish handler
|
||||
- Add credential details row with icon after passkey creation
|
||||
- Add form validation for passkey credential input
|
||||
- implement passkey registration flow
|
||||
- Add hidden input to store passkey credential data for form submission
|
||||
- add CI workflow for deploying network
|
||||
- add hway binary support and Homebrew formula
|
||||
- remove username from passkey creation
|
||||
- implement passkey registration flow
|
||||
- add passkey creation functionality
|
||||
- add CNAME for onsonr.dev domain
|
||||
|
||||
### Fix
|
||||
|
||||
- use Unix domain sockets for devnet processes
|
||||
- correct workflow name and improve devnet deployment process
|
||||
- correct title of profile creation page
|
||||
- rename devbox start script to up and remove stop script
|
||||
- Consolidate archive configuration and add LICENSE file
|
||||
- Improve cross-browser passkey credential handling and encoding
|
||||
- Remove commented-out code in passkey registration script
|
||||
- remove line-clamp from tailwind config
|
||||
- remove unnecessary background and restart settings from process-compose.yaml
|
||||
- suppress process-compose server output and log to file
|
||||
|
||||
### Refactor
|
||||
|
||||
- remove unnecessary git fetch step in deploy workflow
|
||||
- remove obsolete interchain test dependencies
|
||||
- update index views to use new nebula components
|
||||
- move Wasm related code to pkg/common/wasm
|
||||
- migrate config package to pkg directory
|
||||
- migrate to new configuration system and model definitions
|
||||
- move session package to pkg directory
|
||||
- Refactor registration forms to use UI components
|
||||
- move gateway config to vault package
|
||||
- improve command line flag descriptions and variable names
|
||||
- refactor hway command to use echo framework for server
|
||||
- Update root command to load EnvImpl from cobra flags
|
||||
- Modify command flags and environment loading logic in cmds.go
|
||||
- improve build process and move process-compose.yaml
|
||||
- remove unused devbox.json and related configurations
|
||||
- Improve mobile layout responsiveness for Rows and Columns components
|
||||
- Remove max-w-fit from Rows component
|
||||
- replace session package with context package
|
||||
- rename database initialization function
|
||||
- move session management to dedicated database module
|
||||
- remove unused UI components related to wallet and index pages
|
||||
- consolidate handlers into single files
|
||||
- move gateway and vault packages to internal directory
|
||||
- Move registration form components to dedicated directory
|
||||
- remove unused devbox package
|
||||
- remove devbox configuration
|
||||
- move vault package to app directory
|
||||
- improve code structure within gateway package
|
||||
- move gateway package to app directory
|
||||
- move vault package internal components to root
|
||||
- migrate layout imports to common styles package
|
||||
- Move form templates and styles to common directory
|
||||
- consolidate authentication and DID handling logic
|
||||
- Improve WebAuthn credential handling and validation in register finish route
|
||||
- remove profile card component
|
||||
- Simplify passkey registration UI and move profile component inline
|
||||
- Update credential logging with transport and ID type
|
||||
- Update register handler to use protocol.CredentialDescriptor struct
|
||||
- Update credential handling to use protocol.CredentialDescriptor
|
||||
- improve profile card styling and functionality
|
||||
- Simplify session management and browser information extraction
|
||||
- Update PeerInfo to extract and store comprehensive device information
|
||||
- improve address display in property details
|
||||
- remove unused documentation generation script
|
||||
- replace sonr/pkg/styles/layout with nebula/ui/layout
|
||||
- migrate UI components to nebula module
|
||||
- improve scopes.json structure and update scripts for better usability
|
||||
|
||||
## v0.5.20 (2024-12-07)
|
||||
|
||||
### Refactor
|
||||
|
||||
- simplify CI workflow by removing redundant asset publishing steps
|
||||
|
||||
## v0.5.19 (2024-12-06)
|
||||
|
||||
### Feat
|
||||
|
||||
- add support for parent field and resources list in Capability message
|
||||
- add fast reflection methods for Capability and Resource
|
||||
- add gum package and update devbox configuration
|
||||
- add new button components and layout improvements
|
||||
|
||||
### Fix
|
||||
|
||||
- adjust fullscreen modal close button margin
|
||||
- update devbox lockfile
|
||||
- resolve rendering issue in login modal
|
||||
|
||||
### Refactor
|
||||
|
||||
- rename accaddr package to address
|
||||
- Update Credential table to match WebAuthn Credential Descriptor
|
||||
- Deployment setup
|
||||
- migrate build system from Taskfile to Makefile
|
||||
- rename Assertion to Account and update related code
|
||||
- remove unused TUI components
|
||||
- Move IPFS interaction functions to common package
|
||||
- remove dependency on DWN.pkl
|
||||
- remove unused dependencies and simplify module imports
|
||||
- Rename x/vault -> x/dwn and x/service -> x/svc
|
||||
- move resolver formatter to services package
|
||||
- remove web documentation
|
||||
- update devbox configuration and scripts
|
||||
- rename layout component to root
|
||||
- refactor authentication pages into their own modules
|
||||
- update templ version to v0.2.778 and remove unused air config
|
||||
- move signer implementation to mpc package
|
||||
|
||||
## v0.5.18 (2024-11-06)
|
||||
|
||||
## v0.5.17 (2024-11-05)
|
||||
|
||||
### Feat
|
||||
|
||||
- add remote client constructor
|
||||
- add avatar image components
|
||||
- add SVG CDN Illustrations to marketing architecture
|
||||
- **marketing**: refactor marketing page components
|
||||
- Refactor intro video component to use a proper script template
|
||||
- Move Alpine.js script initialization to separate component
|
||||
- Add intro video modal component
|
||||
- add homepage architecture section
|
||||
- add Hero section component with stats and buttons
|
||||
- **css**: add new utility classes for group hover
|
||||
- implement authentication register finish endpoint
|
||||
- add controller creation step to allocate
|
||||
- Update service module README based on protobuf files
|
||||
- Update x/macaroon/README.md with details from protobuf files
|
||||
- update Vault README with details from proto files
|
||||
|
||||
### Fix
|
||||
|
||||
- update file paths in error messages
|
||||
- update intro video modal script
|
||||
|
||||
### Refactor
|
||||
|
||||
- update marketing section architecture
|
||||
- change verification table id
|
||||
- **proto**: remove macaroon proto
|
||||
- rename ValidateBasic to Validate
|
||||
- rename session cookie key
|
||||
- remove unused sync-initial endpoint
|
||||
- remove formatter.go from service module
|
||||
|
||||
## v0.5.16 (2024-10-21)
|
||||
|
||||
### Fix
|
||||
|
||||
- include assets generation in wasm build
|
||||
|
||||
## v0.5.15 (2024-10-21)
|
||||
|
||||
## v0.5.14 (2024-10-21)
|
||||
|
||||
### Refactor
|
||||
|
||||
- remove StakingKeeper dependency from GlobalFeeDecorator
|
||||
|
||||
## v0.5.13 (2024-10-21)
|
||||
|
||||
### Feat
|
||||
|
||||
- add custom secp256k1 pubkey
|
||||
|
||||
### Refactor
|
||||
|
||||
- update gRPC client to use new request types
|
||||
- use RawPublicKey instead of PublicKey in macaroon issuer
|
||||
- improve error handling in DID module
|
||||
|
||||
## v0.5.12 (2024-10-18)
|
||||
|
||||
### Feat
|
||||
|
||||
- add User-Agent and Platform to session
|
||||
- introduce AuthState enum for authentication state
|
||||
|
||||
### Fix
|
||||
|
||||
- **version**: revert version bump to 0.5.11
|
||||
- **version**: update version to 0.5.12
|
||||
|
||||
### Refactor
|
||||
|
||||
- remove dependency on proto change detection
|
||||
- update asset publishing configuration
|
||||
|
||||
## v0.5.11 (2024-10-10)
|
||||
|
||||
### Feat
|
||||
|
||||
- nebula assets served from CDN
|
||||
- use CDN for nebula frontend assets
|
||||
- add static hero section content to homepage
|
||||
- add wrangler scripts for development, build, and deployment
|
||||
- remove build configuration
|
||||
- move gateway web code to dedicated directory
|
||||
- add PubKey fast reflection
|
||||
- **macaroon**: add transaction allowlist/denylist caveats
|
||||
- add PR labeler
|
||||
- **devbox**: remove hway start command
|
||||
- add GitHub Actions workflow for running tests
|
||||
- add workflow for deploying Hway to Cloudflare Workers
|
||||
- Publish configs to R2
|
||||
- integrate nebula UI with worker-assets-gen
|
||||
- extract reusable layout components
|
||||
- Implement service worker for IPFS vault
|
||||
- implement CDN support for assets
|
||||
- add payment method support
|
||||
- add support for public key management
|
||||
- add ModalForm component
|
||||
- add LoginStart and RegisterStart routes
|
||||
- implement authentication views
|
||||
- add json tags to config structs
|
||||
- implement templ forms for consent privacy, credential assert, credential register, and profile details
|
||||
- **vault**: introduce assembly of the initial vault
|
||||
- add client logos to homepage
|
||||
- add tailwind utility classes
|
||||
- implement new profile card component
|
||||
|
||||
### Fix
|
||||
|
||||
- Correct source directory for asset publishing
|
||||
- install dependencies before nebula build
|
||||
- update Schema service to use new API endpoint
|
||||
- fix broken logo image path
|
||||
|
||||
### Refactor
|
||||
|
||||
- remove unnecessary branch configuration from scheduled release workflow
|
||||
- update dwn configuration generation import path
|
||||
- use nebula/routes instead of nebula/global
|
||||
- move index template to routes package
|
||||
- remove cdn package and move assets to global styles
|
||||
- move nebula assets to hway build directory
|
||||
- remove docker build and deployment
|
||||
- rename internal/session package to internal/ctx
|
||||
- remove unused fields from
|
||||
- rename PR_TEMPLATE to PULL_REQUEST_TEMPLATE
|
||||
- remove devbox.json init hook
|
||||
- rename sonrd dockerfile to Dockerfile
|
||||
- remove unused dependency
|
||||
- rename 'global/cdn' to 'assets'
|
||||
- move CDN assets to separate folder
|
||||
- move Pkl module definitions to dedicated package
|
||||
- move CDN assets to js/ folder
|
||||
- remove unused component templates
|
||||
- move ui components to global
|
||||
- move view handlers to router package
|
||||
|
||||
## v0.5.10 (2024-10-07)
|
||||
|
||||
### Feat
|
||||
|
||||
- **blocks**: remove button component
|
||||
|
||||
## v0.5.9 (2024-10-06)
|
||||
|
||||
### Feat
|
||||
|
||||
- add Motr support
|
||||
- update UIUX PKL to utilize optional fields
|
||||
|
||||
### Fix
|
||||
|
||||
- Update source directory for asset publishing
|
||||
|
||||
## v0.5.8 (2024-10-04)
|
||||
|
||||
### Refactor
|
||||
|
||||
- Remove unused logs configuration
|
||||
|
||||
## v0.5.7 (2024-10-04)
|
||||
|
||||
### Feat
|
||||
|
||||
- **devbox**: use process-compose for testnet services
|
||||
- remove motr.mjs dependency
|
||||
- add markdown rendering to issue templates
|
||||
- update issue templates for better clarity
|
||||
- add issue templates for tracking and task issues
|
||||
- add issue templates for bug report and tracking
|
||||
|
||||
### Refactor
|
||||
|
||||
- update issue template headings
|
||||
- rename bug-report issue template to bug
|
||||
|
||||
## v0.5.6 (2024-10-03)
|
||||
|
||||
### Feat
|
||||
|
||||
- introduce docker-compose based setup
|
||||
- add hway and sonr processes to dev environment
|
||||
|
||||
## v0.5.5 (2024-10-03)
|
||||
|
||||
### Feat
|
||||
|
||||
- add rudimentary DidController table
|
||||
- update home section with new features
|
||||
- introduce Home model and refactor views
|
||||
- **nebula**: create Home model for home page
|
||||
|
||||
### Refactor
|
||||
|
||||
- reorganize pkl files for better separation of concerns
|
||||
- rename msg_server_test.go to rpc_test.go
|
||||
|
||||
## v0.5.4 (2024-10-02)
|
||||
|
||||
## v0.5.3 (2024-10-02)
|
||||
|
||||
### Fix
|
||||
|
||||
- remove unnecessary telegram message template
|
||||
|
||||
## v0.5.2 (2024-10-02)
|
||||
|
||||
### Feat
|
||||
|
||||
- **service**: integrate group module (#1104)
|
||||
|
||||
### Refactor
|
||||
|
||||
- revert version bump to 0.5.1
|
||||
|
||||
## v0.5.1 (2024-10-02)
|
||||
|
||||
### Refactor
|
||||
|
||||
- move Motr API to state package
|
||||
|
||||
## v0.5.0 (2024-10-02)
|
||||
|
||||
### Feat
|
||||
|
||||
- allow multiple macaroons with the same id
|
||||
|
||||
## v0.4.5 (2024-10-02)
|
||||
|
||||
### Feat
|
||||
|
||||
- **release**: add docker images for sonrd and motr
|
||||
- update homepage with new visual design
|
||||
- add DID to vault genesis schema
|
||||
- add video component
|
||||
- add video component
|
||||
- add hx-get attribute to primary button in hero section
|
||||
|
||||
### Fix
|
||||
|
||||
- use correct secret for docker login
|
||||
- **layout**: add missing favicon
|
||||
- **hero**: Use hx-swap for primary button to prevent flicker
|
||||
|
||||
### Refactor
|
||||
|
||||
- use single GITHUB_TOKEN for release workflow
|
||||
- update workflow variables
|
||||
|
||||
## v0.4.2 (2024-10-01)
|
||||
|
||||
### Refactor
|
||||
|
||||
- use single GITHUB_TOKEN for release workflow
|
||||
|
||||
## v0.4.1 (2024-10-01)
|
||||
|
||||
### Feat
|
||||
|
||||
- Implement session management
|
||||
- allow manual release triggers
|
||||
- add Input and RegistrationForm models
|
||||
- add new utility classes
|
||||
- add login and registration pages
|
||||
- add tailwindcss utilities
|
||||
- add support for ARM64 architecture
|
||||
- add DWN resolver field
|
||||
- add stats section to homepage
|
||||
- implement hero section using Pkl
|
||||
|
||||
### Fix
|
||||
|
||||
- **version**: update version number to 0.4.0
|
||||
- update release workflow to use latest tag
|
||||
- **versioning**: revert version to 0.9.0
|
||||
- **cta**: Fix typo in CTA title
|
||||
- change bento section title to reflect security focus
|
||||
- adjust hero image dimensions
|
||||
- **Input**: Change type from to
|
||||
- update hero image height in config.pkl
|
||||
|
||||
### Refactor
|
||||
|
||||
- move home page sections to home package
|
||||
- rename motrd to motr
|
||||
- update hero image dimensions
|
||||
- move nebula configuration to static file
|
||||
|
||||
## v0.4.0 (2024-09-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- add PKL schema for message formats
|
||||
- add Homebrew tap for sonr
|
||||
- update release workflow to use latest tag
|
||||
- **dwn**: add wasm build for dwn
|
||||
- add macaroon and oracle genesis states
|
||||
- add scheduled binary release workflow
|
||||
- introduce process-compose for process management
|
||||
- add counter animation to hero section
|
||||
- add registration page
|
||||
|
||||
### Fix
|
||||
|
||||
- Enable scheduled release workflow
|
||||
|
||||
### Refactor
|
||||
|
||||
- remove old changelog entries
|
||||
- rename buf-publish.yml to publish-assets.yml
|
||||
- remove unused field from
|
||||
- remove unnecessary checkout in scheduled-release workflow
|
||||
- rename build ID to sonr
|
||||
- remove unnecessary release existence check
|
||||
- move dwn wasm build to pkg directory
|
||||
|
||||
## v0.3.1 (2024-09-29)
|
||||
|
||||
### Refactor
|
||||
|
||||
- move nebula/pages to pkg/nebula/pages
|
||||
|
||||
## v0.3.0 (2024-09-29)
|
||||
|
||||
### Feat
|
||||
|
||||
- add buf.lock for proto definitions
|
||||
|
||||
### Fix
|
||||
|
||||
- remove unused linting rules
|
||||
- update proto breaking check target to master branch
|
||||
|
||||
### Refactor
|
||||
|
||||
- remove unused lock files and configurations
|
||||
|
||||
## v0.2.0 (2024-09-29)
|
||||
|
||||
### Feat
|
||||
|
||||
- disable goreleaser workflow
|
||||
- update workflows to include master branch
|
||||
- remove global style declaration
|
||||
- **oracle**: add oracle module
|
||||
- optimize IPFS configuration for better performance
|
||||
- add local IPFS bootstrap script and refactor devbox config
|
||||
- add AllocateVault HTTP endpoint
|
||||
- add WebAuthn credential management functionality
|
||||
- remove unused coins interface
|
||||
- remove global integrity proof from genesis state
|
||||
- add vault module
|
||||
- enable buf.build publishing on master and develop branches
|
||||
- add Gitflow workflow for syncing branches
|
||||
- add automated production release workflow
|
||||
- **ui**: implement profile page
|
||||
- add automated production release workflow
|
||||
- **did**: remove unused proto files
|
||||
- add enums.pulsar.go file for PermissionScope enum (#4)
|
||||
- add initial DID implementation
|
||||
- remove builder interface
|
||||
- add basic UI for block explorer
|
||||
- add Usage: pkl [OPTIONS] COMMAND [ARGS]...
|
||||
- use SQLite embedded driver
|
||||
- add DID method for each coin
|
||||
- Expand KeyType enum and update KeyInfo message in genesis.proto
|
||||
- Add whitelisted key types to genesis params
|
||||
- Add DID grants protobuf definition
|
||||
- Add fields to KeyInfo struct to distinguish CBOR and standard blockchain key types
|
||||
- Add new message types for AssetInfo, ChainInfo, Endpoint, ExplorerInfo, FeeInfo, and KeyInfo
|
||||
- run sonr-node container in testnet network and make network external
|
||||
- Add docker-compose.yaml file to start a Sonr testnet node
|
||||
- configure Sonr testnet environment
|
||||
- Update Dockerfile to start and run a testnet
|
||||
- add Equal methods for AssetInfo and ChainInfo types
|
||||
- Add ProveWitness and SyncVault RPCs
|
||||
- Add MsgRegisterService to handle service registration
|
||||
- Add MsgRegisterService to handle service registration
|
||||
- add enums.pulsar.go file for PermissionScope enum
|
||||
|
||||
### Fix
|
||||
|
||||
- ensure go version is up-to-date
|
||||
- use GITHUB_TOKEN for version bump workflow
|
||||
- update account table interface to use address, chain and network
|
||||
- **ci**: update docker vm release workflow with new token
|
||||
- use mnemonic phrases for test account keys
|
||||
- reduce motr proxy shutdown timeout
|
||||
- **nebula**: use bunx for tailwindcss build
|
||||
- **proto**: update protobuf message index numbers
|
||||
- **ante**: reduce POA rate floor and ceiling
|
||||
- Update proc_list_width in mprocs.yaml
|
||||
- Add service to database when registering
|
||||
- pin added did documents to local ipfs node
|
||||
- remove extra spaces in typeUrl
|
||||
- **release**: remove unnecessary quotes in tag pattern
|
||||
- remove unused imports and simplify KeyInfo message
|
||||
- bind node ports to localhost
|
||||
- Update docker-compose network name to dokploy-network
|
||||
- Update network name to dokploy
|
||||
- remove unused port mapping
|
||||
- Update docker-compose.yaml to use correct volume path
|
||||
- update docker-compose volume name
|
||||
- Update docker-compose.yaml to use shell directly for sonrd command
|
||||
- replace "sh" with "/bin/sh" in docker-compose.yaml command
|
||||
- Update runner image dependencies for debian-11
|
||||
- **deps**: update golang image to 1.21
|
||||
- **chains**: update nomic chain build target
|
||||
- Remove unused `Meta` message from `genesis.proto`
|
||||
- Add ProveWitness and SyncVault RPCs
|
||||
|
||||
### Refactor
|
||||
|
||||
- adjust source directory for config files (#1102)
|
||||
- Use actions/checkout@v4
|
||||
- remove unused master branch from CI workflow
|
||||
- rename github token secret
|
||||
- remove unnecessary x-cloak styles
|
||||
- optimize oracle genesis proto
|
||||
- remove unused code related to whitelisted assets
|
||||
- update buf publish source directory
|
||||
- adjust devbox configuration to reflect nebula changes
|
||||
- rename msg_server.go to rpc.go
|
||||
- remove devbox integration
|
||||
- move dwn package to app/config
|
||||
- move configuration files to app directory
|
||||
- extract root command creation to separate file
|
||||
- move ipfs setup to function
|
||||
- remove unnecessary proxy config
|
||||
- rename script to
|
||||
- move DWN proxy server logic to separate file
|
||||
- use htmx instead of dwn for vault client
|
||||
- remove unused environment variables
|
||||
- simplify verification method structure
|
||||
- use staking keeper in DID keeper
|
||||
- remove unused dependencies
|
||||
- remove unused image building workflow
|
||||
- add field to
|
||||
- Update KeyKind Enum to have proper naming conventions
|
||||
- Update `DIDNamespace` to have proper naming convention
|
||||
- expose ports directly in docker-compose
|
||||
- remove unused port mappings
|
||||
- streamline script execution
|
||||
- use CMD instead of ENTRYPOINT in Dockerfile
|
||||
- **deps**: Upgrade Debian base image to 11
|
||||
- Simplify the types and properties to keep a consistent structure for the blockchain
|
||||
- remove PERMISSION_SCOPE_IDENTIFIERS_ENS enum value
|
||||
+3
-38
@@ -1,41 +1,4 @@
|
||||
FROM jetpackio/devbox:latest AS sonrvm
|
||||
|
||||
# Installing your devbox project
|
||||
WORKDIR /code
|
||||
USER root:root
|
||||
|
||||
RUN mkdir -p /code && chown ${DEVBOX_USER}:${DEVBOX_USER} /code
|
||||
|
||||
USER ${DEVBOX_USER}:${DEVBOX_USER}
|
||||
|
||||
COPY --chown=${DEVBOX_USER}:${DEVBOX_USER} devbox.json devbox.json
|
||||
COPY --chown=${DEVBOX_USER}:${DEVBOX_USER} process-compose.yaml process-compose.yaml
|
||||
|
||||
RUN devbox run -- echo "Installed Packages."
|
||||
|
||||
ENTRYPOINT ["devbox", "run"]
|
||||
|
||||
# --------------------------------------------------------
|
||||
FROM jetpackio/devbox:latest AS sonr-runner
|
||||
|
||||
WORKDIR /code
|
||||
USER root:root
|
||||
|
||||
RUN mkdir -p /code && chown ${DEVBOX_USER}:${DEVBOX_USER} /code
|
||||
|
||||
USER ${DEVBOX_USER}:${DEVBOX_USER}
|
||||
|
||||
COPY --chown=${DEVBOX_USER}:${DEVBOX_USER} devbox.json devbox.json
|
||||
COPY --chown=${DEVBOX_USER}:${DEVBOX_USER} process-compose.yaml process-compose.yaml
|
||||
COPY --chown=${DEVBOX_USER}:${DEVBOX_USER} . .
|
||||
|
||||
RUN devbox run -- echo "Installed Packages."
|
||||
|
||||
RUN git config --global --add safe.directory /code
|
||||
ENTRYPOINT ["devbox", "run", "testnet"]
|
||||
|
||||
# --------------------------------------------------------
|
||||
FROM golang:1.22-alpine AS go-builder
|
||||
FROM golang:1.23-alpine AS go-builder
|
||||
|
||||
SHELL ["/bin/sh", "-ecuxo", "pipefail"]
|
||||
|
||||
@@ -68,6 +31,8 @@ RUN LEDGER_ENABLED=false BUILD_TAGS=muslc LINK_STATICALLY=true make build \
|
||||
# --------------------------------------------------------
|
||||
FROM debian:11-slim
|
||||
|
||||
LABEL org.opencontainers.image.source https://github.com/onsonr/sonr
|
||||
|
||||
COPY --from=go-builder /code/build/sonrd /usr/bin/sonrd
|
||||
|
||||
# Install dependencies for Debian 11
|
||||
|
||||
@@ -8,14 +8,16 @@ SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g')
|
||||
BINDIR ?= $(GOPATH)/bin
|
||||
SIMAPP = ./app
|
||||
|
||||
PC_PORT_NUM=42069
|
||||
PC_LOG_FILE=./sonr.log
|
||||
PC_SOCKET_PATH=/tmp/sonr-net.sock
|
||||
# Fetch from env
|
||||
RELEASE_DATE ?= $(shell date +%Y).$(shell date +%V).$(shell date +%u)
|
||||
VERSION ?= $(shell echo $(shell git describe --tags) | sed 's/^v//')
|
||||
COMMIT ?= $(shell git log -1 --format='%H')
|
||||
OS ?= $(shell uname -s)
|
||||
ROOT ?= $(shell git rev-parse --show-toplevel)
|
||||
|
||||
# for dockerized protobuf tools
|
||||
DOCKER := $(shell which docker)
|
||||
HTTPS_GIT := github.com/onsonr/sonr.git
|
||||
PROCESS_COMPOSE := $(shell which process-compose)
|
||||
|
||||
export GO111MODULE = on
|
||||
|
||||
@@ -75,8 +77,6 @@ ldflags := $(strip $(ldflags))
|
||||
BUILD_FLAGS := -tags "$(build_tags_comma_sep)" -ldflags '$(ldflags)' -trimpath
|
||||
|
||||
# The below include contains the tools and runsim targets.
|
||||
include contrib/devtools/Makefile
|
||||
|
||||
all: install lint test
|
||||
|
||||
build: go.sum
|
||||
@@ -87,6 +87,12 @@ else
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/sonrd ./cmd/sonrd
|
||||
endif
|
||||
|
||||
build-motr: go.sum
|
||||
GOOS=js GOARCH=wasm go build -o static/wasm/app.wasm ./cmd/motr/main.go
|
||||
|
||||
build-hway: go.sum
|
||||
go build -o build/hway ./cmd/hway
|
||||
|
||||
build-windows-client: go.sum
|
||||
GOOS=windows GOARCH=amd64 go build -mod=readonly $(BUILD_FLAGS) -o build/sonrd.exe ./cmd/sonrd
|
||||
|
||||
@@ -100,8 +106,17 @@ endif
|
||||
install: go.sum
|
||||
go install -mod=readonly $(BUILD_FLAGS) ./cmd/sonrd
|
||||
|
||||
install-hway: go.sum
|
||||
go install -mod=readonly ./cmd/hway
|
||||
|
||||
release: fmt-date
|
||||
@go install github.com/goreleaser/goreleaser/v2@latest
|
||||
RELEASE_DATE=$(RELEASE_DATE) goreleaser release --clean
|
||||
|
||||
|
||||
########################################
|
||||
### Tools & dependencies
|
||||
########################################
|
||||
|
||||
go-mod-cache: go.sum
|
||||
@echo "--> Download go modules to local cache"
|
||||
@@ -127,12 +142,9 @@ clean:
|
||||
distclean: clean
|
||||
rm -rf vendor/
|
||||
|
||||
init-env:
|
||||
@echo "Installing process-compose"
|
||||
sh scripts/init_env.sh
|
||||
|
||||
########################################
|
||||
### Testing
|
||||
########################################
|
||||
|
||||
test: test-unit
|
||||
test-all: test-race test-cover test-system
|
||||
@@ -184,7 +196,6 @@ format: format-tools
|
||||
|
||||
mod-tidy:
|
||||
go mod tidy
|
||||
cd interchaintest && go mod tidy
|
||||
|
||||
.PHONY: format-tools lint format mod-tidy
|
||||
|
||||
@@ -302,71 +313,41 @@ testnet-basic: setup-testnet
|
||||
sh-testnet: mod-tidy
|
||||
CHAIN_ID="sonr-testnet-1" BLOCK_TIME="1000ms" CLEAN=true sh scripts/test_node.sh
|
||||
|
||||
.PHONY: setup-testnet set-testnet-configs testnet testnet-basic sh-testnet
|
||||
.PHONY: setup-testnet set-testnet-configs testnet testnet-basic sh-testnet dop-testnet
|
||||
|
||||
###############################################################################
|
||||
### generation ###
|
||||
###############################################################################
|
||||
.PHONY: gen-pkl gen-templ
|
||||
|
||||
gen-pkl: init-env
|
||||
pkl-gen-go pkl/sonr.orm/UCAN.pkl
|
||||
pkl-gen-go pkl/sonr.orm/Models.pkl
|
||||
pkl-gen-go pkl/sonr.conf/Hway.pkl
|
||||
pkl-gen-go pkl/sonr.conf/Motr.pkl
|
||||
|
||||
gen-templ: init-env
|
||||
templ generate
|
||||
|
||||
|
||||
###############################################################################
|
||||
### custom builds ###
|
||||
###############################################################################
|
||||
.PHONY: build-motr build-hway logs-hway logs-sonr
|
||||
|
||||
build-motr:
|
||||
GOOS=js GOARCH=wasm go build -o static/wasm/app.wasm ./cmd/motr/main.go
|
||||
|
||||
build-hway: gen-templ
|
||||
go build -o build/hway ./cmd/hway
|
||||
|
||||
logs-hway: init-env
|
||||
bin/process-compose process logs hway --port $(PC_PORT_NUM) --follow
|
||||
|
||||
logs-sonr: init-env
|
||||
bin/process-compose process logs sonr --port $(PC_PORT_NUM) --follow
|
||||
|
||||
###############################################################################
|
||||
### Network Start/Stop ###
|
||||
### extra utils ###
|
||||
###############################################################################
|
||||
|
||||
.PHONY: deploy start start-tui start-uds stop stop-uds restart status
|
||||
push-docker:
|
||||
@docker build -t ghcr.io/onsonr/sonr:latest .
|
||||
@docker tag ghcr.io/onsonr/sonr:latest ghcr.io/onsonr/sonr:$(VERSION)
|
||||
@docker push ghcr.io/onsonr/sonr:latest
|
||||
@docker push ghcr.io/onsonr/sonr:$(VERSION)
|
||||
|
||||
start: build-hway init-env
|
||||
bin/process-compose up --port $(PC_PORT_NUM) --log-file $(PC_LOG_FILE) --detached -f deploy/process-compose.yaml
|
||||
status:
|
||||
@gh run ls -L 3
|
||||
@gum format -- "# Sonr ($OS-$VERSION)" "- ($(COMMIT)) $ROOT" "- $(RELEASE_DATE)"
|
||||
@sleep 3
|
||||
|
||||
start-tui: build-hway init-env
|
||||
bin/process-compose up --port $(PC_PORT_NUM) --log-file $(PC_LOG_FILE) -f deploy/process-compose.yaml
|
||||
release:
|
||||
@go install github.com/goreleaser/goreleaser/v2@latest
|
||||
@RELEASE_DATE=$(RELEASE_DATE) goreleaser release --clean
|
||||
|
||||
start-uds: build-hway init-env
|
||||
bin/process-compose up --use-uds --unix-socket $(PC_SOCKET_PATH) --log-file $(PC_LOG_FILE) --detached -f deploy/process-compose.yaml
|
||||
release-dry:
|
||||
@go install github.com/goreleaser/goreleaser/v2@latest
|
||||
@RELEASE_DATE=$(RELEASE_DATE) goreleaser release --snapshot --clean --skip=publish
|
||||
|
||||
stop: init-env
|
||||
bin/process-compose down --port $(PC_PORT_NUM)
|
||||
release-check:
|
||||
@go install github.com/goreleaser/goreleaser/v2@latest
|
||||
@RELEASE_DATE=$(RELEASE_DATE) goreleaser check
|
||||
|
||||
stop-uds: init-env
|
||||
bin/process-compose down --use-uds --unix-socket $(PC_SOCKET_PATH)
|
||||
|
||||
status: init-env
|
||||
bin/process-compose project state --port $(PC_PORT_NUM)
|
||||
validate-tag:
|
||||
@sh ./scripts/validate_tag.sh
|
||||
###############################################################################
|
||||
### help ###
|
||||
###############################################################################
|
||||
|
||||
deploy:
|
||||
cd ./proto && bunx buf dep update && bunx buf build && bunx buf push
|
||||
sh ./.github/scripts/upload_cdn.sh
|
||||
|
||||
help:
|
||||
@echo "Usage: make <target>"
|
||||
@echo ""
|
||||
@@ -378,7 +359,5 @@ help:
|
||||
@echo " sh-testnet : Shell local devnet"
|
||||
@echo " ictest-basic : Basic end-to-end test"
|
||||
@echo " ictest-ibc : IBC end-to-end test"
|
||||
@echo " templ : Generate templ files"
|
||||
@echo " vault : Build vault.wasm"
|
||||
|
||||
.PHONY: help
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
[](https://sonr.io)
|
||||
[](https://goreportcard.com/report/github.com/onsonr/sonr)
|
||||
[](https://sonarcloud.io/summary/new_code?id=sonr-io_sonr)
|
||||
[](https://cloudsmith.io/~sonr/repos/sonr/packages/detail/deb/sonrd/latest/a=amd64;xc=main;d=ubuntu%252Fxenial;t=binary/)
|
||||
|
||||
> Sonr is a combination of decentralized primitives. Fundamentally, it is a peer-to-peer identity and asset management system that leverages DID documents, Webauthn, and IPFS—providing users with a secure, portable decentralized identity.
|
||||
|
||||
@@ -38,4 +37,3 @@ Sonr would not have been possible without the direct and indirect support of the
|
||||
- [Forum](https://github.com/onsonr/sonr/discussions)
|
||||
- [Issues](https://github.com/onsonr/sonr/issues)
|
||||
- [Twitter](https://sonr.io/twitter)
|
||||
- [Dev Chat](https://sonr.io/discord)
|
||||
|
||||
+2515
-427
File diff suppressed because it is too large
Load Diff
+747
-2417
File diff suppressed because it is too large
Load Diff
+28
-3253
File diff suppressed because it is too large
Load Diff
+1
-127
@@ -19,10 +19,7 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Query_Params_FullMethodName = "/dwn.v1.Query/Params"
|
||||
Query_Schema_FullMethodName = "/dwn.v1.Query/Schema"
|
||||
Query_Allocate_FullMethodName = "/dwn.v1.Query/Allocate"
|
||||
Query_Sync_FullMethodName = "/dwn.v1.Query/Sync"
|
||||
Query_Params_FullMethodName = "/dwn.v1.Query/Params"
|
||||
)
|
||||
|
||||
// QueryClient is the client API for Query service.
|
||||
@@ -33,15 +30,6 @@ const (
|
||||
type QueryClient interface {
|
||||
// Params queries all parameters of the module.
|
||||
Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
|
||||
// Schema queries the DID document by its id. And returns the required PKL
|
||||
// information
|
||||
Schema(ctx context.Context, in *QuerySchemaRequest, opts ...grpc.CallOption) (*QuerySchemaResponse, error)
|
||||
// Allocate initializes a Target Vault available for claims with a compatible
|
||||
// Authentication mechanism. The default authentication mechanism is WebAuthn.
|
||||
Allocate(ctx context.Context, in *QueryAllocateRequest, opts ...grpc.CallOption) (*QueryAllocateResponse, error)
|
||||
// Sync queries the DID document by its id. And returns the required PKL
|
||||
// information
|
||||
Sync(ctx context.Context, in *QuerySyncRequest, opts ...grpc.CallOption) (*QuerySyncResponse, error)
|
||||
}
|
||||
|
||||
type queryClient struct {
|
||||
@@ -62,36 +50,6 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts .
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) Schema(ctx context.Context, in *QuerySchemaRequest, opts ...grpc.CallOption) (*QuerySchemaResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QuerySchemaResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Schema_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) Allocate(ctx context.Context, in *QueryAllocateRequest, opts ...grpc.CallOption) (*QueryAllocateResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryAllocateResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Allocate_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) Sync(ctx context.Context, in *QuerySyncRequest, opts ...grpc.CallOption) (*QuerySyncResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QuerySyncResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Sync_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
// All implementations must embed UnimplementedQueryServer
|
||||
// for forward compatibility.
|
||||
@@ -100,15 +58,6 @@ func (c *queryClient) Sync(ctx context.Context, in *QuerySyncRequest, opts ...gr
|
||||
type QueryServer interface {
|
||||
// Params queries all parameters of the module.
|
||||
Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
|
||||
// Schema queries the DID document by its id. And returns the required PKL
|
||||
// information
|
||||
Schema(context.Context, *QuerySchemaRequest) (*QuerySchemaResponse, error)
|
||||
// Allocate initializes a Target Vault available for claims with a compatible
|
||||
// Authentication mechanism. The default authentication mechanism is WebAuthn.
|
||||
Allocate(context.Context, *QueryAllocateRequest) (*QueryAllocateResponse, error)
|
||||
// Sync queries the DID document by its id. And returns the required PKL
|
||||
// information
|
||||
Sync(context.Context, *QuerySyncRequest) (*QuerySyncResponse, error)
|
||||
mustEmbedUnimplementedQueryServer()
|
||||
}
|
||||
|
||||
@@ -122,15 +71,6 @@ type UnimplementedQueryServer struct{}
|
||||
func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) Schema(context.Context, *QuerySchemaRequest) (*QuerySchemaResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Schema not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) Allocate(context.Context, *QueryAllocateRequest) (*QueryAllocateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Allocate not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) Sync(context.Context, *QuerySyncRequest) (*QuerySyncResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Sync not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {}
|
||||
func (UnimplementedQueryServer) testEmbeddedByValue() {}
|
||||
|
||||
@@ -170,60 +110,6 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_Schema_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QuerySchemaRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).Schema(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_Schema_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).Schema(ctx, req.(*QuerySchemaRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_Allocate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryAllocateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).Allocate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_Allocate_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).Allocate(ctx, req.(*QueryAllocateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_Sync_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QuerySyncRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).Sync(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_Sync_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).Sync(ctx, req.(*QuerySyncRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Query_ServiceDesc is the grpc.ServiceDesc for Query service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -235,18 +121,6 @@ var Query_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Params",
|
||||
Handler: _Query_Params_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Schema",
|
||||
Handler: _Query_Schema_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Allocate",
|
||||
Handler: _Query_Allocate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Sync",
|
||||
Handler: _Query_Sync_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "dwn/v1/query.proto",
|
||||
|
||||
@@ -1818,7 +1818,7 @@ func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_dwn_v1_tx_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
// MsgInitialize spawns a New Vault with Unclaimed State. This is a one-time
|
||||
// MsgSpawn spawns a New Vault with Unclaimed State. This is a one-time
|
||||
// operation that must be performed interacting with the Vault.
|
||||
//
|
||||
// Since: cosmos-sdk 0.47
|
||||
@@ -1869,8 +1869,8 @@ func (x *MsgInitialize) GetParams() *Params {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MsgInitializeResponse defines the response structure for executing a
|
||||
// MsgInitialize message.
|
||||
// MsgSpawnResponse defines the response structure for executing a
|
||||
// MsgSpawn message.
|
||||
//
|
||||
// Since: cosmos-sdk 0.47
|
||||
type MsgInitializeResponse struct {
|
||||
|
||||
@@ -33,7 +33,7 @@ type MsgClient interface {
|
||||
//
|
||||
// Since: cosmos-sdk 0.47
|
||||
UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error)
|
||||
// Initialize spawns a new Vault
|
||||
// Spawn spawns a new Vault
|
||||
Initialize(ctx context.Context, in *MsgInitialize, opts ...grpc.CallOption) (*MsgInitializeResponse, error)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ type MsgServer interface {
|
||||
//
|
||||
// Since: cosmos-sdk 0.47
|
||||
UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error)
|
||||
// Initialize spawns a new Vault
|
||||
// Spawn spawns a new Vault
|
||||
Initialize(context.Context, *MsgInitialize) (*MsgInitializeResponse, error)
|
||||
mustEmbedUnimplementedMsgServer()
|
||||
}
|
||||
|
||||
+1475
-498
File diff suppressed because it is too large
Load Diff
+1949
-28
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,9 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Query_Params_FullMethodName = "/svc.v1.Query/Params"
|
||||
Query_Params_FullMethodName = "/svc.v1.Query/Params"
|
||||
Query_OriginExists_FullMethodName = "/svc.v1.Query/OriginExists"
|
||||
Query_ResolveOrigin_FullMethodName = "/svc.v1.Query/ResolveOrigin"
|
||||
)
|
||||
|
||||
// QueryClient is the client API for Query service.
|
||||
@@ -30,6 +32,10 @@ const (
|
||||
type QueryClient interface {
|
||||
// Params queries all parameters of the module.
|
||||
Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
|
||||
// OriginExists queries if a given origin exists.
|
||||
OriginExists(ctx context.Context, in *QueryOriginExistsRequest, opts ...grpc.CallOption) (*QueryOriginExistsResponse, error)
|
||||
// ResolveOrigin queries the domain of a given service and returns its record with capabilities.
|
||||
ResolveOrigin(ctx context.Context, in *QueryResolveOriginRequest, opts ...grpc.CallOption) (*QueryResolveOriginResponse, error)
|
||||
}
|
||||
|
||||
type queryClient struct {
|
||||
@@ -50,6 +56,26 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts .
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) OriginExists(ctx context.Context, in *QueryOriginExistsRequest, opts ...grpc.CallOption) (*QueryOriginExistsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryOriginExistsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_OriginExists_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) ResolveOrigin(ctx context.Context, in *QueryResolveOriginRequest, opts ...grpc.CallOption) (*QueryResolveOriginResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryResolveOriginResponse)
|
||||
err := c.cc.Invoke(ctx, Query_ResolveOrigin_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
// All implementations must embed UnimplementedQueryServer
|
||||
// for forward compatibility.
|
||||
@@ -58,6 +84,10 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts .
|
||||
type QueryServer interface {
|
||||
// Params queries all parameters of the module.
|
||||
Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
|
||||
// OriginExists queries if a given origin exists.
|
||||
OriginExists(context.Context, *QueryOriginExistsRequest) (*QueryOriginExistsResponse, error)
|
||||
// ResolveOrigin queries the domain of a given service and returns its record with capabilities.
|
||||
ResolveOrigin(context.Context, *QueryResolveOriginRequest) (*QueryResolveOriginResponse, error)
|
||||
mustEmbedUnimplementedQueryServer()
|
||||
}
|
||||
|
||||
@@ -71,6 +101,12 @@ type UnimplementedQueryServer struct{}
|
||||
func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) OriginExists(context.Context, *QueryOriginExistsRequest) (*QueryOriginExistsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OriginExists not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) ResolveOrigin(context.Context, *QueryResolveOriginRequest) (*QueryResolveOriginResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ResolveOrigin not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {}
|
||||
func (UnimplementedQueryServer) testEmbeddedByValue() {}
|
||||
|
||||
@@ -110,6 +146,42 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_OriginExists_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryOriginExistsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).OriginExists(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_OriginExists_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).OriginExists(ctx, req.(*QueryOriginExistsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_ResolveOrigin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryResolveOriginRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).ResolveOrigin(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_ResolveOrigin_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).ResolveOrigin(ctx, req.(*QueryResolveOriginRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Query_ServiceDesc is the grpc.ServiceDesc for Query service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -121,6 +193,14 @@ var Query_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Params",
|
||||
Handler: _Query_Params_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "OriginExists",
|
||||
Handler: _Query_OriginExists_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ResolveOrigin",
|
||||
Handler: _Query_ResolveOrigin_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "svc/v1/query.proto",
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# Local Interchain Configurations
|
||||
|
||||
RUN:
|
||||
- `make testnet` *(full setup: docker image, binary, keys, and ibc testnet start)*
|
||||
- `spawn local-ic start testnet` *(Standalone start)*
|
||||
|
||||
## Documentation
|
||||
|
||||
* https://github.com/strangelove-ventures/interchaintest/tree/main/local-interchain
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
{
|
||||
"chains": [
|
||||
{
|
||||
"name": "core",
|
||||
"ibc_paths": ["ibc-connection-1"],
|
||||
"chain_id": "chainid-1",
|
||||
"denom": "usnr",
|
||||
"binary": "sonrd",
|
||||
"bech32_prefix": "idx",
|
||||
"docker_image": {
|
||||
"repository": "core",
|
||||
"version": "local"
|
||||
},
|
||||
"gas_prices": "0usnr",
|
||||
"chain_type": "cosmos",
|
||||
"coin_type": 118,
|
||||
"trusting_period": "336h",
|
||||
"gas_adjustment": 1.5,
|
||||
"number_vals": 1,
|
||||
"number_node": 0,
|
||||
"debugging": true,
|
||||
"block_time": "1000ms",
|
||||
"host_port_override": {
|
||||
"26657": "26657",
|
||||
"1317": "1317",
|
||||
"9090": "9090"
|
||||
},
|
||||
"encoding-options": ["wasm", "tokenfactory"],
|
||||
"config_file_overrides": [
|
||||
{
|
||||
"file": "config/config.toml",
|
||||
"paths": {
|
||||
"moniker": "localvalmoniker",
|
||||
"rpc.cors_allowed_origins": ["*"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"genesis": {
|
||||
"modify": [
|
||||
{
|
||||
"key": "app_state.gov.params.voting_period",
|
||||
"value": "15s"
|
||||
},
|
||||
{
|
||||
"key": "app_state.gov.params.expedited_voting_period",
|
||||
"value": "10s"
|
||||
},
|
||||
{
|
||||
"key": "app_state.gov.params.max_deposit_period",
|
||||
"value": "15s"
|
||||
},
|
||||
{
|
||||
"key": "app_state.gov.params.min_deposit.0.denom",
|
||||
"value": "usnr"
|
||||
},
|
||||
{
|
||||
"key": "app_state.gov.params.min_deposit.0.amount",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"accounts": [
|
||||
{
|
||||
"name": "acc0",
|
||||
"address": "idx1hj5fveer5cjtn4wd6wstzugjfdxzl0xpecp0nd",
|
||||
"amount": "10000000000usnr",
|
||||
"mnemonic": "decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry"
|
||||
},
|
||||
{
|
||||
"name": "acc1",
|
||||
"address": "idx1efd63aw40lxf3n4mhf7dzhjkr453axur9vjt6y",
|
||||
"amount": "10000000000usnr",
|
||||
"mnemonic": "wealth flavor believe regret funny network recall kiss grape useless pepper cram hint member few certain unveil rather brick bargain curious require crowd raise"
|
||||
}
|
||||
],
|
||||
"startup_commands": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "gaia",
|
||||
"chain_id": "localcosmos-1",
|
||||
"denom": "uatom",
|
||||
"binary": "gaiad",
|
||||
"bech32_prefix": "cosmos",
|
||||
"docker_image": {
|
||||
"version": "v9.1.0"
|
||||
},
|
||||
"block_time": "1000ms",
|
||||
"gas_prices": "0%DENOM%",
|
||||
"gas_adjustment": 2.0,
|
||||
"ibc_paths": ["ibc-connection-1"],
|
||||
"genesis": {
|
||||
"accounts": [
|
||||
{
|
||||
"name": "acc0",
|
||||
"address": "cosmos1hj5fveer5cjtn4wd6wstzugjfdxzl0xpxvjjvr",
|
||||
"amount": "10000000%DENOM%",
|
||||
"mnemonic": "decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
{
|
||||
"chains": [
|
||||
{
|
||||
"name": "core",
|
||||
"chain_id": "chainid-1",
|
||||
"denom": "usnr",
|
||||
"binary": "sonrd",
|
||||
"bech32_prefix": "idx",
|
||||
"docker_image": {
|
||||
"repository": "core",
|
||||
"version": "local"
|
||||
},
|
||||
"gas_prices": "0usnr",
|
||||
"chain_type": "cosmos",
|
||||
"coin_type": 118,
|
||||
"trusting_period": "336h",
|
||||
"gas_adjustment": 1.5,
|
||||
"number_vals": 1,
|
||||
"number_node": 0,
|
||||
"debugging": true,
|
||||
"block_time": "1000ms",
|
||||
"host_port_override": {
|
||||
"26657": "26657",
|
||||
"1317": "1317",
|
||||
"9090": "9090"
|
||||
},
|
||||
"encoding-options": ["wasm", "tokenfactory"],
|
||||
"config_file_overrides": [
|
||||
{
|
||||
"file": "config/config.toml",
|
||||
"paths": {
|
||||
"moniker": "localvalmoniker",
|
||||
"rpc.cors_allowed_origins": ["*"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"genesis": {
|
||||
"modify": [
|
||||
{
|
||||
"key": "app_state.gov.params.voting_period",
|
||||
"value": "15s"
|
||||
},
|
||||
{
|
||||
"key": "app_state.gov.params.expedited_voting_period",
|
||||
"value": "10s"
|
||||
},
|
||||
{
|
||||
"key": "app_state.gov.params.max_deposit_period",
|
||||
"value": "15s"
|
||||
},
|
||||
{
|
||||
"key": "app_state.gov.params.min_deposit.0.denom",
|
||||
"value": "usnr"
|
||||
},
|
||||
{
|
||||
"key": "app_state.gov.params.min_deposit.0.amount",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"accounts": [
|
||||
{
|
||||
"name": "acc0",
|
||||
"address": "idx1hj5fveer5cjtn4wd6wstzugjfdxzl0xpecp0nd",
|
||||
"amount": "10000000000usnr",
|
||||
"mnemonic": "decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry"
|
||||
},
|
||||
{
|
||||
"name": "acc1",
|
||||
"address": "idx1efd63aw40lxf3n4mhf7dzhjkr453axur9vjt6y",
|
||||
"amount": "10000000000usnr",
|
||||
"mnemonic": "wealth flavor believe regret funny network recall kiss grape useless pepper cram hint member few certain unveil rather brick bargain curious require crowd raise"
|
||||
}
|
||||
],
|
||||
"startup_commands": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"github.com/onsonr/sonr/crypto/ucan"
|
||||
"github.com/onsonr/sonr/internal/gateway"
|
||||
"github.com/onsonr/sonr/pkg/common/ipfs"
|
||||
config "github.com/onsonr/sonr/pkg/config/hway"
|
||||
"github.com/onsonr/sonr/pkg/database/sessions"
|
||||
"github.com/onsonr/sonr/pkg/didauth/producer"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Command line flags
|
||||
var (
|
||||
servePort int // Gateway http entry point (default 3000)
|
||||
configDir string // Hway config directory (default hway)
|
||||
sqliteFile string // SQLite database file (default hway.db)
|
||||
chainID string // Current chain ID (default sonr-testnet-1)
|
||||
ipfsGatewayURL string // IPFS gateway URL (default localhost:8080)
|
||||
sonrAPIURL string // Sonr API URL (default localhost:1317)
|
||||
sonrGrpcURL string // Sonr gRPC URL (default localhost:9090)
|
||||
sonrRPCURL string // Sonr RPC URL (default localhost:26657)
|
||||
)
|
||||
|
||||
func rootCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "hway",
|
||||
Short: "Sonr DID gateway",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
env, err := loadEnvImplFromArgs(args)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
e, err := setupServer(env)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := e.Start(fmt.Sprintf(":%d", env.GetServePort())); err != http.ErrServerClosed {
|
||||
log.Fatal(err)
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
cmd.Flags().IntVar(&servePort, "serve-port", 3000, "Port to serve the gateway on")
|
||||
cmd.Flags().StringVar(&configDir, "config-dir", "hway", "Directory to store config files")
|
||||
cmd.Flags().StringVar(&sqliteFile, "sqlite-file", "hway.db", "File to store sqlite database")
|
||||
cmd.Flags().StringVar(&chainID, "chain-id", "sonr-testnet-1", "Chain ID")
|
||||
cmd.Flags().StringVar(&ipfsGatewayURL, "ipfs-gateway-url", "localhost:8080", "IPFS gateway URL")
|
||||
cmd.Flags().StringVar(&sonrAPIURL, "sonr-api-url", "localhost:1317", "Sonr API URL")
|
||||
cmd.Flags().StringVar(&sonrGrpcURL, "sonr-grpc-url", "localhost:9090", "Sonr gRPC URL")
|
||||
cmd.Flags().StringVar(&sonrRPCURL, "sonr-rpc-url", "localhost:26657", "Sonr RPC URL")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func loadEnvImplFromArgs(args []string) (config.Hway, error) {
|
||||
cmd := rootCmd()
|
||||
if err := cmd.ParseFlags(args); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
env := &config.HwayImpl{
|
||||
ServePort: servePort,
|
||||
ConfigDir: configDir,
|
||||
SqliteFile: sqliteFile,
|
||||
ChainId: chainID,
|
||||
IpfsGatewayUrl: ipfsGatewayURL,
|
||||
SonrApiUrl: sonrAPIURL,
|
||||
SonrGrpcUrl: sonrGrpcURL,
|
||||
SonrRpcUrl: sonrRPCURL,
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
|
||||
// setupServer sets up the server
|
||||
func setupServer(env config.Hway) (*echo.Echo, error) {
|
||||
ipc, err := ipfs.NewClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db, err := sessions.NewGormDB(env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e := echo.New()
|
||||
e.IPExtractor = echo.ExtractIPDirect()
|
||||
e.Use(middleware.Logger())
|
||||
e.Use(middleware.Recover())
|
||||
e.Use(producer.Middleware(ipc, ucan.ServicePermissions))
|
||||
gateway.RegisterRoutes(e, env, db)
|
||||
return e, nil
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// main is the entry point for the application
|
||||
func main() {
|
||||
cmd := rootCmd()
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"syscall/js"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/vault"
|
||||
"github.com/onsonr/sonr/pkg/common/wasm"
|
||||
"github.com/onsonr/sonr/pkg/config/motr"
|
||||
"github.com/onsonr/sonr/pkg/didauth/controller"
|
||||
)
|
||||
|
||||
var (
|
||||
env *motr.Environment
|
||||
config *motr.Config
|
||||
err error
|
||||
)
|
||||
|
||||
func broadcastTx(this js.Value, args []js.Value) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func simulateTx(this js.Value, args []js.Value) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func processConfig(this js.Value, args []js.Value) interface{} {
|
||||
if len(args) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
configString := args[0].String()
|
||||
if err := json.Unmarshal([]byte(configString), &config); err != nil {
|
||||
println("Error parsing config:", err.Error())
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Load dwn config
|
||||
js.Global().Set("broadcastTx", js.FuncOf(broadcastTx))
|
||||
js.Global().Set("simulateTx", js.FuncOf(simulateTx))
|
||||
js.Global().Set("processConfig", js.FuncOf(processConfig))
|
||||
|
||||
e := echo.New()
|
||||
e.Use(wasm.ContextMiddleware)
|
||||
e.Use(controller.Middleware(nil))
|
||||
vault.RegisterRoutes(e, config)
|
||||
wasm.ServeFetch(e)
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
func main() {
|
||||
rootCmd := NewRootCmd()
|
||||
|
||||
if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil {
|
||||
log.NewLogger(rootCmd.OutOrStderr()).Error("failure when running app", "err", err)
|
||||
os.Exit(1)
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
###
|
||||
# Find OS and Go environment
|
||||
# GO contains the Go binary
|
||||
# FS contains the OS file separator
|
||||
###
|
||||
ifeq ($(OS),Windows_NT)
|
||||
GO := $(shell where go.exe 2> NUL)
|
||||
FS := "\\"
|
||||
else
|
||||
GO := $(shell command -v go 2> /dev/null)
|
||||
FS := "/"
|
||||
endif
|
||||
|
||||
ifeq ($(GO),)
|
||||
$(error could not find go. Is it in PATH? $(GO))
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
### Functions ###
|
||||
###############################################################################
|
||||
|
||||
go_get = $(if $(findstring Windows_NT,$(OS)),\
|
||||
IF NOT EXIST $(GITHUBDIR)$(FS)$(1)$(FS) ( mkdir $(GITHUBDIR)$(FS)$(1) ) else (cd .) &\
|
||||
IF NOT EXIST $(GITHUBDIR)$(FS)$(1)$(FS)$(2)$(FS) ( cd $(GITHUBDIR)$(FS)$(1) && git clone https://github.com/$(1)/$(2) ) else (cd .) &\
|
||||
,\
|
||||
mkdir -p $(GITHUBDIR)$(FS)$(1) &&\
|
||||
(test ! -d $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && cd $(GITHUBDIR)$(FS)$(1) && git clone https://github.com/$(1)/$(2)) || true &&\
|
||||
)\
|
||||
cd $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && git fetch origin && git checkout -q $(3)
|
||||
|
||||
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||
mkfile_dir := $(shell cd $(shell dirname $(mkfile_path)); pwd)
|
||||
|
||||
|
||||
###############################################################################
|
||||
### Tools ###
|
||||
###############################################################################
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN ?= $(PREFIX)/bin
|
||||
UNAME_S ?= $(shell uname -s)
|
||||
UNAME_M ?= $(shell uname -m)
|
||||
|
||||
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||
GITHUBDIR := $(GOPATH)$(FS)src$(FS)github.com
|
||||
|
||||
BUF_VERSION ?= 0.11.0
|
||||
|
||||
TOOLS_DESTDIR ?= $(GOPATH)/bin
|
||||
STATIK = $(TOOLS_DESTDIR)/statik
|
||||
RUNSIM = $(TOOLS_DESTDIR)/runsim
|
||||
GOLANGCI_LINT = $(TOOLS_DESTDIR)/golangci-lint
|
||||
|
||||
tools: tools-stamp
|
||||
tools-stamp: statik runsim golangci-lint
|
||||
# Create dummy file to satisfy dependency and avoid
|
||||
# rebuilding when this Makefile target is hit twice
|
||||
# in a row.
|
||||
touch $@
|
||||
|
||||
statik: $(STATIK)
|
||||
$(STATIK):
|
||||
@echo "Installing statik..."
|
||||
@(cd /tmp && go install github.com/rakyll/statik@v0.1.6)
|
||||
|
||||
# Install the runsim binary with a temporary workaround of entering an outside
|
||||
# directory as the "go get" command ignores the -mod option and will polute the
|
||||
# go.{mod, sum} files.
|
||||
#
|
||||
# ref: https://github.com/golang/go/issues/30515
|
||||
runsim: $(RUNSIM)
|
||||
$(RUNSIM):
|
||||
@echo "Installing runsim..."
|
||||
@(cd /tmp && go install github.com/cosmos/tools/cmd/runsim@v1.0.0)
|
||||
|
||||
golangci-lint: $(GOLANGCI_LINT)
|
||||
$(GOLANGCI_LINT):
|
||||
@echo "Installing golangci-lint..."
|
||||
@(cd /tmp && go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.47.0)
|
||||
|
||||
tools-clean:
|
||||
rm -f $(STATIK) $(GOLANGCI_LINT) $(RUNSIM)
|
||||
rm -f tools-stamp
|
||||
|
||||
.PHONY: tools-clean statik runsim
|
||||
@@ -1,6 +0,0 @@
|
||||
## Contributors
|
||||
|
||||
Thanks to the entire Cosmos SDK team and the contributors who put their efforts into making simulation testing
|
||||
easier to implement. 🤗
|
||||
|
||||
https://github.com/cosmos/cosmos-sdk/blob/master/contrib/devtools/Makefile
|
||||
@@ -601,11 +601,11 @@ func (p *PointBls12377G1) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *PointBls12377G1) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *PointBls12377G1) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -874,11 +874,11 @@ func (p *PointBls12377G2) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *PointBls12377G2) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *PointBls12377G2) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -573,11 +573,11 @@ func (p *PointBls12381G1) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *PointBls12381G1) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *PointBls12381G1) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -823,11 +823,11 @@ func (p *PointBls12381G2) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *PointBls12381G2) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *PointBls12381G2) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -336,14 +336,14 @@ func pointUnmarshalText(input []byte) (Point, error) {
|
||||
return curve.Point.FromAffineCompressed(buffer)
|
||||
}
|
||||
|
||||
func pointMarshalJson(point Point) ([]byte, error) {
|
||||
func pointMarshalJSON(point Point) ([]byte, error) {
|
||||
m := make(map[string]string, 2)
|
||||
m["type"] = point.CurveName()
|
||||
m["value"] = hex.EncodeToString(point.ToAffineCompressed())
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
func pointUnmarshalJson(input []byte) (Point, error) {
|
||||
func pointUnmarshalJSON(input []byte) (Point, error) {
|
||||
var m map[string]string
|
||||
|
||||
err := json.Unmarshal(input, &m)
|
||||
|
||||
@@ -682,11 +682,11 @@ func (p *PointEd25519) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *PointEd25519) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *PointEd25519) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -653,11 +653,11 @@ func (p *PointK256) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *PointK256) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *PointK256) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -701,11 +701,11 @@ func (p *BenchPointP256) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *BenchPointP256) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *BenchPointP256) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -651,11 +651,11 @@ func (p *PointP256) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *PointP256) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *PointP256) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -669,11 +669,11 @@ func (p *PointPallas) UnmarshalText(input []byte) error {
|
||||
}
|
||||
|
||||
func (p *PointPallas) MarshalJSON() ([]byte, error) {
|
||||
return pointMarshalJson(p)
|
||||
return pointMarshalJSON(p)
|
||||
}
|
||||
|
||||
func (p *PointPallas) UnmarshalJSON(input []byte) error {
|
||||
pt, err := pointUnmarshalJson(input)
|
||||
pt, err := pointUnmarshalJSON(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/libp2p/go-libp2p/core/crypto"
|
||||
mb "github.com/multiformats/go-multibase"
|
||||
varint "github.com/multiformats/go-varint"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeyPrefix indicates a decentralized identifier that uses the key method
|
||||
KeyPrefix = "did:key"
|
||||
// MulticodecKindRSAPubKey rsa-x509-pub https://github.com/multiformats/multicodec/pull/226
|
||||
MulticodecKindRSAPubKey = 0x1205
|
||||
// MulticodecKindEd25519PubKey ed25519-pub
|
||||
MulticodecKindEd25519PubKey = 0xed
|
||||
// MulticodecKindSecp256k1PubKey secp256k1-pub
|
||||
MulticodecKindSecp256k1PubKey = 0x1206
|
||||
)
|
||||
|
||||
// DID is a DID:key identifier
|
||||
type DID struct {
|
||||
crypto.PubKey
|
||||
}
|
||||
|
||||
// NewDID constructs an Identifier from a public key
|
||||
func NewDID(pub crypto.PubKey) (DID, error) {
|
||||
switch pub.Type() {
|
||||
case crypto.Ed25519, crypto.RSA, crypto.Secp256k1:
|
||||
return DID{PubKey: pub}, nil
|
||||
default:
|
||||
return DID{}, fmt.Errorf("unsupported key type: %s", pub.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// NewFromPubKey constructs an Identifier from a public key
|
||||
func NewFromPubKey(pub PubKey) DID {
|
||||
return DID{PubKey: pub}
|
||||
}
|
||||
|
||||
// MulticodecType indicates the type for this multicodec
|
||||
func (id DID) MulticodecType() uint64 {
|
||||
switch id.Type() {
|
||||
case crypto.RSA:
|
||||
return MulticodecKindRSAPubKey
|
||||
case crypto.Ed25519:
|
||||
return MulticodecKindEd25519PubKey
|
||||
case crypto.Secp256k1:
|
||||
return MulticodecKindSecp256k1PubKey
|
||||
default:
|
||||
panic("unexpected crypto type")
|
||||
}
|
||||
}
|
||||
|
||||
// String returns this did:key formatted as a string
|
||||
func (id DID) String() string {
|
||||
raw, err := id.Raw()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
t := id.MulticodecType()
|
||||
size := varint.UvarintSize(t)
|
||||
data := make([]byte, size+len(raw))
|
||||
n := varint.PutUvarint(data, t)
|
||||
copy(data[n:], raw)
|
||||
|
||||
b58BKeyStr, err := mb.Encode(mb.Base58BTC, data)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s:%s", KeyPrefix, b58BKeyStr)
|
||||
}
|
||||
|
||||
// VerifyKey returns the backing implementation for a public key, one of:
|
||||
// *rsa.PublicKey, ed25519.PublicKey
|
||||
func (id DID) VerifyKey() (interface{}, error) {
|
||||
rawPubBytes, err := id.Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch id.Type() {
|
||||
case crypto.RSA:
|
||||
verifyKeyiface, err := x509.ParsePKIXPublicKey(rawPubBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
verifyKey, ok := verifyKeyiface.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("public key is not an RSA key. got type: %T", verifyKeyiface)
|
||||
}
|
||||
return verifyKey, nil
|
||||
case crypto.Ed25519:
|
||||
return ed25519.PublicKey(rawPubBytes), nil
|
||||
case crypto.Secp256k1:
|
||||
// Handle both compressed and uncompressed Secp256k1 public keys
|
||||
if len(rawPubBytes) == 65 || len(rawPubBytes) == 33 {
|
||||
return rawPubBytes, nil
|
||||
}
|
||||
return nil, fmt.Errorf("invalid Secp256k1 public key length: %d", len(rawPubBytes))
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized Public Key type: %s", id.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// Parse turns a string into a key method ID
|
||||
func Parse(keystr string) (DID, error) {
|
||||
var id DID
|
||||
if !strings.HasPrefix(keystr, KeyPrefix) {
|
||||
return id, fmt.Errorf("decentralized identifier is not a 'key' type")
|
||||
}
|
||||
|
||||
keystr = strings.TrimPrefix(keystr, KeyPrefix+":")
|
||||
|
||||
enc, data, err := mb.Decode(keystr)
|
||||
if err != nil {
|
||||
return id, fmt.Errorf("decoding multibase: %w", err)
|
||||
}
|
||||
|
||||
if enc != mb.Base58BTC {
|
||||
return id, fmt.Errorf("unexpected multibase encoding: %s", mb.EncodingToStr[enc])
|
||||
}
|
||||
|
||||
keyType, n, err := varint.FromUvarint(data)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
switch keyType {
|
||||
case MulticodecKindRSAPubKey:
|
||||
pub, err := crypto.UnmarshalRsaPublicKey(data[n:])
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return DID{pub}, nil
|
||||
case MulticodecKindEd25519PubKey:
|
||||
pub, err := crypto.UnmarshalEd25519PublicKey(data[n:])
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return DID{pub}, nil
|
||||
case MulticodecKindSecp256k1PubKey:
|
||||
// Handle both compressed and uncompressed formats
|
||||
keyData := data[n:]
|
||||
if len(keyData) != 33 && len(keyData) != 65 {
|
||||
return id, fmt.Errorf("invalid Secp256k1 public key length: %d", len(keyData))
|
||||
}
|
||||
pub, err := crypto.UnmarshalSecp256k1PublicKey(keyData)
|
||||
if err != nil {
|
||||
return id, fmt.Errorf("failed to unmarshal Secp256k1 key: %w", err)
|
||||
}
|
||||
return DID{pub}, nil
|
||||
}
|
||||
|
||||
return id, fmt.Errorf("unrecognized key type multicodec prefix: %x", data[0])
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package keys
|
||||
|
||||
type DIDMethod string
|
||||
|
||||
const (
|
||||
DIDMethodKey DIDMethod = "key"
|
||||
DIDMethodSonr DIDMethod = "sonr"
|
||||
DIDMehthodBitcoin DIDMethod = "btcr"
|
||||
DIDMethodEthereum DIDMethod = "ethr"
|
||||
DIDMethodCbor DIDMethod = "cbor"
|
||||
DIDMethodCID DIDMethod = "cid"
|
||||
DIDMethodIPFS DIDMethod = "ipfs"
|
||||
)
|
||||
|
||||
func (d DIDMethod) String() string {
|
||||
return string(d)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package parsers
|
||||
@@ -0,0 +1,12 @@
|
||||
package parsers
|
||||
|
||||
type CosmosPrefix string
|
||||
|
||||
const (
|
||||
ATOMPrefix CosmosPrefix = "cosmos"
|
||||
AXELARPrefix CosmosPrefix = "axelar"
|
||||
EVMOSPrefix CosmosPrefix = "evmos"
|
||||
OSMOPrefix CosmosPrefix = "osmo"
|
||||
SONRPrefix CosmosPrefix = "idx"
|
||||
STARSPrefix CosmosPrefix = "stars"
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
package parsers
|
||||
@@ -0,0 +1 @@
|
||||
package parsers
|
||||
@@ -1,4 +1,4 @@
|
||||
package didkey
|
||||
package parsers
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
@@ -23,23 +23,23 @@ const (
|
||||
MulticodecKindSecp256k1PubKey = 0x1206
|
||||
)
|
||||
|
||||
// ID is a DID:key identifier
|
||||
type ID struct {
|
||||
// DIDKey is a DID:key identifier
|
||||
type DIDKey struct {
|
||||
crypto.PubKey
|
||||
}
|
||||
|
||||
// NewID constructs an Identifier from a public key
|
||||
func NewID(pub crypto.PubKey) (ID, error) {
|
||||
// NewKeyDID constructs an Identifier from a public key
|
||||
func NewKeyDID(pub crypto.PubKey) (DIDKey, error) {
|
||||
switch pub.Type() {
|
||||
case crypto.Ed25519, crypto.RSA, crypto.Secp256k1:
|
||||
return ID{PubKey: pub}, nil
|
||||
return DIDKey{PubKey: pub}, nil
|
||||
default:
|
||||
return ID{}, fmt.Errorf("unsupported key type: %s", pub.Type())
|
||||
return DIDKey{}, fmt.Errorf("unsupported key type: %s", pub.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// MulticodecType indicates the type for this multicodec
|
||||
func (id ID) MulticodecType() uint64 {
|
||||
func (id DIDKey) MulticodecType() uint64 {
|
||||
switch id.Type() {
|
||||
case crypto.RSA:
|
||||
return MulticodecKindRSAPubKey
|
||||
@@ -53,7 +53,7 @@ func (id ID) MulticodecType() uint64 {
|
||||
}
|
||||
|
||||
// String returns this did:key formatted as a string
|
||||
func (id ID) String() string {
|
||||
func (id DIDKey) String() string {
|
||||
raw, err := id.Raw()
|
||||
if err != nil {
|
||||
return ""
|
||||
@@ -75,7 +75,7 @@ func (id ID) String() string {
|
||||
|
||||
// VerifyKey returns the backing implementation for a public key, one of:
|
||||
// *rsa.PublicKey, ed25519.PublicKey
|
||||
func (id ID) VerifyKey() (interface{}, error) {
|
||||
func (id DIDKey) VerifyKey() (interface{}, error) {
|
||||
rawPubBytes, err := id.PubKey.Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -100,13 +100,13 @@ func (id ID) VerifyKey() (interface{}, error) {
|
||||
}
|
||||
return nil, fmt.Errorf("invalid Secp256k1 public key length: %d", len(rawPubBytes))
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized Public Key type: %s", id.PubKey.Type())
|
||||
return nil, fmt.Errorf("unrecognized Public Key type: %s", id.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// Parse turns a string into a key method ID
|
||||
func Parse(keystr string) (ID, error) {
|
||||
var id ID
|
||||
func Parse(keystr string) (DIDKey, error) {
|
||||
var id DIDKey
|
||||
if !strings.HasPrefix(keystr, KeyPrefix) {
|
||||
return id, fmt.Errorf("decentralized identifier is not a 'key' type")
|
||||
}
|
||||
@@ -133,13 +133,13 @@ func Parse(keystr string) (ID, error) {
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return ID{pub}, nil
|
||||
return DIDKey{pub}, nil
|
||||
case MulticodecKindEd25519PubKey:
|
||||
pub, err := crypto.UnmarshalEd25519PublicKey(data[n:])
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return ID{pub}, nil
|
||||
return DIDKey{pub}, nil
|
||||
case MulticodecKindSecp256k1PubKey:
|
||||
// Handle both compressed and uncompressed formats
|
||||
keyData := data[n:]
|
||||
@@ -150,7 +150,7 @@ func Parse(keystr string) (ID, error) {
|
||||
if err != nil {
|
||||
return id, fmt.Errorf("failed to unmarshal Secp256k1 key: %w", err)
|
||||
}
|
||||
return ID{pub}, nil
|
||||
return DIDKey{pub}, nil
|
||||
}
|
||||
|
||||
return id, fmt.Errorf("unrecognized key type multicodec prefix: %x", data[0])
|
||||
@@ -0,0 +1 @@
|
||||
package parsers
|
||||
@@ -0,0 +1 @@
|
||||
package parsers
|
||||
@@ -0,0 +1,86 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
|
||||
p2pcrypto "github.com/libp2p/go-libp2p/core/crypto"
|
||||
p2ppb "github.com/libp2p/go-libp2p/core/crypto/pb"
|
||||
"github.com/onsonr/sonr/crypto/core/curves"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
type PubKey interface {
|
||||
Bytes() []byte
|
||||
Raw() ([]byte, error)
|
||||
Equals(b p2pcrypto.Key) bool
|
||||
Type() p2ppb.KeyType
|
||||
Hex() string
|
||||
Verify(msg []byte, sig []byte) (bool, error)
|
||||
}
|
||||
|
||||
type pubKey struct {
|
||||
publicPoint curves.Point
|
||||
method string
|
||||
}
|
||||
|
||||
func NewPubKey(pk curves.Point) PubKey {
|
||||
return &pubKey{
|
||||
publicPoint: pk,
|
||||
}
|
||||
}
|
||||
|
||||
func (p pubKey) Bytes() []byte {
|
||||
return p.publicPoint.ToAffineCompressed()
|
||||
}
|
||||
|
||||
func (p pubKey) Raw() ([]byte, error) {
|
||||
return p.publicPoint.ToAffineCompressed(), nil
|
||||
}
|
||||
|
||||
func (p pubKey) Equals(b p2pcrypto.Key) bool {
|
||||
if b == nil {
|
||||
return false
|
||||
}
|
||||
apbz, err := b.Raw()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
bbz, err := p.Raw()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(apbz, bbz)
|
||||
}
|
||||
|
||||
func (p pubKey) Hex() string {
|
||||
return hex.EncodeToString(p.publicPoint.ToAffineCompressed())
|
||||
}
|
||||
|
||||
func (p pubKey) Type() p2ppb.KeyType {
|
||||
return p2ppb.KeyType_Secp256k1
|
||||
}
|
||||
|
||||
func (p pubKey) Verify(data []byte, sigBz []byte) (bool, error) {
|
||||
sig, err := deserializeSignature(sigBz)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
pp, err := getEcdsaPoint(p.Bytes())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
pk := &ecdsa.PublicKey{
|
||||
Curve: pp.Curve,
|
||||
X: pp.X,
|
||||
Y: pp.Y,
|
||||
}
|
||||
|
||||
// Hash the message using SHA3-256
|
||||
hash := sha3.New256()
|
||||
hash.Write(data)
|
||||
digest := hash.Sum(nil)
|
||||
|
||||
return ecdsa.Verify(pk, digest, sig.R, sig.S), nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/onsonr/sonr/crypto/core/curves"
|
||||
)
|
||||
|
||||
// getEcdsaPoint builds an elliptic curve point from a compressed byte slice
|
||||
func getEcdsaPoint(pubKey []byte) (*curves.EcPoint, error) {
|
||||
crv := curves.K256()
|
||||
x := new(big.Int).SetBytes(pubKey[1:33])
|
||||
y := new(big.Int).SetBytes(pubKey[33:])
|
||||
ecCurve, err := crv.ToEllipticCurve()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting curve: %v", err)
|
||||
}
|
||||
return &curves.EcPoint{X: x, Y: y, Curve: ecCurve}, nil
|
||||
}
|
||||
|
||||
// SerializeSecp256k1Signature serializes an ECDSA signature into a byte slice
|
||||
func serializeSignature(sig *curves.EcdsaSignature) ([]byte, error) {
|
||||
rBytes := sig.R.Bytes()
|
||||
sBytes := sig.S.Bytes()
|
||||
|
||||
sigBytes := make([]byte, 66) // V (1 byte) + R (32 bytes) + S (32 bytes)
|
||||
sigBytes[0] = byte(sig.V)
|
||||
copy(sigBytes[33-len(rBytes):33], rBytes)
|
||||
copy(sigBytes[66-len(sBytes):66], sBytes)
|
||||
return sigBytes, nil
|
||||
}
|
||||
|
||||
// DeserializeSecp256k1Signature deserializes an ECDSA signature from a byte slice
|
||||
func deserializeSignature(sigBytes []byte) (*curves.EcdsaSignature, error) {
|
||||
if len(sigBytes) != 66 {
|
||||
return nil, errors.New("malformed signature: not the correct size")
|
||||
}
|
||||
sig := &curves.EcdsaSignature{
|
||||
V: int(sigBytes[0]),
|
||||
R: new(big.Int).SetBytes(sigBytes[1:33]),
|
||||
S: new(big.Int).SetBytes(sigBytes[33:66]),
|
||||
}
|
||||
return sig, nil
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"github.com/onsonr/sonr/crypto/core/curves"
|
||||
"github.com/onsonr/sonr/crypto/core/protocol"
|
||||
"github.com/onsonr/sonr/crypto/keys"
|
||||
"github.com/onsonr/sonr/crypto/tecdsa/dklsv1/dkg"
|
||||
)
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Exported Generics │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
type (
|
||||
AliceOut *dkg.AliceOutput
|
||||
BobOut *dkg.BobOutput
|
||||
Point curves.Point
|
||||
Role string // Role is the type for the role
|
||||
Message *protocol.Message // Message is the protocol.Message that is used for MPC
|
||||
Signature *curves.EcdsaSignature // Signature is the type for the signature
|
||||
RefreshFunc interface{ protocol.Iterator } // RefreshFunc is the type for the refresh function
|
||||
SignFunc interface{ protocol.Iterator } // SignFunc is the type for the sign function
|
||||
)
|
||||
|
||||
const (
|
||||
RoleVal = "validator"
|
||||
RoleUser = "user"
|
||||
)
|
||||
|
||||
// Enclave defines the interface for key management operations
|
||||
type Enclave interface {
|
||||
Address() string // Address returns the Sonr address of the keyEnclave
|
||||
DID() keys.DID // DID returns the DID of the keyEnclave
|
||||
Export(key []byte) ([]byte, error) // Export returns encrypted enclave data
|
||||
Import(data []byte, key []byte) error // Import decrypts and loads enclave data
|
||||
IsValid() bool // IsValid returns true if the keyEnclave is valid
|
||||
PubKey() keys.PubKey // PubKey returns the public key of the keyEnclave
|
||||
Refresh() (Enclave, error) // Refresh returns a new keyEnclave
|
||||
Serialize() ([]byte, error) // Serialize returns the serialized keyEnclave
|
||||
Sign(data []byte) ([]byte, error) // Sign returns the signature of the data
|
||||
Verify(data []byte, sig []byte) (bool, error) // Verify returns true if the signature is valid
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func randNonce() []byte {
|
||||
nonce := make([]byte, 12)
|
||||
rand.Read(nonce)
|
||||
return nonce
|
||||
}
|
||||
|
||||
func TestKeyShareGeneration(t *testing.T) {
|
||||
t.Run("Generate Valid Enclave", func(t *testing.T) {
|
||||
nonce := randNonce()
|
||||
// Generate enclave
|
||||
enclave, err := GenEnclave(nonce)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, enclave)
|
||||
|
||||
// Validate enclave contents
|
||||
assert.True(t, enclave.IsValid())
|
||||
})
|
||||
|
||||
t.Run("Export and Import", func(t *testing.T) {
|
||||
nonce := randNonce()
|
||||
// Generate original enclave
|
||||
original, err := GenEnclave(nonce)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test key for encryption/decryption (32 bytes)
|
||||
testKey := []byte("test-key-12345678-test-key-123456")
|
||||
|
||||
// Test Export/Import
|
||||
t.Run("Full Enclave", func(t *testing.T) {
|
||||
// Export enclave
|
||||
data, err := original.Export(testKey)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, data)
|
||||
|
||||
// Create new empty enclave
|
||||
newEnclave, err := GenEnclave(nonce)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Import enclave
|
||||
err = newEnclave.Import(data, testKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify the imported enclave works by signing
|
||||
testData := []byte("test message")
|
||||
sig, err := newEnclave.Sign(testData)
|
||||
require.NoError(t, err)
|
||||
valid, err := newEnclave.Verify(testData, sig)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, valid)
|
||||
})
|
||||
|
||||
// Test Invalid Key
|
||||
t.Run("Invalid Key", func(t *testing.T) {
|
||||
data, err := original.Export(testKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
wrongKey := []byte("wrong-key-12345678")
|
||||
err = original.Import(data, wrongKey)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestEnclaveOperations(t *testing.T) {
|
||||
t.Run("Signing and Verification", func(t *testing.T) {
|
||||
nonce := randNonce()
|
||||
// Generate valid enclave
|
||||
enclave, err := GenEnclave(nonce)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test signing
|
||||
testData := []byte("test message")
|
||||
signature, err := enclave.Sign(testData)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, signature)
|
||||
|
||||
// Verify the signature
|
||||
valid, err := enclave.Verify(testData, signature)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, valid)
|
||||
|
||||
// Test invalid data verification
|
||||
invalidData := []byte("wrong message")
|
||||
valid, err = enclave.Verify(invalidData, signature)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, valid)
|
||||
})
|
||||
|
||||
t.Run("Address and Public Key", func(t *testing.T) {
|
||||
nonce := randNonce()
|
||||
enclave, err := GenEnclave(nonce)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test Address
|
||||
addr := enclave.Address()
|
||||
assert.NotEmpty(t, addr)
|
||||
assert.True(t, strings.HasPrefix(addr, "idx"))
|
||||
|
||||
// Test Public Key
|
||||
pubKey := enclave.PubKey()
|
||||
assert.NotNil(t, pubKey)
|
||||
assert.NotEmpty(t, pubKey.Bytes())
|
||||
})
|
||||
|
||||
t.Run("Refresh Operation", func(t *testing.T) {
|
||||
nonce := randNonce()
|
||||
enclave, err := GenEnclave(nonce)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test refresh
|
||||
refreshedEnclave, err := enclave.Refresh()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, refreshedEnclave)
|
||||
|
||||
// Verify refreshed enclave is valid
|
||||
assert.True(t, refreshedEnclave.IsValid())
|
||||
|
||||
// Verify it maintains the same address
|
||||
assert.Equal(t, enclave.Address(), refreshedEnclave.Address())
|
||||
})
|
||||
}
|
||||
|
||||
func TestEnclaveSerialization(t *testing.T) {
|
||||
t.Run("Marshal and Unmarshal", func(t *testing.T) {
|
||||
nonce := randNonce()
|
||||
// Generate original enclave
|
||||
original, err := GenEnclave(nonce)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, original)
|
||||
|
||||
// Marshal
|
||||
keyclave, ok := original.(*keyEnclave)
|
||||
require.True(t, ok)
|
||||
|
||||
data, err := keyclave.Serialize()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, data)
|
||||
|
||||
// Unmarshal
|
||||
restored := &keyEnclave{}
|
||||
err = restored.Unmarshal(data)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify restored enclave
|
||||
assert.Equal(t, keyclave.Addr, restored.Addr)
|
||||
assert.True(t, keyclave.PubPoint.Equal(restored.PubPoint))
|
||||
assert.True(t, restored.IsValid())
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/ecdsa"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/onsonr/sonr/crypto/core/curves"
|
||||
"github.com/onsonr/sonr/crypto/keys"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// keyEnclave implements the Enclave interface
|
||||
type keyEnclave struct {
|
||||
// Serialized fields
|
||||
Addr string `json:"address"`
|
||||
PubPoint curves.Point `json:"-"`
|
||||
PubBytes []byte `json:"pub_key"`
|
||||
ValShare Message `json:"val_share"`
|
||||
UserShare Message `json:"user_share"`
|
||||
|
||||
// Extra fields
|
||||
nonce []byte
|
||||
}
|
||||
|
||||
func newEnclave(valShare, userShare Message, nonce []byte) (Enclave, error) {
|
||||
pubPoint, err := getAlicePubPoint(valShare)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := computeSonrAddr(pubPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &keyEnclave{
|
||||
Addr: addr,
|
||||
PubPoint: pubPoint,
|
||||
ValShare: valShare,
|
||||
UserShare: userShare,
|
||||
nonce: nonce,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Address returns the Sonr address of the keyEnclave
|
||||
func (k *keyEnclave) Address() string {
|
||||
return k.Addr
|
||||
}
|
||||
|
||||
// DID returns the DID of the keyEnclave
|
||||
func (k *keyEnclave) DID() keys.DID {
|
||||
return keys.NewFromPubKey(k.PubKey())
|
||||
}
|
||||
|
||||
// Export returns encrypted enclave data
|
||||
func (k *keyEnclave) Export(key []byte) ([]byte, error) {
|
||||
data, err := k.Serialize()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize enclave: %w", err)
|
||||
}
|
||||
|
||||
hashedKey := hashKey(key)
|
||||
block, err := aes.NewCipher(hashedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aesgcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return aesgcm.Seal(nil, k.nonce, data, nil), nil
|
||||
}
|
||||
|
||||
// Import decrypts and loads enclave data
|
||||
func (k *keyEnclave) Import(data []byte, key []byte) error {
|
||||
hashedKey := hashKey(key)
|
||||
block, err := aes.NewCipher(hashedKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
aesgcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
decrypted, err := aesgcm.Open(nil, k.nonce, data, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return k.Unmarshal(decrypted)
|
||||
}
|
||||
|
||||
// IsValid returns true if the keyEnclave is valid
|
||||
func (k *keyEnclave) IsValid() bool {
|
||||
return k.PubPoint != nil && k.ValShare != nil && k.UserShare != nil && k.Addr != ""
|
||||
}
|
||||
|
||||
// PubKey returns the public key of the keyEnclave
|
||||
func (k *keyEnclave) PubKey() keys.PubKey {
|
||||
return keys.NewPubKey(k.PubPoint)
|
||||
}
|
||||
|
||||
// Refresh returns a new keyEnclave
|
||||
func (k *keyEnclave) Refresh() (Enclave, error) {
|
||||
refreshFuncVal, err := valRefreshFunc(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refreshFuncUser, err := userRefreshFunc(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ExecuteRefresh(refreshFuncVal, refreshFuncUser, k.nonce)
|
||||
}
|
||||
|
||||
// Sign returns the signature of the data
|
||||
func (k *keyEnclave) Sign(data []byte) ([]byte, error) {
|
||||
userSign, err := userSignFunc(k, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valSign, err := valSignFunc(k, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ExecuteSigning(valSign, userSign)
|
||||
}
|
||||
|
||||
// Verify returns true if the signature is valid
|
||||
func (k *keyEnclave) Verify(data []byte, sig []byte) (bool, error) {
|
||||
edSig, err := deserializeSignature(sig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
ePub, err := getEcdsaPoint(k.PubPoint.ToAffineUncompressed())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
pk := &ecdsa.PublicKey{
|
||||
Curve: ePub.Curve,
|
||||
X: ePub.X,
|
||||
Y: ePub.Y,
|
||||
}
|
||||
|
||||
// Hash the message using SHA3-256
|
||||
hash := sha3.New256()
|
||||
hash.Write(data)
|
||||
digest := hash.Sum(nil)
|
||||
|
||||
return ecdsa.Verify(pk, digest, edSig.R, edSig.S), nil
|
||||
}
|
||||
|
||||
// Marshal returns the JSON encoding of keyEnclave
|
||||
func (k *keyEnclave) Serialize() ([]byte, error) {
|
||||
// Store compressed public point bytes before marshaling
|
||||
k.PubBytes = k.PubPoint.ToAffineCompressed()
|
||||
return json.Marshal(k)
|
||||
}
|
||||
|
||||
// Unmarshal parses the JSON-encoded data and stores the result
|
||||
func (k *keyEnclave) Unmarshal(data []byte) error {
|
||||
if err := json.Unmarshal(data, k); err != nil {
|
||||
return err
|
||||
}
|
||||
// Reconstruct Point from bytes
|
||||
curve := curves.K256()
|
||||
point, err := curve.NewIdentityPoint().FromAffineCompressed(k.PubBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
k.PubPoint = point
|
||||
return nil
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/bech32"
|
||||
)
|
||||
|
||||
type (
|
||||
ExportedKeyset = []byte
|
||||
)
|
||||
|
||||
type Keyset interface {
|
||||
Address() string
|
||||
Val() *ValKeyshare
|
||||
ValJSON() string
|
||||
User() *UserKeyshare
|
||||
UserJSON() string
|
||||
}
|
||||
|
||||
type keyset struct {
|
||||
val *ValKeyshare
|
||||
user *UserKeyshare
|
||||
addr string
|
||||
}
|
||||
|
||||
func (k keyset) Address() string {
|
||||
return k.addr
|
||||
}
|
||||
|
||||
func (k keyset) Val() *ValKeyshare {
|
||||
return k.val
|
||||
}
|
||||
|
||||
func (k keyset) User() *UserKeyshare {
|
||||
return k.user
|
||||
}
|
||||
|
||||
func (k keyset) ValJSON() string {
|
||||
return k.val.String()
|
||||
}
|
||||
|
||||
func (k keyset) UserJSON() string {
|
||||
return k.user.String()
|
||||
}
|
||||
|
||||
func ComputeIssuerDID(pk []byte) (string, string, error) {
|
||||
addr, err := ComputeSonrAddr(pk)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return fmt.Sprintf("did:sonr:%s", addr), addr, nil
|
||||
}
|
||||
|
||||
func ComputeSonrAddr(pk []byte) (string, error) {
|
||||
sonrAddr, err := bech32.ConvertAndEncode("idx", pk)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return sonrAddr, nil
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/onsonr/sonr/crypto/core/protocol"
|
||||
"github.com/onsonr/sonr/crypto/tecdsa/dklsv1/dkg"
|
||||
)
|
||||
|
||||
// BaseKeyshare contains common fields and methods for both validator and user keyshares
|
||||
type BaseKeyshare struct {
|
||||
Message *protocol.Message `json:"message"`
|
||||
Role int `json:"role"`
|
||||
UncompressedPubKey []byte `json:"public_key"`
|
||||
CompressedPubKey []byte `json:"compressed_public_key"`
|
||||
}
|
||||
|
||||
func initFromAlice(aliceOut *dkg.AliceOutput, originalMsg *protocol.Message) BaseKeyshare {
|
||||
return BaseKeyshare{
|
||||
Message: originalMsg,
|
||||
Role: 1,
|
||||
UncompressedPubKey: aliceOut.PublicKey.ToAffineUncompressed(),
|
||||
CompressedPubKey: aliceOut.PublicKey.ToAffineCompressed(),
|
||||
}
|
||||
}
|
||||
|
||||
func initFromBob(bobOut *dkg.BobOutput, originalMsg *protocol.Message) BaseKeyshare {
|
||||
return BaseKeyshare{
|
||||
Message: originalMsg,
|
||||
Role: 2,
|
||||
UncompressedPubKey: bobOut.PublicKey.ToAffineUncompressed(),
|
||||
CompressedPubKey: bobOut.PublicKey.ToAffineCompressed(),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BaseKeyshare) GetPayloads() map[string][]byte {
|
||||
return b.Message.Payloads
|
||||
}
|
||||
|
||||
func (b *BaseKeyshare) GetMetadata() map[string]string {
|
||||
return b.Message.Metadata
|
||||
}
|
||||
|
||||
func (b *BaseKeyshare) GetPublicKey() []byte {
|
||||
return b.UncompressedPubKey
|
||||
}
|
||||
|
||||
func (b *BaseKeyshare) GetProtocol() string {
|
||||
return b.Message.Protocol
|
||||
}
|
||||
|
||||
func (b *BaseKeyshare) GetRole() int32 {
|
||||
return int32(b.Role)
|
||||
}
|
||||
|
||||
func (b *BaseKeyshare) GetVersion() uint32 {
|
||||
return uint32(b.Message.Version)
|
||||
}
|
||||
|
||||
func (b *BaseKeyshare) ECDSAPublicKey() (*ecdsa.PublicKey, error) {
|
||||
return ComputeEcdsaPublicKey(b.UncompressedPubKey)
|
||||
}
|
||||
|
||||
func (b *BaseKeyshare) ExtractMessage() *protocol.Message {
|
||||
return &protocol.Message{
|
||||
Payloads: b.GetPayloads(),
|
||||
Metadata: b.GetMetadata(),
|
||||
Protocol: b.GetProtocol(),
|
||||
Version: uint(b.GetVersion()),
|
||||
}
|
||||
}
|
||||
+15
-124
@@ -1,20 +1,13 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
genericecdsa "crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/onsonr/sonr/crypto/core/curves"
|
||||
"github.com/onsonr/sonr/crypto/core/protocol"
|
||||
"github.com/onsonr/sonr/crypto/tecdsa/dklsv1"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// NewKeyshareSource generates a new MPC keyshare
|
||||
func NewKeyset() (Keyset, error) {
|
||||
// GenEnclave generates a new MPC keyshare
|
||||
func GenEnclave(nonce []byte) (Enclave, error) {
|
||||
curve := curves.K256()
|
||||
valKs := dklsv1.NewAliceDkg(curve, protocol.Version1)
|
||||
userKs := dklsv1.NewBobDkg(curve, protocol.Version1)
|
||||
@@ -26,27 +19,15 @@ func NewKeyset() (Keyset, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valShare, err := NewValKeyshare(valRes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userRes, err := userKs.Result(protocol.Version1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userShare, err := NewUserKeyshare(userRes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addr, err := computeSonrAddr(valShare.CompressedPublicKey())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return keyset{val: valShare, user: userShare, addr: addr}, nil
|
||||
return newEnclave(valRes, userRes, nonce)
|
||||
}
|
||||
|
||||
// ExecuteSigning runs the MPC signing protocol
|
||||
func ExecuteSigning(signFuncVal SignFunc, signFuncUser SignFunc) (Signature, error) {
|
||||
func ExecuteSigning(signFuncVal SignFunc, signFuncUser SignFunc) ([]byte, error) {
|
||||
aErr, bErr := RunProtocol(signFuncVal, signFuncUser)
|
||||
if err := checkIteratedErrors(aErr, bErr); err != nil {
|
||||
return nil, err
|
||||
@@ -55,11 +36,19 @@ func ExecuteSigning(signFuncVal SignFunc, signFuncUser SignFunc) (Signature, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dklsv1.DecodeSignature(out)
|
||||
s, err := dklsv1.DecodeSignature(out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sig, err := serializeSignature(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// ExecuteRefresh runs the MPC refresh protocol
|
||||
func ExecuteRefresh(refreshFuncVal RefreshFunc, refreshFuncUser RefreshFunc) (Keyset, error) {
|
||||
func ExecuteRefresh(refreshFuncVal RefreshFunc, refreshFuncUser RefreshFunc, nonce []byte) (Enclave, error) {
|
||||
aErr, bErr := RunProtocol(refreshFuncVal, refreshFuncUser)
|
||||
if err := checkIteratedErrors(aErr, bErr); err != nil {
|
||||
return nil, err
|
||||
@@ -68,53 +57,11 @@ func ExecuteRefresh(refreshFuncVal RefreshFunc, refreshFuncUser RefreshFunc) (Ke
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valShare, err := NewValKeyshare(valRefreshResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userRefreshResult, err := refreshFuncUser.Result(protocol.Version1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userShare, err := NewUserKeyshare(userRefreshResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addr, err := computeSonrAddr(valShare.CompressedPublicKey())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return keyset{val: valShare, user: userShare, addr: addr}, nil
|
||||
}
|
||||
|
||||
// SerializeSecp256k1Signature serializes an ECDSA signature into a byte slice
|
||||
func SerializeSignature(sig Signature) ([]byte, error) {
|
||||
rBytes := sig.R.Bytes()
|
||||
sBytes := sig.S.Bytes()
|
||||
|
||||
sigBytes := make([]byte, 66) // V (1 byte) + R (32 bytes) + S (32 bytes)
|
||||
sigBytes[0] = byte(sig.V)
|
||||
copy(sigBytes[33-len(rBytes):33], rBytes)
|
||||
copy(sigBytes[66-len(sBytes):66], sBytes)
|
||||
return sigBytes, nil
|
||||
}
|
||||
|
||||
// DeserializeSecp256k1Signature deserializes an ECDSA signature from a byte slice
|
||||
func DeserializeSignature(sigBytes []byte) (Signature, error) {
|
||||
if len(sigBytes) != 66 {
|
||||
return nil, errors.New("malformed signature: not the correct size")
|
||||
}
|
||||
sig := &curves.EcdsaSignature{
|
||||
V: int(sigBytes[0]),
|
||||
R: new(big.Int).SetBytes(sigBytes[1:33]),
|
||||
S: new(big.Int).SetBytes(sigBytes[33:66]),
|
||||
}
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// VerifyMPCSignature verifies an MPC signature
|
||||
func VerifyMPCSignature(sig Signature, msg []byte, publicKey *ecdsa.PublicKey) bool {
|
||||
return ecdsa.Verify(publicKey, msg, sig.R, sig.S)
|
||||
return newEnclave(valRefreshResult, userRefreshResult, nonce)
|
||||
}
|
||||
|
||||
// For DKG bob starts first. For refresh and sign, Alice starts first.
|
||||
@@ -139,59 +86,3 @@ func RunProtocol(firstParty protocol.Iterator, secondParty protocol.Iterator) (e
|
||||
}
|
||||
return aErr, bErr
|
||||
}
|
||||
|
||||
// ComputeEcPoint builds an elliptic curve point from a compressed byte slice
|
||||
func ComputeEcPoint(pubKey []byte) (*curves.EcPoint, error) {
|
||||
crv := curves.K256()
|
||||
x := new(big.Int).SetBytes(pubKey[1:33])
|
||||
y := new(big.Int).SetBytes(pubKey[33:])
|
||||
ecCurve, err := crv.ToEllipticCurve()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting curve: %v", err)
|
||||
}
|
||||
return &curves.EcPoint{X: x, Y: y, Curve: ecCurve}, nil
|
||||
}
|
||||
|
||||
func ComputeEcdsaPublicKey(pubKey []byte) (*genericecdsa.PublicKey, error) {
|
||||
pk, err := ComputeEcPoint(pubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &genericecdsa.PublicKey{
|
||||
Curve: pk.Curve,
|
||||
X: pk.X,
|
||||
Y: pk.Y,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// VerifySignature verifies the signature of a message
|
||||
func VerifySignature(pk []byte, msg []byte, sig []byte) (bool, error) {
|
||||
pp, err := ComputeEcPoint(pk)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sigEd, err := DeserializeSignature(sig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
hash := sha3.New256()
|
||||
_, err = hash.Write(msg)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
digest := hash.Sum(nil)
|
||||
return curves.VerifyEcdsa(pp, digest[:], sigEd), nil
|
||||
}
|
||||
|
||||
func checkIteratedErrors(aErr, bErr error) error {
|
||||
if aErr == protocol.ErrProtocolFinished && bErr == protocol.ErrProtocolFinished {
|
||||
return nil
|
||||
}
|
||||
if aErr != protocol.ErrProtocolFinished {
|
||||
return aErr
|
||||
}
|
||||
if bErr != protocol.ErrProtocolFinished {
|
||||
return bErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/bech32"
|
||||
"github.com/onsonr/sonr/crypto/core/curves"
|
||||
"github.com/onsonr/sonr/crypto/core/protocol"
|
||||
"github.com/onsonr/sonr/crypto/tecdsa/dklsv1"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
var ErrInvalidKeyshareRole = errors.New("invalid keyshare role")
|
||||
|
||||
type Role int
|
||||
|
||||
const (
|
||||
RoleUnknown Role = iota
|
||||
RoleUser
|
||||
RoleValidator
|
||||
)
|
||||
|
||||
func (r Role) IsUser() bool {
|
||||
return r == RoleUser
|
||||
}
|
||||
|
||||
func (r Role) IsValidator() bool {
|
||||
return r == RoleValidator
|
||||
}
|
||||
|
||||
// Message is the protocol.Message that is used for MPC
|
||||
type Message *protocol.Message
|
||||
|
||||
type Signature *curves.EcdsaSignature
|
||||
|
||||
// RefreshFunc is the type for the refresh function
|
||||
type RefreshFunc interface {
|
||||
protocol.Iterator
|
||||
}
|
||||
|
||||
// SignFunc is the type for the sign function
|
||||
type SignFunc interface {
|
||||
protocol.Iterator
|
||||
}
|
||||
|
||||
type ValKeyshare struct {
|
||||
BaseKeyshare
|
||||
encoded string
|
||||
}
|
||||
|
||||
func computeSonrAddr(pk []byte) (string, error) {
|
||||
sonrAddr, err := bech32.ConvertAndEncode("idx", pk)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return sonrAddr, nil
|
||||
}
|
||||
|
||||
func NewValKeyshare(msg *protocol.Message) (*ValKeyshare, error) {
|
||||
vks := new(ValKeyshare)
|
||||
encoded, err := protocol.EncodeMessage(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valShare, err := dklsv1.DecodeAliceDkgResult(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vks.BaseKeyshare = initFromAlice(valShare, msg)
|
||||
vks.encoded = encoded
|
||||
return vks, nil
|
||||
}
|
||||
|
||||
func (v *ValKeyshare) RefreshFunc() (RefreshFunc, error) {
|
||||
curve := curves.K256()
|
||||
return dklsv1.NewAliceRefresh(curve, v.ExtractMessage(), protocol.Version1)
|
||||
}
|
||||
|
||||
func (v *ValKeyshare) SignFunc(msg []byte) (SignFunc, error) {
|
||||
curve := curves.K256()
|
||||
return dklsv1.NewAliceSign(curve, sha3.New256(), msg, v.ExtractMessage(), protocol.Version1)
|
||||
}
|
||||
|
||||
func (v *ValKeyshare) String() string {
|
||||
return v.encoded
|
||||
}
|
||||
|
||||
// PublicKey returns the uncompressed public key (65 bytes)
|
||||
func (v *ValKeyshare) PublicKey() []byte {
|
||||
return v.UncompressedPubKey
|
||||
}
|
||||
|
||||
// CompressedPublicKey returns the compressed public key (33 bytes)
|
||||
func (v *ValKeyshare) CompressedPublicKey() []byte {
|
||||
return v.CompressedPubKey
|
||||
}
|
||||
|
||||
type UserKeyshare struct {
|
||||
BaseKeyshare
|
||||
encoded string
|
||||
}
|
||||
|
||||
func NewUserKeyshare(msg *protocol.Message) (*UserKeyshare, error) {
|
||||
uks := new(UserKeyshare)
|
||||
encoded, err := protocol.EncodeMessage(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := dklsv1.DecodeBobDkgResult(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uks.BaseKeyshare = initFromBob(out, msg)
|
||||
uks.encoded = encoded
|
||||
return uks, nil
|
||||
}
|
||||
|
||||
func (u *UserKeyshare) RefreshFunc() (RefreshFunc, error) {
|
||||
curve := curves.K256()
|
||||
return dklsv1.NewBobRefresh(curve, u.ExtractMessage(), protocol.Version1)
|
||||
}
|
||||
|
||||
func (u *UserKeyshare) SignFunc(msg []byte) (SignFunc, error) {
|
||||
curve := curves.K256()
|
||||
return dklsv1.NewBobSign(curve, sha3.New256(), msg, u.ExtractMessage(), protocol.Version1)
|
||||
}
|
||||
|
||||
func (u *UserKeyshare) String() string {
|
||||
return u.encoded
|
||||
}
|
||||
|
||||
// PublicKey returns the uncompressed public key (65 bytes)
|
||||
func (u *UserKeyshare) PublicKey() []byte {
|
||||
return u.UncompressedPubKey
|
||||
}
|
||||
|
||||
// CompressedPublicKey returns the compressed public key (33 bytes)
|
||||
func (u *UserKeyshare) CompressedPublicKey() []byte {
|
||||
return u.CompressedPubKey
|
||||
}
|
||||
|
||||
func encodeMessage(m *protocol.Message) (string, error) {
|
||||
return protocol.EncodeMessage(m)
|
||||
}
|
||||
|
||||
func decodeMessage(s string) (*protocol.Message, error) {
|
||||
return protocol.DecodeMessage(s)
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package spec
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
)
|
||||
|
||||
// MPCSigningMethod implements the SigningMethod interface for MPC-based signing
|
||||
type MPCSigningMethod struct {
|
||||
Name string
|
||||
ks ucanKeyshare
|
||||
}
|
||||
|
||||
// NewJWTSigningMethod creates a new MPC signing method with the given keyshare source
|
||||
func NewJWTSigningMethod(name string, ks ucanKeyshare) *MPCSigningMethod {
|
||||
return &MPCSigningMethod{
|
||||
Name: name,
|
||||
ks: ks,
|
||||
}
|
||||
}
|
||||
|
||||
// Alg returns the signing method's name
|
||||
func (m *MPCSigningMethod) Alg() string {
|
||||
return m.Name
|
||||
}
|
||||
|
||||
// Verify verifies the signature using the MPC public key
|
||||
func (m *MPCSigningMethod) Verify(signingString, signature string, key interface{}) error {
|
||||
// // Decode the signature
|
||||
// sig, err := base64.RawURLEncoding.DecodeString(signature)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // Hash the signing string
|
||||
// hasher := sha256.New()
|
||||
// hasher.Write([]byte(signingString))
|
||||
// digest := hasher.Sum(nil)
|
||||
// valid, err := m.ks.valShare.PublicKey().Verify(digest, sig)
|
||||
// if !valid || err != nil {
|
||||
// return fmt.Errorf("invalid signature")
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sign signs the data using MPC
|
||||
func (m *MPCSigningMethod) Sign(signingString string, key interface{}) (string, error) {
|
||||
// Hash the signing string
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
// digest := hasher.Sum(nil)
|
||||
//
|
||||
// // Create signing functions
|
||||
// signFunc, err := m.ks.userShare.SignFunc(digest)
|
||||
// if err != nil {
|
||||
// return "", fmt.Errorf("failed to create sign function: %w", err)
|
||||
// }
|
||||
//
|
||||
// valSignFunc, err := m.ks.valShare.SignFunc(digest)
|
||||
// if err != nil {
|
||||
// return "", fmt.Errorf("failed to create validator sign function: %w", err)
|
||||
// }
|
||||
|
||||
// // Run the signing protocol
|
||||
// sig, err := mpc.ExecuteSigning(valSignFunc, signFunc)
|
||||
// if err != nil {
|
||||
// return "", fmt.Errorf("failed to run sign protocol: %w", err)
|
||||
// }
|
||||
|
||||
// Encode the signature
|
||||
// encoded := base64.RawURLEncoding.EncodeToString(sig)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Register the MPC signing method
|
||||
jwt.RegisterSigningMethod("MPC256", func() jwt.SigningMethod {
|
||||
return &MPCSigningMethod{
|
||||
Name: "MPC256",
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -5,9 +5,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
"github.com/onsonr/sonr/crypto/keys"
|
||||
"github.com/onsonr/sonr/crypto/ucan"
|
||||
"github.com/onsonr/sonr/crypto/ucan/didkey"
|
||||
"lukechampine.com/blake3"
|
||||
)
|
||||
|
||||
@@ -23,21 +22,18 @@ type KeyshareSource interface {
|
||||
UCANParser() *ucan.TokenParser
|
||||
}
|
||||
|
||||
func NewSource(ks mpc.Keyset) (KeyshareSource, error) {
|
||||
val := ks.Val()
|
||||
user := ks.User()
|
||||
iss, addr, err := ComputeIssuerDID(val.GetPublicKey())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ucanKeyshare{
|
||||
userShare: user,
|
||||
valShare: val,
|
||||
addr: addr,
|
||||
issuerDID: iss,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// func NewSource(ks mpc.KeyEnclave) (KeyshareSource, error) {
|
||||
// iss, addr, err := getIssuerDID(val.PublicKey())
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// return ucanKeyshare{
|
||||
// issuerDID: iss,
|
||||
// addr: addr,
|
||||
// }, nil
|
||||
// }
|
||||
//
|
||||
// Address returns the address of the keyshare
|
||||
func (k ucanKeyshare) Address() string {
|
||||
return k.addr
|
||||
@@ -61,33 +57,32 @@ func (k ucanKeyshare) ChainCode() ([]byte, error) {
|
||||
|
||||
// DefaultOriginToken returns a default token with the keyshare's issuer as the audience
|
||||
func (k ucanKeyshare) OriginToken() (*Token, error) {
|
||||
att := ucan.NewSmartAccount(k.addr)
|
||||
// att := ucan.NewSmartAccount(k.addr)
|
||||
zero := time.Time{}
|
||||
return k.NewOriginToken(k.issuerDID, att, nil, zero, zero)
|
||||
// return k.NewOriginToken(k.issuerDID, att, nil, zero, zero)
|
||||
return k.newToken(k.issuerDID, nil, nil, nil, zero, zero)
|
||||
}
|
||||
|
||||
func (k ucanKeyshare) SignData(data []byte) ([]byte, error) {
|
||||
// Create signing functions
|
||||
signFunc, err := k.userShare.SignFunc(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create sign function: %w", err)
|
||||
}
|
||||
|
||||
valSignFunc, err := k.valShare.SignFunc(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create validator sign function: %w", err)
|
||||
}
|
||||
// // Create signing functions
|
||||
// signFunc, err := k.userShare.SignFunc(data)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to create sign function: %w", err)
|
||||
// }
|
||||
//
|
||||
// valSignFunc, err := k.valShare.SignFunc(data)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to create validator sign function: %w", err)
|
||||
// }
|
||||
|
||||
// Run the signing protocol
|
||||
sig, err := mpc.ExecuteSigning(valSignFunc, signFunc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to run sign protocol: %w", err)
|
||||
}
|
||||
return mpc.SerializeSignature(sig)
|
||||
// return mpc.ExecuteSigning(valSignFunc, signFunc)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (k ucanKeyshare) VerifyData(data []byte, sig []byte) (bool, error) {
|
||||
return mpc.VerifySignature(k.userShare.PublicKey(), data, sig)
|
||||
return false, nil
|
||||
// return k.valShare.PublicKey().Verify(data, sig)
|
||||
}
|
||||
|
||||
// TokenParser returns a token parser that can be used to parse tokens
|
||||
@@ -107,7 +102,6 @@ func (k ucanKeyshare) UCANParser() *ucan.TokenParser {
|
||||
if key == ucan.CapKey {
|
||||
cap = val
|
||||
} else {
|
||||
rsc = ucan.NewStringLengthResource(key, val)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +121,6 @@ func (k ucanKeyshare) UCANParser() *ucan.TokenParser {
|
||||
type customDIDPubKeyResolver struct{}
|
||||
|
||||
// ResolveDIDKey extracts a public key from a did:key string
|
||||
func (customDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (didkey.ID, error) {
|
||||
return didkey.Parse(didStr)
|
||||
func (customDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (keys.DID, error) {
|
||||
return keys.Parse(didStr)
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/bech32"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
"github.com/onsonr/sonr/crypto/keys"
|
||||
"github.com/onsonr/sonr/crypto/ucan"
|
||||
)
|
||||
|
||||
@@ -30,9 +30,6 @@ var (
|
||||
)
|
||||
|
||||
type ucanKeyshare struct {
|
||||
userShare *mpc.UserKeyshare
|
||||
valShare *mpc.ValKeyshare
|
||||
|
||||
addr string
|
||||
issuerDID string
|
||||
}
|
||||
@@ -97,20 +94,10 @@ func (k ucanKeyshare) newToken(audienceDID string, prf []Proof, att Attenuations
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ComputeIssuerDID computes the issuer DID from a public key
|
||||
func ComputeIssuerDID(pk []byte) (string, string, error) {
|
||||
addr, err := ComputeSonrAddr(pk)
|
||||
func getIssuerDID(pk keys.PubKey) (string, string, error) {
|
||||
addr, err := bech32.ConvertAndEncode("idx", pk.Bytes())
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return fmt.Sprintf("did:sonr:%s", addr), addr, nil
|
||||
}
|
||||
|
||||
// ComputeSonrAddr computes the Sonr address from a public key
|
||||
func ComputeSonrAddr(pk []byte) (string, error) {
|
||||
sonrAddr, err := bech32.ConvertAndEncode("idx", pk)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return sonrAddr, nil
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package mpc
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/bech32"
|
||||
"github.com/onsonr/sonr/crypto/core/curves"
|
||||
"github.com/onsonr/sonr/crypto/core/protocol"
|
||||
"github.com/onsonr/sonr/crypto/tecdsa/dklsv1"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
func checkIteratedErrors(aErr, bErr error) error {
|
||||
if aErr == protocol.ErrProtocolFinished && bErr == protocol.ErrProtocolFinished {
|
||||
return nil
|
||||
}
|
||||
if aErr != protocol.ErrProtocolFinished {
|
||||
return aErr
|
||||
}
|
||||
if bErr != protocol.ErrProtocolFinished {
|
||||
return bErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func computeSonrAddr(pp Point) (string, error) {
|
||||
pk := pp.ToAffineCompressed()
|
||||
sonrAddr, err := bech32.ConvertAndEncode("idx", pk)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return sonrAddr, nil
|
||||
}
|
||||
|
||||
func hashKey(key []byte) []byte {
|
||||
hash := sha3.New256()
|
||||
hash.Write(key)
|
||||
return hash.Sum(nil)[:32] // Use first 32 bytes of hash
|
||||
}
|
||||
|
||||
func decryptKeyshare(msg []byte, key []byte, nonce []byte) ([]byte, error) {
|
||||
hashedKey := hashKey(key)
|
||||
block, err := aes.NewCipher(hashedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aesgcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plaintext, err := aesgcm.Open(nil, nonce, msg, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
func encryptKeyshare(msg Message, key []byte, nonce []byte) ([]byte, error) {
|
||||
hashedKey := hashKey(key)
|
||||
msgBytes, err := protocol.EncodeMessage(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
block, err := aes.NewCipher(hashedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aesgcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ciphertext := aesgcm.Seal(nil, nonce, []byte(msgBytes), nil)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func getAliceOut(msg *protocol.Message) (AliceOut, error) {
|
||||
return dklsv1.DecodeAliceDkgResult(msg)
|
||||
}
|
||||
|
||||
func getAlicePubPoint(msg *protocol.Message) (Point, error) {
|
||||
out, err := dklsv1.DecodeAliceDkgResult(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.PublicKey, nil
|
||||
}
|
||||
|
||||
func getBobOut(msg *protocol.Message) (BobOut, error) {
|
||||
return dklsv1.DecodeBobDkgResult(msg)
|
||||
}
|
||||
|
||||
func getBobPubPoint(msg *protocol.Message) (Point, error) {
|
||||
out, err := dklsv1.DecodeBobDkgResult(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.PublicKey, nil
|
||||
}
|
||||
|
||||
// getEcdsaPoint builds an elliptic curve point from a compressed byte slice
|
||||
func getEcdsaPoint(pubKey []byte) (*curves.EcPoint, error) {
|
||||
crv := curves.K256()
|
||||
x := new(big.Int).SetBytes(pubKey[1:33])
|
||||
y := new(big.Int).SetBytes(pubKey[33:])
|
||||
ecCurve, err := crv.ToEllipticCurve()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting curve: %v", err)
|
||||
}
|
||||
return &curves.EcPoint{X: x, Y: y, Curve: ecCurve}, nil
|
||||
}
|
||||
|
||||
func serializeSignature(sig *curves.EcdsaSignature) ([]byte, error) {
|
||||
if sig == nil {
|
||||
return nil, errors.New("nil signature")
|
||||
}
|
||||
|
||||
rBytes := sig.R.Bytes()
|
||||
sBytes := sig.S.Bytes()
|
||||
|
||||
// Ensure both components are 32 bytes
|
||||
rPadded := make([]byte, 32)
|
||||
sPadded := make([]byte, 32)
|
||||
copy(rPadded[32-len(rBytes):], rBytes)
|
||||
copy(sPadded[32-len(sBytes):], sBytes)
|
||||
|
||||
// Concatenate R and S
|
||||
result := make([]byte, 64)
|
||||
copy(result[0:32], rPadded)
|
||||
copy(result[32:64], sPadded)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func deserializeSignature(sigBytes []byte) (*curves.EcdsaSignature, error) {
|
||||
if len(sigBytes) != 64 {
|
||||
return nil, fmt.Errorf("invalid signature length: expected 64 bytes, got %d", len(sigBytes))
|
||||
}
|
||||
|
||||
r := new(big.Int).SetBytes(sigBytes[:32])
|
||||
s := new(big.Int).SetBytes(sigBytes[32:])
|
||||
|
||||
return &curves.EcdsaSignature{
|
||||
R: r,
|
||||
S: s,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func userSignFunc(k *keyEnclave, bz []byte) (SignFunc, error) {
|
||||
curve := curves.K256()
|
||||
return dklsv1.NewBobSign(curve, sha3.New256(), bz, k.UserShare, protocol.Version1)
|
||||
}
|
||||
|
||||
func userRefreshFunc(k *keyEnclave) (RefreshFunc, error) {
|
||||
curve := curves.K256()
|
||||
return dklsv1.NewBobRefresh(curve, k.UserShare, protocol.Version1)
|
||||
}
|
||||
|
||||
func valSignFunc(k *keyEnclave, bz []byte) (SignFunc, error) {
|
||||
curve := curves.K256()
|
||||
return dklsv1.NewAliceSign(curve, sha3.New256(), bz, k.ValShare, protocol.Version1)
|
||||
}
|
||||
|
||||
func valRefreshFunc(k *keyEnclave) (RefreshFunc, error) {
|
||||
curve := curves.K256()
|
||||
return dklsv1.NewAliceRefresh(curve, k.ValShare, protocol.Version1)
|
||||
}
|
||||
@@ -73,32 +73,6 @@ type Resource interface {
|
||||
Contains(b Resource) bool
|
||||
}
|
||||
|
||||
type stringLengthRsc struct {
|
||||
t string
|
||||
v string
|
||||
}
|
||||
|
||||
// NewStringLengthResource is a silly implementation of resource to use while
|
||||
// I figure out what an OR filter on strings is. Don't use this.
|
||||
func NewStringLengthResource(typ, val string) Resource {
|
||||
return stringLengthRsc{
|
||||
t: typ,
|
||||
v: val,
|
||||
}
|
||||
}
|
||||
|
||||
func (r stringLengthRsc) Type() string {
|
||||
return r.t
|
||||
}
|
||||
|
||||
func (r stringLengthRsc) Value() string {
|
||||
return r.v
|
||||
}
|
||||
|
||||
func (r stringLengthRsc) Contains(b Resource) bool {
|
||||
return r.Type() == b.Type() && len(r.Value()) <= len(b.Value())
|
||||
}
|
||||
|
||||
// Capability is an action users can perform
|
||||
type Capability interface {
|
||||
// A Capability must be expressable as a string
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
package ucan
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAttenuationsContains(t *testing.T) {
|
||||
aContains := [][2]string{
|
||||
{
|
||||
`[
|
||||
{ "cap": "SUPER_USER", "dataset": "b5/world_bank_population"},
|
||||
{ "cap": "OVERWRITE", "api": "https://api.qri.cloud" }
|
||||
]`,
|
||||
`[
|
||||
{"cap": "SOFT_DELETE", "dataset": "b5/world_bank_population" }
|
||||
]`,
|
||||
},
|
||||
{
|
||||
`[
|
||||
{ "cap": "SUPER_USER", "dataset": "b5/world_bank_population"},
|
||||
{ "cap": "OVERWRITE", "api": "https://api.qri.cloud" }
|
||||
]`,
|
||||
`[
|
||||
{"cap": "SUPER_USER", "dataset": "b5/world_bank_population" }
|
||||
]`,
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range aContains {
|
||||
t.Run(fmt.Sprintf("contains_%d", i), func(t *testing.T) {
|
||||
a := testAttenuations(c[0])
|
||||
b := testAttenuations(c[1])
|
||||
if !a.Contains(b) {
|
||||
t.Errorf("expected a attenuations to contain b attenuations")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
aNotContains := [][2]string{
|
||||
{
|
||||
`[
|
||||
{ "cap": "SUPER_USER", "dataset": "b5/world_bank_population"},
|
||||
{ "cap": "OVERWRITE", "api": "https://api.qri.cloud" }
|
||||
]`,
|
||||
`[
|
||||
{ "cap": "CREATE", "dataset": "b5" }
|
||||
]`,
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range aNotContains {
|
||||
t.Run(fmt.Sprintf("not_contains_%d", i), func(t *testing.T) {
|
||||
a := testAttenuations(c[0])
|
||||
b := testAttenuations(c[1])
|
||||
if a.Contains(b) {
|
||||
t.Errorf("expected a attenuations to NOT contain b attenuations")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func mustJSON(data string, v interface{}) {
|
||||
if err := json.Unmarshal([]byte(data), v); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testAttenuations(data string) Attenuations {
|
||||
caps := NewNestedCapabilities("SUPER_USER", "OVERWRITE", "SOFT_DELETE", "REVISE", "CREATE")
|
||||
|
||||
v := []map[string]string{}
|
||||
mustJSON(data, &v)
|
||||
|
||||
var att Attenuations
|
||||
for _, x := range v {
|
||||
var cap Capability
|
||||
var rsc Resource
|
||||
for key, val := range x {
|
||||
switch key {
|
||||
case CapKey:
|
||||
cap = caps.Cap(val)
|
||||
default:
|
||||
rsc = NewStringLengthResource(key, val)
|
||||
}
|
||||
}
|
||||
att = append(att, Attenuation{cap, rsc})
|
||||
}
|
||||
|
||||
return att
|
||||
}
|
||||
|
||||
func TestNestedCapabilities(t *testing.T) {
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.orm.UCAN`. DO NOT EDIT.
|
||||
package attns
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/apple/pkl-go/pkl"
|
||||
)
|
||||
|
||||
type UCAN struct {
|
||||
}
|
||||
|
||||
// LoadFromPath loads the pkl module at the given path and evaluates it into a UCAN
|
||||
func LoadFromPath(ctx context.Context, path string) (ret *UCAN, err error) {
|
||||
evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := evaluator.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
ret, err = Load(ctx, evaluator, pkl.FileSource(path))
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Load loads the pkl module at the given source and evaluates it with the given evaluator into a UCAN
|
||||
func Load(ctx context.Context, evaluator pkl.Evaluator, source *pkl.ModuleSource) (*UCAN, error) {
|
||||
var ret UCAN
|
||||
if err := evaluator.EvaluateModule(ctx, source, &ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.orm.UCAN`. DO NOT EDIT.
|
||||
package capability
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Capability string
|
||||
|
||||
const (
|
||||
CAPOWNER Capability = "CAP_OWNER"
|
||||
CAPOPERATOR Capability = "CAP_OPERATOR"
|
||||
CAPOBSERVER Capability = "CAP_OBSERVER"
|
||||
CAPAUTHENTICATE Capability = "CAP_AUTHENTICATE"
|
||||
CAPAUTHORIZE Capability = "CAP_AUTHORIZE"
|
||||
CAPDELEGATE Capability = "CAP_DELEGATE"
|
||||
CAPINVOKE Capability = "CAP_INVOKE"
|
||||
CAPEXECUTE Capability = "CAP_EXECUTE"
|
||||
CAPPROPOSE Capability = "CAP_PROPOSE"
|
||||
CAPSIGN Capability = "CAP_SIGN"
|
||||
CAPSETPOLICY Capability = "CAP_SET_POLICY"
|
||||
CAPSETTHRESHOLD Capability = "CAP_SET_THRESHOLD"
|
||||
CAPRECOVER Capability = "CAP_RECOVER"
|
||||
CAPSOCIAL Capability = "CAP_SOCIAL"
|
||||
CAPVOTE Capability = "CAP_VOTE"
|
||||
CAPRESOLVER Capability = "CAP_RESOLVER"
|
||||
CAPPRODUCER Capability = "CAP_PRODUCER"
|
||||
)
|
||||
|
||||
// String returns the string representation of Capability
|
||||
func (rcv Capability) String() string {
|
||||
return string(rcv)
|
||||
}
|
||||
|
||||
var _ encoding.BinaryUnmarshaler = new(Capability)
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler for Capability.
|
||||
func (rcv *Capability) UnmarshalBinary(data []byte) error {
|
||||
switch str := string(data); str {
|
||||
case "CAP_OWNER":
|
||||
*rcv = CAPOWNER
|
||||
case "CAP_OPERATOR":
|
||||
*rcv = CAPOPERATOR
|
||||
case "CAP_OBSERVER":
|
||||
*rcv = CAPOBSERVER
|
||||
case "CAP_AUTHENTICATE":
|
||||
*rcv = CAPAUTHENTICATE
|
||||
case "CAP_AUTHORIZE":
|
||||
*rcv = CAPAUTHORIZE
|
||||
case "CAP_DELEGATE":
|
||||
*rcv = CAPDELEGATE
|
||||
case "CAP_INVOKE":
|
||||
*rcv = CAPINVOKE
|
||||
case "CAP_EXECUTE":
|
||||
*rcv = CAPEXECUTE
|
||||
case "CAP_PROPOSE":
|
||||
*rcv = CAPPROPOSE
|
||||
case "CAP_SIGN":
|
||||
*rcv = CAPSIGN
|
||||
case "CAP_SET_POLICY":
|
||||
*rcv = CAPSETPOLICY
|
||||
case "CAP_SET_THRESHOLD":
|
||||
*rcv = CAPSETTHRESHOLD
|
||||
case "CAP_RECOVER":
|
||||
*rcv = CAPRECOVER
|
||||
case "CAP_SOCIAL":
|
||||
*rcv = CAPSOCIAL
|
||||
case "CAP_VOTE":
|
||||
*rcv = CAPVOTE
|
||||
case "CAP_RESOLVER":
|
||||
*rcv = CAPRESOLVER
|
||||
case "CAP_PRODUCER":
|
||||
*rcv = CAPPRODUCER
|
||||
default:
|
||||
return fmt.Errorf(`illegal: "%s" is not a valid Capability`, str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package capability
|
||||
@@ -1,8 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.orm.UCAN`. DO NOT EDIT.
|
||||
package attns
|
||||
|
||||
import "github.com/apple/pkl-go/pkl"
|
||||
|
||||
func init() {
|
||||
pkl.RegisterMapping("sonr.orm.UCAN", UCAN{})
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.orm.UCAN`. DO NOT EDIT.
|
||||
package policytype
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type PolicyType string
|
||||
|
||||
const (
|
||||
POLICYTHRESHOLD PolicyType = "POLICY_THRESHOLD"
|
||||
POLICYTIMELOCK PolicyType = "POLICY_TIMELOCK"
|
||||
POLICYWHITELIST PolicyType = "POLICY_WHITELIST"
|
||||
POLICYKEYGEN PolicyType = "POLICY_KEYGEN"
|
||||
)
|
||||
|
||||
// String returns the string representation of PolicyType
|
||||
func (rcv PolicyType) String() string {
|
||||
return string(rcv)
|
||||
}
|
||||
|
||||
var _ encoding.BinaryUnmarshaler = new(PolicyType)
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler for PolicyType.
|
||||
func (rcv *PolicyType) UnmarshalBinary(data []byte) error {
|
||||
switch str := string(data); str {
|
||||
case "POLICY_THRESHOLD":
|
||||
*rcv = POLICYTHRESHOLD
|
||||
case "POLICY_TIMELOCK":
|
||||
*rcv = POLICYTIMELOCK
|
||||
case "POLICY_WHITELIST":
|
||||
*rcv = POLICYWHITELIST
|
||||
case "POLICY_KEYGEN":
|
||||
*rcv = POLICYKEYGEN
|
||||
default:
|
||||
return fmt.Errorf(`illegal: "%s" is not a valid PolicyType`, str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// Code generated from Pkl module `sonr.orm.UCAN`. DO NOT EDIT.
|
||||
package resourcetype
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ResourceType string
|
||||
|
||||
const (
|
||||
RESACCOUNT ResourceType = "RES_ACCOUNT"
|
||||
RESTRANSACTION ResourceType = "RES_TRANSACTION"
|
||||
RESPOLICY ResourceType = "RES_POLICY"
|
||||
RESRECOVERY ResourceType = "RES_RECOVERY"
|
||||
RESVAULT ResourceType = "RES_VAULT"
|
||||
RESIPFS ResourceType = "RES_IPFS"
|
||||
RESIPNS ResourceType = "RES_IPNS"
|
||||
RESKEYSHARE ResourceType = "RES_KEYSHARE"
|
||||
)
|
||||
|
||||
// String returns the string representation of ResourceType
|
||||
func (rcv ResourceType) String() string {
|
||||
return string(rcv)
|
||||
}
|
||||
|
||||
var _ encoding.BinaryUnmarshaler = new(ResourceType)
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler for ResourceType.
|
||||
func (rcv *ResourceType) UnmarshalBinary(data []byte) error {
|
||||
switch str := string(data); str {
|
||||
case "RES_ACCOUNT":
|
||||
*rcv = RESACCOUNT
|
||||
case "RES_TRANSACTION":
|
||||
*rcv = RESTRANSACTION
|
||||
case "RES_POLICY":
|
||||
*rcv = RESPOLICY
|
||||
case "RES_RECOVERY":
|
||||
*rcv = RESRECOVERY
|
||||
case "RES_VAULT":
|
||||
*rcv = RESVAULT
|
||||
case "RES_IPFS":
|
||||
*rcv = RESIPFS
|
||||
case "RES_IPNS":
|
||||
*rcv = RESIPNS
|
||||
case "RES_KEYSHARE":
|
||||
*rcv = RESKEYSHARE
|
||||
default:
|
||||
return fmt.Errorf(`illegal: "%s" is not a valid ResourceType`, str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package resourcetype
|
||||
|
||||
// Resource is a unique identifier for a thing, usually stored state. Resources
|
||||
// are organized by string types
|
||||
type Resource interface {
|
||||
Type() ResourceType
|
||||
Value() string
|
||||
Contains(b Resource) bool
|
||||
}
|
||||
|
||||
type stringResource struct {
|
||||
t ResourceType
|
||||
v string
|
||||
}
|
||||
|
||||
func (r stringResource) Type() ResourceType {
|
||||
return r.t
|
||||
}
|
||||
|
||||
func (r stringResource) Value() string {
|
||||
return r.v
|
||||
}
|
||||
|
||||
func (r stringResource) Contains(b Resource) bool {
|
||||
return r.Type() == b.Type() && len(r.Value()) <= len(b.Value())
|
||||
}
|
||||
|
||||
func NewResource(typ ResourceType, val string) Resource {
|
||||
return stringResource{
|
||||
t: typ,
|
||||
v: val,
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
package ucan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
"github.com/onsonr/sonr/crypto/ucan/attns/capability"
|
||||
"github.com/onsonr/sonr/crypto/ucan/attns/policytype"
|
||||
"github.com/onsonr/sonr/crypto/ucan/attns/resourcetype"
|
||||
)
|
||||
|
||||
// NewSmartAccount creates default attenuations for a smart account
|
||||
func NewSmartAccount(
|
||||
accountAddr string,
|
||||
) Attenuations {
|
||||
caps := AccountPermissions.GetCapabilities()
|
||||
return Attenuations{
|
||||
// Owner capabilities
|
||||
{Cap: caps.Cap(CapOwner.String()), Rsc: NewResource(ResAccount, accountAddr)},
|
||||
|
||||
// Operation capabilities
|
||||
{Cap: caps.Cap(capability.CAPEXECUTE.String()), Rsc: NewResource(ResTransaction, fmt.Sprintf("%s:*", accountAddr))},
|
||||
{Cap: caps.Cap(capability.CAPPROPOSE.String()), Rsc: NewResource(ResTransaction, fmt.Sprintf("%s:*", accountAddr))},
|
||||
{Cap: caps.Cap(capability.CAPSIGN.String()), Rsc: NewResource(ResTransaction, fmt.Sprintf("%s:*", accountAddr))},
|
||||
|
||||
// Policy capabilities
|
||||
{Cap: caps.Cap(capability.CAPSETPOLICY.String()), Rsc: NewResource(ResPolicy, fmt.Sprintf("%s:*", accountAddr))},
|
||||
{Cap: caps.Cap(capability.CAPSETTHRESHOLD.String()), Rsc: NewResource(ResPolicy, fmt.Sprintf("%s:threshold", accountAddr))},
|
||||
}
|
||||
}
|
||||
|
||||
// NewSmartAccountPolicy creates attenuations for policy management
|
||||
func NewSmartAccountPolicy(
|
||||
accountAddr string,
|
||||
policyType policytype.PolicyType,
|
||||
) Attenuations {
|
||||
caps := AccountPermissions.GetCapabilities()
|
||||
return Attenuations{
|
||||
{
|
||||
Cap: caps.Cap(capability.CAPSETPOLICY.String()),
|
||||
Rsc: NewResource(
|
||||
ResPolicy,
|
||||
fmt.Sprintf("%s:%s", accountAddr, policyType),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SmartAccountCapabilities defines the capability hierarchy
|
||||
func SmartAccountCapabilities() []string {
|
||||
return []string{
|
||||
CapOwner.String(),
|
||||
CapOperator.String(),
|
||||
CapObserver.String(),
|
||||
CapExecute.String(),
|
||||
CapPropose.String(),
|
||||
CapSign.String(),
|
||||
CapSetPolicy.String(),
|
||||
CapSetThreshold.String(),
|
||||
CapRecover.String(),
|
||||
CapSocial.String(),
|
||||
}
|
||||
}
|
||||
|
||||
// CreateVaultAttenuations creates default attenuations for a smart account
|
||||
func NewService(
|
||||
origin string,
|
||||
) Attenuations {
|
||||
caps := ServicePermissions.GetCapabilities()
|
||||
return Attenuations{
|
||||
// Owner capabilities
|
||||
{Cap: caps.Cap(capability.CAPOWNER.String()), Rsc: NewResource(resourcetype.RESACCOUNT, origin)},
|
||||
|
||||
// Operation capabilities
|
||||
{Cap: caps.Cap(capability.CAPEXECUTE.String()), Rsc: NewResource(resourcetype.RESTRANSACTION, fmt.Sprintf("%s:*", origin))},
|
||||
{Cap: caps.Cap(capability.CAPPROPOSE.String()), Rsc: NewResource(resourcetype.RESTRANSACTION, fmt.Sprintf("%s:*", origin))},
|
||||
{Cap: caps.Cap(capability.CAPSIGN.String()), Rsc: NewResource(resourcetype.RESTRANSACTION, fmt.Sprintf("%s:*", origin))},
|
||||
|
||||
// Policy capabilities
|
||||
{Cap: caps.Cap(capability.CAPSETPOLICY.String()), Rsc: NewResource(resourcetype.RESPOLICY, fmt.Sprintf("%s:*", origin))},
|
||||
{Cap: caps.Cap(capability.CAPSETTHRESHOLD.String()), Rsc: NewResource(resourcetype.RESPOLICY, fmt.Sprintf("%s:threshold", origin))},
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceCapabilities defines the capability hierarchy
|
||||
func ServiceCapabilities() []string {
|
||||
return []string{
|
||||
CapOwner.String(),
|
||||
CapOperator.String(),
|
||||
CapObserver.String(),
|
||||
CapExecute.String(),
|
||||
CapPropose.String(),
|
||||
CapSign.String(),
|
||||
CapResolver.String(),
|
||||
CapProducer.String(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewVault creates default attenuations for a smart account
|
||||
func NewVault(
|
||||
kss mpc.Keyset,
|
||||
) Attenuations {
|
||||
accountAddr, err := mpc.ComputeSonrAddr(kss.User().GetPublicKey())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
caps := VaultPermissions.GetCapabilities()
|
||||
return Attenuations{
|
||||
// Owner capabilities
|
||||
{Cap: caps.Cap(capability.CAPOWNER.String()), Rsc: NewResource(resourcetype.RESACCOUNT, accountAddr)},
|
||||
|
||||
// Operation capabilities
|
||||
{Cap: caps.Cap(capability.CAPEXECUTE.String()), Rsc: NewResource(resourcetype.RESTRANSACTION, fmt.Sprintf("%s:*", accountAddr))},
|
||||
{Cap: caps.Cap(capability.CAPPROPOSE.String()), Rsc: NewResource(resourcetype.RESTRANSACTION, fmt.Sprintf("%s:*", accountAddr))},
|
||||
{Cap: caps.Cap(capability.CAPSIGN.String()), Rsc: NewResource(resourcetype.RESTRANSACTION, fmt.Sprintf("%s:*", accountAddr))},
|
||||
|
||||
// Policy capabilities
|
||||
{Cap: caps.Cap(capability.CAPSETPOLICY.String()), Rsc: NewResource(resourcetype.RESPOLICY, fmt.Sprintf("%s:*", accountAddr))},
|
||||
{Cap: caps.Cap(capability.CAPSETTHRESHOLD.String()), Rsc: NewResource(resourcetype.RESPOLICY, fmt.Sprintf("%s:threshold", accountAddr))},
|
||||
}
|
||||
}
|
||||
|
||||
// NewVaultPolicy creates attenuations for policy management
|
||||
func NewVaultPolicy(
|
||||
accountAddr string,
|
||||
policyType policytype.PolicyType,
|
||||
) Attenuations {
|
||||
caps := VaultPermissions.GetCapabilities()
|
||||
return Attenuations{
|
||||
{
|
||||
Cap: caps.Cap(capability.CAPSETPOLICY.String()),
|
||||
Rsc: NewResource(
|
||||
resourcetype.RESPOLICY,
|
||||
fmt.Sprintf("%s:%s", accountAddr, policyType),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// VaultCapabilities defines the capability hierarchy
|
||||
func VaultCapabilities() []string {
|
||||
return []string{
|
||||
CapOwner.String(),
|
||||
CapOperator.String(),
|
||||
CapObserver.String(),
|
||||
CapAuthenticate.String(),
|
||||
CapAuthorize.String(),
|
||||
CapDelegate.String(),
|
||||
CapInvoke.String(),
|
||||
CapExecute.String(),
|
||||
CapRecover.String(),
|
||||
}
|
||||
}
|
||||
+57
-18
@@ -1,27 +1,66 @@
|
||||
package ucan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// CtxKey defines a distinct type for context keys used by the access
|
||||
// package
|
||||
type CtxKey string
|
||||
|
||||
// TokenCtxKey is the key for adding an access UCAN to a context.Context
|
||||
const TokenCtxKey CtxKey = "UCAN"
|
||||
|
||||
// CtxWithToken adds a UCAN value to a context
|
||||
func CtxWithToken(ctx context.Context, t Token) context.Context {
|
||||
return context.WithValue(ctx, TokenCtxKey, t)
|
||||
var EmptyAttenuation = Attenuation{
|
||||
Cap: Capability(nil),
|
||||
Rsc: Resource(nil),
|
||||
}
|
||||
|
||||
// FromCtx extracts a token from a given context if one is set, returning nil
|
||||
// otherwise
|
||||
func FromCtx(ctx context.Context) *Token {
|
||||
iface := ctx.Value(TokenCtxKey)
|
||||
if ref, ok := iface.(*Token); ok {
|
||||
return ref
|
||||
// Permissions represents the type of attenuation
|
||||
type Permissions string
|
||||
|
||||
const (
|
||||
// AccountPermissions represents the smart account attenuation
|
||||
AccountPermissions = Permissions("account")
|
||||
|
||||
// ServicePermissions represents the service attenuation
|
||||
ServicePermissions = Permissions("service")
|
||||
|
||||
// VaultPermissions represents the vault attenuation
|
||||
VaultPermissions = Permissions("vault")
|
||||
)
|
||||
|
||||
// Cap returns the capability for the given AttenuationPreset
|
||||
func (a Permissions) NewCap(c string) Capability {
|
||||
return a.GetCapabilities().Cap(c)
|
||||
}
|
||||
|
||||
// NestedCapabilities returns the nested capabilities for the given AttenuationPreset
|
||||
func (a Permissions) GetCapabilities() NestedCapabilities {
|
||||
var caps []string
|
||||
switch a {
|
||||
case AccountPermissions:
|
||||
// caps = SmartAccountCapabilities()
|
||||
case VaultPermissions:
|
||||
// caps = VaultCapabilities()
|
||||
}
|
||||
return nil
|
||||
return NewNestedCapabilities(caps...)
|
||||
}
|
||||
|
||||
// Equals returns true if the given AttenuationPreset is equal to the receiver
|
||||
func (a Permissions) Equals(b Permissions) bool {
|
||||
return a == b
|
||||
}
|
||||
|
||||
// String returns the string representation of the AttenuationPreset
|
||||
func (a Permissions) String() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
// ParseAttenuationData parses raw attenuation data into a structured format
|
||||
func ParseAttenuationData(data map[string]interface{}) (Permissions, map[string]interface{}, error) {
|
||||
typeRaw, ok := data["preset"]
|
||||
if !ok {
|
||||
return "", nil, fmt.Errorf("missing preset type in attenuation data")
|
||||
}
|
||||
|
||||
presetType, ok := typeRaw.(string)
|
||||
if !ok {
|
||||
return "", nil, fmt.Errorf("invalid preset type format")
|
||||
}
|
||||
|
||||
return Permissions(presetType), data, nil
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
package didkey
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/libp2p/go-libp2p/core/crypto"
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
)
|
||||
|
||||
func TestID_Parse(t *testing.T) {
|
||||
keyStrED := "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
|
||||
id, err := Parse(keyStrED)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if id.String() != keyStrED {
|
||||
t.Errorf("string mismatch.\nwant: %q\ngot: %q", keyStrED, id.String())
|
||||
}
|
||||
|
||||
keyStrRSA := "did:key:z2MGw4gk84USotaWf4AkJ83DcnrfgGaceF86KQXRYMfQ7xqnUFp38UZ6Le8JPfkb4uCLGjHBzKpjEXb9hx9n2ftecQWCHXKtKszkke4FmENdTZ7i9sqRmL3pLnEEJ774r3HMuuC7tNRQ6pqzrxatXx2WinCibdhUmvh3FobnA9ygeqkSGtV6WLa7NVFw9cAvnv8Y6oHcaoZK7fNP4ASGs6AHmSC6ydSR676aKYMe95QmEAj4xJptDsSxG7zLAGzAdwCgm56M4fTno8GdWNmU6Pdghnuf6fWyYus9ASwdfwyaf3SDf4uo5T16PRJssHkQh6DJHfK4Rka7RNQLjzfGBPjFLHbUSvmf4EdbHasbVaveAArD68ZfazRCCvjdovQjWr6uyLCwSAQLPUFZBTT8mW"
|
||||
|
||||
id, err = Parse(keyStrRSA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if id.String() != keyStrRSA {
|
||||
t.Errorf("string mismatch.\nwant: %q\ngot: %q", keyStrRSA, id.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestID_FromMPCKey(t *testing.T) {
|
||||
// Generate new MPC keyset
|
||||
ks, err := mpc.NewKeyset()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate MPC keyset: %v", err)
|
||||
}
|
||||
|
||||
// Get public key from validator share
|
||||
pubKey := ks.Val().PublicKey()
|
||||
if len(pubKey) != 65 {
|
||||
t.Fatalf("expected 65-byte uncompressed public key, got %d bytes", len(pubKey))
|
||||
}
|
||||
|
||||
// Create crypto.PubKey from raw bytes
|
||||
cryptoPubKey, err := crypto.UnmarshalSecp256k1PublicKey(pubKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to unmarshal public key: %v", err)
|
||||
}
|
||||
|
||||
// Create DID Key ID
|
||||
id, err := NewID(cryptoPubKey)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create DID Key ID: %v", err)
|
||||
}
|
||||
log.Printf("%s\n", id.String())
|
||||
|
||||
// Verify the key can be parsed back
|
||||
parsed, err := Parse(id.String())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse DID Key string: %v", err)
|
||||
}
|
||||
|
||||
// Verify the parsed key matches original
|
||||
if parsed.String() != id.String() {
|
||||
t.Errorf("parsed key doesn't match original.\nwant: %q\ngot: %q",
|
||||
id.String(), parsed.String())
|
||||
}
|
||||
|
||||
// Verify we can get back a valid verify key
|
||||
verifyKey, err := id.VerifyKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get verify key: %v", err)
|
||||
}
|
||||
|
||||
// Verify the key is the right type and length
|
||||
rawKey, ok := verifyKey.([]byte)
|
||||
if !ok {
|
||||
t.Fatalf("expected []byte verify key, got %T", verifyKey)
|
||||
}
|
||||
if len(rawKey) != 65 && len(rawKey) != 33 {
|
||||
t.Errorf("invalid key length %d, expected 65 or 33 bytes", len(rawKey))
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
package ucan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsonr/sonr/crypto/ucan/attns/capability"
|
||||
"github.com/onsonr/sonr/crypto/ucan/attns/policytype"
|
||||
"github.com/onsonr/sonr/crypto/ucan/attns/resourcetype"
|
||||
)
|
||||
|
||||
var EmptyAttenuation = Attenuation{
|
||||
Cap: Capability(nil),
|
||||
Rsc: Resource(nil),
|
||||
}
|
||||
|
||||
const (
|
||||
// Owner
|
||||
CapOwner = capability.CAPOWNER
|
||||
CapOperator = capability.CAPOPERATOR
|
||||
CapObserver = capability.CAPOBSERVER
|
||||
|
||||
// Auth
|
||||
CapAuthenticate = capability.CAPAUTHENTICATE
|
||||
CapAuthorize = capability.CAPAUTHORIZE
|
||||
CapDelegate = capability.CAPDELEGATE
|
||||
CapInvoke = capability.CAPINVOKE
|
||||
CapExecute = capability.CAPEXECUTE
|
||||
CapPropose = capability.CAPPROPOSE
|
||||
CapSign = capability.CAPSIGN
|
||||
CapSetPolicy = capability.CAPSETPOLICY
|
||||
CapSetThreshold = capability.CAPSETTHRESHOLD
|
||||
CapRecover = capability.CAPRECOVER
|
||||
CapSocial = capability.CAPSOCIAL
|
||||
CapResolver = capability.CAPRESOLVER
|
||||
CapProducer = capability.CAPPRODUCER
|
||||
|
||||
// Resources
|
||||
ResAccount = resourcetype.RESACCOUNT
|
||||
ResTransaction = resourcetype.RESTRANSACTION
|
||||
ResPolicy = resourcetype.RESPOLICY
|
||||
ResRecovery = resourcetype.RESRECOVERY
|
||||
ResVault = resourcetype.RESVAULT
|
||||
ResIPFS = resourcetype.RESIPFS
|
||||
ResIPNS = resourcetype.RESIPNS
|
||||
ResKeyShare = resourcetype.RESKEYSHARE
|
||||
|
||||
// PolicyTypes
|
||||
PolicyThreshold = policytype.POLICYTHRESHOLD
|
||||
PolicyTimelock = policytype.POLICYTIMELOCK
|
||||
PolicyWhitelist = policytype.POLICYWHITELIST
|
||||
PolicyKeyShare = policytype.POLICYKEYGEN
|
||||
)
|
||||
|
||||
// NewVaultResource creates a new resource identifier
|
||||
func NewResource(resType resourcetype.ResourceType, path string) Resource {
|
||||
return NewStringLengthResource(string(resType), path)
|
||||
}
|
||||
|
||||
// Permissions represents the type of attenuation
|
||||
type Permissions string
|
||||
|
||||
const (
|
||||
// AccountPermissions represents the smart account attenuation
|
||||
AccountPermissions = Permissions("account")
|
||||
|
||||
// ServicePermissions represents the service attenuation
|
||||
ServicePermissions = Permissions("service")
|
||||
|
||||
// VaultPermissions represents the vault attenuation
|
||||
VaultPermissions = Permissions("vault")
|
||||
)
|
||||
|
||||
// Cap returns the capability for the given AttenuationPreset
|
||||
func (a Permissions) NewCap(c capability.Capability) Capability {
|
||||
return a.GetCapabilities().Cap(c.String())
|
||||
}
|
||||
|
||||
// NestedCapabilities returns the nested capabilities for the given AttenuationPreset
|
||||
func (a Permissions) GetCapabilities() NestedCapabilities {
|
||||
var caps []string
|
||||
switch a {
|
||||
case AccountPermissions:
|
||||
caps = SmartAccountCapabilities()
|
||||
case VaultPermissions:
|
||||
caps = VaultCapabilities()
|
||||
}
|
||||
return NewNestedCapabilities(caps...)
|
||||
}
|
||||
|
||||
// Equals returns true if the given AttenuationPreset is equal to the receiver
|
||||
func (a Permissions) Equals(b Permissions) bool {
|
||||
return a == b
|
||||
}
|
||||
|
||||
// String returns the string representation of the AttenuationPreset
|
||||
func (a Permissions) String() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
// GetConstructor returns the AttenuationConstructorFunc for a Permission
|
||||
func (a Permissions) GetConstructor() AttenuationConstructorFunc {
|
||||
return NewAttenuationFromPreset(a)
|
||||
}
|
||||
|
||||
// NewAttenuationFromPreset creates an AttenuationConstructorFunc for the given preset
|
||||
func NewAttenuationFromPreset(preset Permissions) AttenuationConstructorFunc {
|
||||
return func(v map[string]interface{}) (Attenuation, error) {
|
||||
// Extract capability and resource from map
|
||||
capStr, ok := v["cap"].(string)
|
||||
if !ok {
|
||||
return EmptyAttenuation, fmt.Errorf("missing or invalid capability in attenuation data")
|
||||
}
|
||||
|
||||
resType, ok := v["type"].(string)
|
||||
if !ok {
|
||||
return EmptyAttenuation, fmt.Errorf("missing or invalid resource type in attenuation data")
|
||||
}
|
||||
|
||||
path, ok := v["path"].(string)
|
||||
if !ok {
|
||||
path = "/" // Default path if not specified
|
||||
}
|
||||
|
||||
// Create capability from preset
|
||||
cap := preset.NewCap(capability.Capability(capStr))
|
||||
if cap == nil {
|
||||
return EmptyAttenuation, fmt.Errorf("invalid capability %s for preset %s", capStr, preset)
|
||||
}
|
||||
|
||||
// Create resource
|
||||
resource := NewResource(resourcetype.ResourceType(resType), path)
|
||||
|
||||
return Attenuation{
|
||||
Cap: cap,
|
||||
Rsc: resource,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetPresetConstructor returns the appropriate AttenuationConstructorFunc for a given type
|
||||
func GetPresetConstructor(attType string) (AttenuationConstructorFunc, error) {
|
||||
preset := Permissions(attType)
|
||||
switch preset {
|
||||
case AccountPermissions, ServicePermissions, VaultPermissions:
|
||||
return NewAttenuationFromPreset(preset), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown attenuation preset: %s", attType)
|
||||
}
|
||||
}
|
||||
|
||||
// ParseAttenuationData parses raw attenuation data into a structured format
|
||||
func ParseAttenuationData(data map[string]interface{}) (Permissions, map[string]interface{}, error) {
|
||||
typeRaw, ok := data["preset"]
|
||||
if !ok {
|
||||
return "", nil, fmt.Errorf("missing preset type in attenuation data")
|
||||
}
|
||||
|
||||
presetType, ok := typeRaw.(string)
|
||||
if !ok {
|
||||
return "", nil, fmt.Errorf("invalid preset type format")
|
||||
}
|
||||
|
||||
return Permissions(presetType), data, nil
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package ucan
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAttenuationPresetConstructor(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
data map[string]interface{}
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid smart account attenuation",
|
||||
data: map[string]interface{}{
|
||||
"preset": "account",
|
||||
"cap": string(CapOwner),
|
||||
"type": string(ResAccount),
|
||||
"path": "/accounts/123",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid vault attenuation",
|
||||
data: map[string]interface{}{
|
||||
"preset": "vault",
|
||||
"cap": string(CapOperator),
|
||||
"type": string(ResVault),
|
||||
"path": "/vaults/456",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
preset, data, err := ParseAttenuationData(tt.data)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
constructor, err := GetPresetConstructor(preset.String())
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
attenuation, err := constructor(data)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, attenuation)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package spec
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/onsonr/sonr/crypto/mpc"
|
||||
)
|
||||
|
||||
// MPCSigningMethod implements the SigningMethod interface for MPC-based signing
|
||||
type MPCSigningMethod struct {
|
||||
Name string
|
||||
ks ucanKeyshare
|
||||
}
|
||||
|
||||
// NewJWTSigningMethod creates a new MPC signing method with the given keyshare source
|
||||
func NewJWTSigningMethod(name string, ks ucanKeyshare) *MPCSigningMethod {
|
||||
return &MPCSigningMethod{
|
||||
Name: name,
|
||||
ks: ks,
|
||||
}
|
||||
}
|
||||
|
||||
// Alg returns the signing method's name
|
||||
func (m *MPCSigningMethod) Alg() string {
|
||||
return m.Name
|
||||
}
|
||||
|
||||
// Verify verifies the signature using the MPC public key
|
||||
func (m *MPCSigningMethod) Verify(signingString, signature string, key interface{}) error {
|
||||
// Decode the signature
|
||||
sig, err := base64.RawURLEncoding.DecodeString(signature)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Hash the signing string
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
digest := hasher.Sum(nil)
|
||||
|
||||
// Verify using the keyshare's public key
|
||||
valid, err := mpc.VerifySignature(m.ks.valShare.PublicKey(), digest, sig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to verify signature: %w", err)
|
||||
}
|
||||
if !valid {
|
||||
return fmt.Errorf("invalid signature")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sign signs the data using MPC
|
||||
func (m *MPCSigningMethod) Sign(signingString string, key interface{}) (string, error) {
|
||||
// Hash the signing string
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
digest := hasher.Sum(nil)
|
||||
|
||||
// Create signing functions
|
||||
signFunc, err := m.ks.userShare.SignFunc(digest)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create sign function: %w", err)
|
||||
}
|
||||
|
||||
valSignFunc, err := m.ks.valShare.SignFunc(digest)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create validator sign function: %w", err)
|
||||
}
|
||||
|
||||
// Run the signing protocol
|
||||
sig, err := mpc.ExecuteSigning(valSignFunc, signFunc)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to run sign protocol: %w", err)
|
||||
}
|
||||
|
||||
// Serialize the signature
|
||||
sigBytes, err := mpc.SerializeSignature(sig)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to serialize signature: %w", err)
|
||||
}
|
||||
|
||||
// Encode the signature
|
||||
encoded := base64.RawURLEncoding.EncodeToString(sigBytes)
|
||||
return encoded, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Register the MPC signing method
|
||||
jwt.RegisterSigningMethod("MPC256", func() jwt.SigningMethod {
|
||||
return &MPCSigningMethod{
|
||||
Name: "MPC256",
|
||||
}
|
||||
})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user