Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
90d7526
add: inital db models
Aman035 Nov 6, 2025
8a66f9f
add: sudo network logic
Aman035 Nov 6, 2025
9a8abac
add: keyshare management
Aman035 Nov 6, 2025
bd9c0ee
initial code
Aman035 Nov 6, 2025
cf426d0
add: keyShare Manager ut
Aman035 Nov 10, 2025
d78b8c8
rm: list
Aman035 Nov 10, 2025
96bf365
minor uv package changes
Aman035 Nov 10, 2025
dfe9f59
add: transport
Aman035 Nov 11, 2025
fdf7537
initial demo
Aman035 Nov 11, 2025
2616b2e
minor changes
Aman035 Nov 12, 2025
e738fd9
fix: replace participant with UV struct
Aman035 Nov 17, 2025
2dc54d0
fix: demo
Aman035 Nov 17, 2025
d723f98
remove: hardcoded config
Aman035 Nov 17, 2025
0ad380a
fix: minor bugs
Aman035 Nov 18, 2025
b5ce83b
add: node service
Aman035 Nov 18, 2025
cbb1270
add: print log
Aman035 Nov 18, 2025
894fd4d
removed unnecessary fns
Aman035 Nov 20, 2025
7166b64
remove: unnecessary logging
Aman035 Nov 20, 2025
3ef5f56
add: eventStore
Aman035 Nov 20, 2025
7a9c013
change: package structure
Aman035 Nov 20, 2025
5febac5
add: dkls package
Aman035 Nov 20, 2025
fc1f1ed
remove transport
Aman035 Nov 20, 2025
d4c7136
add: networking layer
Aman035 Nov 20, 2025
ef0aab1
change node logic
Aman035 Nov 20, 2025
486657e
store changes
Aman035 Nov 22, 2025
cdd4203
update dkls: must require setup
Aman035 Nov 22, 2025
0382b58
remove: core
Aman035 Nov 22, 2025
68e709f
remove: node package
Aman035 Nov 22, 2025
3394e23
add: coordinator, tss and inital sessionManager
Aman035 Nov 22, 2025
21aa17f
add: coordinator package
Aman035 Nov 24, 2025
bbe2648
change: message structure
Aman035 Nov 24, 2025
979af2f
add: GetParticipants fn in dkls
Aman035 Nov 24, 2025
5c9f113
add: get SessionType in dkls
Aman035 Nov 24, 2025
7dfcdce
add: fns to get Pary and PeerIds
Aman035 Nov 24, 2025
74304e8
add: dkls changes
Aman035 Nov 24, 2025
f3adf12
add: tc and sessionManager
Aman035 Nov 24, 2025
52d1a60
add: peer reg changes, temp demo changes
Aman035 Nov 24, 2025
19ef2e3
add: session expiry
Aman035 Nov 24, 2025
620c153
remove: unnecessary fns from dkls, add new msg types
Aman035 Nov 24, 2025
1f9eaf6
remove: unnecessary types from dkls
Aman035 Nov 24, 2025
d4f6394
add: approach for ack and begin messages
Aman035 Nov 25, 2025
8eb65d5
fix: logs
Aman035 Nov 25, 2025
f239e68
fix: signature verification
Aman035 Nov 25, 2025
32419a9
Merge pull request #95 from pushchain/feat/tss-v2
Aman035 Nov 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions cmd/tss/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# TSS Demo

## Quick Start

Start 3 nodes in separate terminals using the test script:

```bash
# Terminal 1
./scripts/test_tss.sh pushvaloper1fv2fm76q7cjnr58wdwyntzrjgtc7qya6n7dmlu 39001 30B0D912700C3DF94F4743F440D1613F7EA67E1CEF32C73B925DB6CD7F1A1544

# Terminal 2
./scripts/test_tss.sh pushvaloper12jzrpp4pkucxxvj6hw4dfxsnhcpy6ddty2fl75 39002 59BA39BF8BCFE835B6ABD7FE5208D8B8AEFF7B467F9FE76F1F43ED392E5B9432

# Terminal 3
./scripts/test_tss.sh pushvaloper1vzuw2x3k2ccme70zcgswv8d88kyc07grdpvw3e 39003 957590C7179F8645368162418A3DF817E5663BBC7C24D0EFE1D64EFFB11DC595
```

The script automatically:

- Builds the binary
- Cleans up previous runs (database and home directory)
- Starts the node with proper configuration
- Logs to `/tmp/tss-<validator>.log`

Wait a few seconds for nodes to register, then trigger operations:

```bash
# Generate a new keyshare (keyID is auto-generated by DKLS)
./build/tss keygen

# Refresh the current keyshare
./build/tss keyrefresh

# Sign a message
./build/tss sign -message="Hello, World!"
```

## Commands

- `node` - Run a TSS node (requires `-validator-address` and `-private-key`)
- `keygen` - Generate a new keyshare (keyID is auto-generated by DKLS, no parameters needed)
- `keyrefresh` - Refresh the current keyshare (uses latest keyshare automatically)
- `sign` - Sign a message (requires `-message` flag)

## Flags

### node command:

- `-validator-address` (required): Validator address (unique per node)
- `-private-key` (required): Ed25519 private key in hex format
- `-p2p-listen`: libp2p listen multiaddr (default: `/ip4/127.0.0.1/tcp/0`)
- `-home`: Directory for keyshare storage (default: `/tmp/tss-<validator>`)
- `-db`: Database file path (default: `/tmp/tss-<validator>.db`)
- `-password`: Encryption password for keyshares (default: `demo-password`)

### keygen command:

- No flags required (keyID is auto-generated by DKLS)

### keyrefresh command:

- No flags required (uses latest keyshare automatically)

### sign command:

- `-message` (required): Message string to sign
122 changes: 122 additions & 0 deletions cmd/tss/dataprovider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package main

import (
"context"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"time"

"github.com/rs/zerolog"

"github.com/pushchain/push-chain-node/universalClient/tss/coordinator"
)

// StaticPushChainDataProvider implements PushChainDataProvider for demo/testing.
// It reads validator information from the shared node registry file.
type StaticPushChainDataProvider struct {
validatorAddress string
logger zerolog.Logger
}

// NewStaticPushChainDataProvider creates a new static data provider.
func NewStaticPushChainDataProvider(validatorAddress string, logger zerolog.Logger) *StaticPushChainDataProvider {
return &StaticPushChainDataProvider{
validatorAddress: validatorAddress,
logger: logger,
}
}

// GetLatestBlockNum returns the latest block number.
// For demo purposes, we return current time + 11 to ensure events created with current time
// are immediately eligible for processing (GetPendingEvents requires events to be 10 blocks behind).
func (p *StaticPushChainDataProvider) GetLatestBlockNum(ctx context.Context) (uint64, error) {
return uint64(time.Now().Unix()) + 11, nil
}

// GetUniversalValidators returns all universal validators.
func (p *StaticPushChainDataProvider) GetUniversalValidators(ctx context.Context) ([]*coordinator.UniversalValidator, error) {
// Read nodes from shared registry file
nodes, err := readNodeRegistry(p.logger)
if err != nil {
return nil, fmt.Errorf("failed to read node registry: %w", err)
}

// Convert to UniversalValidator list
validators := make([]*coordinator.UniversalValidator, 0, len(nodes))
for _, node := range nodes {
validators = append(validators, &coordinator.UniversalValidator{
ValidatorAddress: node.ValidatorAddress,
Status: coordinator.UVStatusActive,
Network: coordinator.NetworkInfo{
PeerID: node.PeerID,
Multiaddrs: node.Multiaddrs,
},
JoinedAtBlock: 0,
})
}

return validators, nil
}

// GetCurrentTSSKeyId returns the current TSS key ID.
// Checks the latest created keyshare file in the tmp directory.
func (p *StaticPushChainDataProvider) GetCurrentTSSKeyId(ctx context.Context) (string, error) {
// Construct the keyshare directory path based on validator address
// Default location is /tmp/tss-<validator>/keyshares
sanitized := strings.ReplaceAll(strings.ReplaceAll(p.validatorAddress, ":", "_"), "/", "_")
keyshareDir := filepath.Join("/tmp", fmt.Sprintf("tss-%s", sanitized), "keyshares")

// Check if directory exists
if _, err := os.Stat(keyshareDir); os.IsNotExist(err) {
// No keyshares directory yet, return empty string
return "", nil
}

// Read all files in the keyshare directory
entries, err := os.ReadDir(keyshareDir)
if err != nil {
return "", fmt.Errorf("failed to read keyshare directory: %w", err)
}

if len(entries) == 0 {
// No keyshares found
return "", nil
}

// Get file info for all entries and sort by modification time
type fileInfo struct {
name string
modTime time.Time
}

files := make([]fileInfo, 0, len(entries))
for _, entry := range entries {
if entry.IsDir() {
continue
}
info, err := entry.Info()
if err != nil {
p.logger.Warn().Err(err).Str("file", entry.Name()).Msg("failed to get file info, skipping")
continue
}
files = append(files, fileInfo{
name: entry.Name(),
modTime: info.ModTime(),
})
}

if len(files) == 0 {
return "", nil
}

// Sort by modification time (newest first)
sort.Slice(files, func(i, j int) bool {
return files[i].modTime.After(files[j].modTime)
})

// Return the most recent keyshare file name (which is the keyID)
return files[0].name, nil
}
Loading
Loading