Skip to content

Commit

Permalink
Add nonce related types to pkg/types
Browse files Browse the repository at this point in the history
  • Loading branch information
nitronit committed Dec 8, 2023
1 parent fbf90af commit b5033ad
Show file tree
Hide file tree
Showing 30 changed files with 158 additions and 134 deletions.
4 changes: 2 additions & 2 deletions cmd/horcrux/cmd/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func addressCmd() *cobra.Command {

key, err := signer.LoadCosignerEd25519Key(keyFile)
if err != nil {
return fmt.Errorf("error reading cosigner key: %w, check that key is present for chain ID: %s", err, chainID)
return fmt.Errorf("error reading cosigner key: %w, check that key is present for chain Index: %s", err, chainID)
}

pubKey = key.PubKey
Expand All @@ -58,7 +58,7 @@ func addressCmd() *cobra.Command {
}
keyFile, err := config.KeyFileExistsSingleSigner(chainID)
if err != nil {
return fmt.Errorf("error reading priv-validator key: %w, check that key is present for chain ID: %s", err, chainID)
return fmt.Errorf("error reading priv-validator key: %w, check that key is present for chain Index: %s", err, chainID)
}

filePV := cometprivval.LoadFilePVEmptyState(keyFile, "")
Expand Down
2 changes: 1 addition & 1 deletion cmd/horcrux/cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ grpcAddr: ""
"--raft-timeout", "500ms",
"--grpc-timeout", "500ms",
},
expectErr: `failed to parse cosigner (shard ID: 1) p2p address: parse "://10.168.1.1:2222": missing protocol scheme`,
expectErr: `failed to parse cosigner (shard Index: 1) p2p address: parse "://10.168.1.1:2222": missing protocol scheme`,
},
{
name: "invalid threshold",
Expand Down
4 changes: 2 additions & 2 deletions cmd/horcrux/cmd/leader_election.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func leaderElectionCmd() *cobra.Command {
Use: "elect [node_id]",
Short: "Elect new raft leader",
Long: `To choose the next eligible leader, pass no argument.
To choose a specific leader, pass that leader's ID as an argument.
To choose a specific leader, pass that leader's Index as an argument.
`,
Args: cobra.RangeArgs(0, 1),
Example: `horcrux elect # elect next eligible leader
Expand Down Expand Up @@ -140,7 +140,7 @@ func getLeaderCmd() *cobra.Command {
}

if p2pListen == "" {
return fmt.Errorf("cosigner config does not exist for our shard ID %d", id)
return fmt.Errorf("cosigner config does not exist for our shard Index %d", id)
}

retryOpts := []grpcretry.CallOption{
Expand Down
2 changes: 1 addition & 1 deletion cmd/horcrux/cmd/shards.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func createCosignerEd25519ShardsCmd() *cobra.Command {
_ = cmd.MarkFlagRequired(flagThreshold)
f.String(flagKeyFile, "", "priv_validator_key.json file to shard")
_ = cmd.MarkFlagRequired(flagKeyFile)
f.String(flagChainID, "", "key shards will sign for this chain ID")
f.String(flagChainID, "", "key shards will sign for this chain Index")
_ = cmd.MarkFlagRequired(flagChainID)

return cmd
Expand Down
4 changes: 2 additions & 2 deletions cmd/horcrux/cmd/threshold.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func NewThresholdValidator(
}

if p2pListen == "" {
return nil, nil, fmt.Errorf("cosigner config does not exist for our shard ID %d", security.GetID())
return nil, nil, fmt.Errorf("cosigner config does not exist for our shard Index %d", security.GetID())
}

localCosigner := signer.NewLocalCosigner(
Expand All @@ -74,7 +74,7 @@ func NewThresholdValidator(
return nil, nil, fmt.Errorf("error creating raft directory: %w", err)
}

// RAFT node ID is the cosigner ID
// RAFT node Index is the cosigner Index
nodeID := fmt.Sprint(security.GetID())

// Start RAFT store listener
Expand Down
30 changes: 30 additions & 0 deletions pkg/types/nonce.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Package types: Nonce.go contains the types for nonce and nonces
*/
package types

import "time"

// Nonces contains the ephemeral information generated by one cosigner (local) for all other cosigners (remote).
type Nonces struct {
PubKey []byte
Shares [][]byte
}

type NoncesWithExpiration struct {
Expiration time.Time
Nonces []Nonces
}

// Nonce is the ephemeral information from another cosigner (remote) destined for this cosigner (local).
type Nonce struct {
Index int
Share []byte
PubKey []byte
}

// PartialSignature contains the signature and identifier for a piece of the combined signature.
type PartialSignature struct {
Index int
Signature []byte
}
10 changes: 5 additions & 5 deletions signer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,26 +242,26 @@ type CosignersConfig []CosignerConfig
func (cosigners CosignersConfig) Validate() error {
// Check IDs to make sure none are duplicated
if dupl := duplicateCosigners(cosigners); len(dupl) != 0 {
return fmt.Errorf("found duplicate cosigner shard ID(s) in args: %v", dupl)
return fmt.Errorf("found duplicate cosigner shard Index(s) in args: %v", dupl)
}

shards := len(cosigners)

// Make sure that the cosigner IDs match the number of cosigners.
for _, cosigner := range cosigners {
if cosigner.ShardID < 1 || cosigner.ShardID > shards {
return fmt.Errorf("cosigner shard ID %d in args is out of range, must be between 1 and %d, inclusive",
return fmt.Errorf("cosigner shard Index %d in args is out of range, must be between 1 and %d, inclusive",
cosigner.ShardID, shards)
}

url, err := url.Parse(cosigner.P2PAddr)
if err != nil {
return fmt.Errorf("failed to parse cosigner (shard ID: %d) p2p address: %w", cosigner.ShardID, err)
return fmt.Errorf("failed to parse cosigner (shard Index: %d) p2p address: %w", cosigner.ShardID, err)
}

host, _, err := net.SplitHostPort(url.Host)
if err != nil {
return fmt.Errorf("failed to parse cosigner (shard ID: %d) host port: %w", cosigner.ShardID, err)
return fmt.Errorf("failed to parse cosigner (shard Index: %d) host port: %w", cosigner.ShardID, err)
}

if host == "0.0.0.0" {
Expand All @@ -287,7 +287,7 @@ func duplicateCosigners(cosigners []CosignerConfig) (duplicates map[int][]string

for shardID, cosigners := range idAddrs {
if len(cosigners) == 1 {
// One address per ID is correct.
// One address per Index is correct.
delete(idAddrs, shardID)
}
}
Expand Down
6 changes: 3 additions & 3 deletions signer/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func TestValidateThresholdModeConfig(t *testing.T) {
},
},
},
expectErr: fmt.Errorf("failed to parse cosigner (shard ID: 1) p2p address: %w", &url.Error{
expectErr: fmt.Errorf("failed to parse cosigner (shard Index: 1) p2p address: %w", &url.Error{
Op: "parse",
URL: ":2222",
Err: fmt.Errorf("missing protocol scheme"),
Expand Down Expand Up @@ -517,7 +517,7 @@ func TestCosignerRSAPubKeysConfigValidate(t *testing.T) {
P2PAddr: "tcp://127.0.0.1:2224",
},
},
expectErr: fmt.Errorf("cosigner shard ID 3 in args is out of range, must be between 1 and 2, inclusive"),
expectErr: fmt.Errorf("cosigner shard Index 3 in args is out of range, must be between 1 and 2, inclusive"),
},
{
name: "duplicate cosigner",
Expand All @@ -532,7 +532,7 @@ func TestCosignerRSAPubKeysConfigValidate(t *testing.T) {
},
},
expectErr: fmt.Errorf(
"found duplicate cosigner shard ID(s) in args: map[2:[tcp://127.0.0.1:2223 tcp://127.0.0.1:2223]]",
"found duplicate cosigner shard Index(s) in args: map[2:[tcp://127.0.0.1:2223 tcp://127.0.0.1:2223]]",
),
},
}
Expand Down
18 changes: 14 additions & 4 deletions signer/cosigner.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/*
Package signer: Cosinger is responsible for the network communication between the cosigners
*/
package signer

import (
Expand All @@ -11,12 +14,19 @@ import (
"github.com/strangelove-ventures/horcrux/signer/proto"
)

type Localcosigner interface {
// TODO - add methods
}
type Remotecosigner interface {
// TODO - add methods
}

// Cosigner interface is a set of methods for an m-of-n threshold signature.
// This interface abstracts the underlying key storage and management
type Cosigner interface {
// Get the ID of the cosigner
// The ID is the shamir index: 1, 2, etc...
GetID() int
// GetIndex gets the index of the cosigner
// The index is the shamir index: 1, 2, etc...
GetIndex() int

// Get the P2P URL (GRPC and Raft)
GetAddress() string
Expand All @@ -37,7 +47,7 @@ type Cosigners []Cosigner

func (cosigners Cosigners) GetByID(id int) Cosigner {
for _, cosigner := range cosigners {
if cosigner.GetID() == id {
if cosigner.GetIndex() == id {
return cosigner
}
}
Expand Down
6 changes: 4 additions & 2 deletions signer/cosigner_grpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type CosignerGRPCServer struct {
cosigner *LocalCosigner
thresholdValidator *ThresholdValidator
raftStore *RaftStore
// TODO: add logger and not rely on raftStore.logger
proto.UnimplementedCosignerServer
}

Expand Down Expand Up @@ -104,6 +105,7 @@ func (rpc *CosignerGRPCServer) GetNonces(
}, nil
}

// TODO: // TransferLeadership should not be a CosignerGRPCServer method?
func (rpc *CosignerGRPCServer) TransferLeadership(
_ context.Context,
req *proto.TransferLeadershipRequest,
Expand All @@ -114,10 +116,10 @@ func (rpc *CosignerGRPCServer) TransferLeadership(
leaderID := req.GetLeaderID()
if leaderID != "" {
for _, c := range rpc.raftStore.Cosigners {
shardID := fmt.Sprint(c.GetID())
shardID := fmt.Sprint(c.GetIndex())
if shardID == leaderID {
raftAddress := p2pURLToRaftAddress(c.GetAddress())
fmt.Printf("Transferring leadership to ID: %s - Address: %s\n", shardID, raftAddress)
fmt.Printf("Transferring leadership to Index: %s - Address: %s\n", shardID, raftAddress)
rpc.raftStore.raft.LeadershipTransferToServer(raft.ServerID(shardID), raft.ServerAddress(raftAddress))
return &proto.TransferLeadershipResponse{LeaderID: shardID, LeaderAddress: raftAddress}, nil
}
Expand Down
10 changes: 5 additions & 5 deletions signer/cosigner_health.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (ch *CosignerHealth) Start(ctx context.Context) {
func (ch *CosignerHealth) MarkUnhealthy(cosigner Cosigner) {
ch.mu.Lock()
defer ch.mu.Unlock()
ch.rtt[cosigner.GetID()] = -1
ch.rtt[cosigner.GetIndex()] = -1
}

func (ch *CosignerHealth) updateRTT(ctx context.Context, cosigner *RemoteCosigner, wg *sync.WaitGroup) {
Expand All @@ -72,15 +72,15 @@ func (ch *CosignerHealth) updateRTT(ctx context.Context, cosigner *RemoteCosigne
defer func() {
ch.mu.Lock()
defer ch.mu.Unlock()
ch.rtt[cosigner.GetID()] = rtt
ch.rtt[cosigner.GetIndex()] = rtt
}()
start := time.Now()
ctx, cancel := context.WithTimeout(ctx, 1*time.Second)
defer cancel()

_, err := cosigner.client.Ping(ctx, &proto.PingRequest{})
if err != nil {
ch.logger.Error("Failed to ping", "cosigner", cosigner.GetID(), "error", err)
ch.logger.Error("Failed to ping", "cosigner", cosigner.GetIndex(), "error", err)
return
}
rtt = time.Since(start).Nanoseconds()
Expand All @@ -94,8 +94,8 @@ func (ch *CosignerHealth) GetFastest() []Cosigner {
copy(fastest, ch.cosigners)

sort.Slice(fastest, func(i, j int) bool {
rtt1, ok1 := ch.rtt[fastest[i].GetID()]
rtt2, ok2 := ch.rtt[fastest[j].GetID()]
rtt1, ok1 := ch.rtt[fastest[i].GetIndex()]
rtt2, ok2 := ch.rtt[fastest[j].GetIndex()]
if rtt1 == -1 || !ok1 {
return false
}
Expand Down
4 changes: 2 additions & 2 deletions signer/cosigner_health_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ func TestCosignerHealth(t *testing.T) {

require.Len(t, fastest, 4)

require.Equal(t, 4, fastest[0].GetID())
require.Equal(t, 2, fastest[1].GetID())
require.Equal(t, 4, fastest[0].GetIndex())
require.Equal(t, 2, fastest[1].GetIndex())
}
8 changes: 4 additions & 4 deletions signer/cosigner_nonce_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func (cnc *CosignerNonceCache) LoadN(ctx context.Context, n int) {
missedNonces.WithLabelValues(p.GetAddress()).Add(float64(1))
totalMissedNonces.WithLabelValues(p.GetAddress()).Inc()

cnc.logger.Error("Failed to get nonces from peer", "peer", p.GetID(), "error", err)
cnc.logger.Error("Failed to get nonces from peer", "peer", p.GetIndex(), "error", err)
return
}

Expand Down Expand Up @@ -350,7 +350,7 @@ CheckNoncesLoop:
for _, p := range fastestPeers {
found := false
for _, n := range cn.Nonces {
if n.Cosigner.GetID() == p.GetID() {
if n.Cosigner.GetIndex() == p.GetIndex() {
found = true
nonces = append(nonces, n.Nonces...)
break
Expand Down Expand Up @@ -383,7 +383,7 @@ CheckNoncesLoop:
// no nonces found
cosignerInts := make([]int, len(fastestPeers))
for i, p := range fastestPeers {
cosignerInts[i] = p.GetID()
cosignerInts[i] = p.GetIndex()
}
return nil, fmt.Errorf("no nonces found involving cosigners %+v", cosignerInts)
}
Expand Down Expand Up @@ -418,7 +418,7 @@ func (cnc *CosignerNonceCache) ClearNonces(cosigner Cosigner) {

deleteID := -1
for j, n := range cn.Nonces {
if n.Cosigner.GetID() == cosigner.GetID() {
if n.Cosigner.GetIndex() == cosigner.GetIndex() {
// remove cosigner from this nonce.
deleteID = j
break
Expand Down
2 changes: 1 addition & 1 deletion signer/cosigner_security.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package signer

// CosignerSecurity is an interface for the security layer of the cosigner.
type CosignerSecurity interface {
// GetID returns the ID of the cosigner.
// GetID returns the Index of the cosigner.
GetID() int

// EncryptAndSign encrypts the nonce and signs it for authentication.
Expand Down
6 changes: 3 additions & 3 deletions signer/cosigner_security_ecies.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func NewCosignerSecurityECIES(key CosignerECIESKey) *CosignerSecurityECIES {
return c
}

// GetID returns the ID of the cosigner.
// GetID returns the Index of the cosigner.
func (c *CosignerSecurityECIES) GetID() int {
return c.key.ID
}
Expand All @@ -141,10 +141,10 @@ func (c *CosignerSecurityECIES) EncryptAndSign(id int, noncePub []byte, nonceSha
SourceID: c.key.ID,
}

// grab the cosigner info for the ID being requested
// grab the cosigner info for the Index being requested
pubKey, ok := c.eciesPubKeys[id]
if !ok {
return nonce, fmt.Errorf("unknown cosigner ID: %d", id)
return nonce, fmt.Errorf("unknown cosigner Index: %d", id)
}

var encryptedPub []byte
Expand Down
6 changes: 3 additions & 3 deletions signer/cosigner_security_rsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func NewCosignerSecurityRSA(key CosignerRSAKey) *CosignerSecurityRSA {
return c
}

// GetID returns the ID of the cosigner.
// GetID returns the Index of the cosigner.
func (c *CosignerSecurityRSA) GetID() int {
return c.key.ID
}
Expand All @@ -133,10 +133,10 @@ func (c *CosignerSecurityRSA) EncryptAndSign(id int, noncePub []byte, nonceShare
SourceID: c.key.ID,
}

// grab the cosigner info for the ID being requested
// grab the cosigner info for the Index being requested
pubKey, ok := c.rsaPubKeys[id]
if !ok {
return nonce, fmt.Errorf("unknown cosigner ID: %d", id)
return nonce, fmt.Errorf("unknown cosigner Index: %d", id)
}

var encryptedPub []byte
Expand Down
2 changes: 1 addition & 1 deletion signer/leader_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type MockLeader struct {
func (m *MockLeader) IsLeader() bool {
m.mu.Lock()
defer m.mu.Unlock()
return m.leader != nil && m.leader.myCosigner.GetID() == m.id
return m.leader != nil && m.leader.myCosigner.GetIndex() == m.id
}

func (m *MockLeader) SetLeader(tv *ThresholdValidator) {
Expand Down
Loading

0 comments on commit b5033ad

Please sign in to comment.