From db002a75be936309ff0094df1da159a52bedb74d Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Fri, 14 Mar 2025 14:01:21 +0100 Subject: [PATCH 01/29] propose remote signing --- pkg/remote_signer/file/README.md | 80 ++ pkg/remote_signer/file/example_test.go | 102 ++ pkg/remote_signer/file/local.go | 245 +++++ pkg/remote_signer/grpc/server.go | 37 + pkg/remote_signer/signer.go | 9 + pkg/remote_signer/v1/signer.pb.go | 914 ++++++++++++++++++ .../rollkit/pkg/remote_signer/v1/signer.proto | 29 + specs/lazy-adr/adr-012-remote-signer.md | 164 ++++ types/pb/rollkit/rollkit.pb.go | 2 +- types/pb/rollkit/state.pb.go | 10 +- 10 files changed, 1586 insertions(+), 6 deletions(-) create mode 100644 pkg/remote_signer/file/README.md create mode 100644 pkg/remote_signer/file/example_test.go create mode 100644 pkg/remote_signer/file/local.go create mode 100644 pkg/remote_signer/grpc/server.go create mode 100644 pkg/remote_signer/signer.go create mode 100644 pkg/remote_signer/v1/signer.pb.go create mode 100644 proto/rollkit/pkg/remote_signer/v1/signer.proto create mode 100644 specs/lazy-adr/adr-012-remote-signer.md diff --git a/pkg/remote_signer/file/README.md b/pkg/remote_signer/file/README.md new file mode 100644 index 0000000000..f4db5f7f6c --- /dev/null +++ b/pkg/remote_signer/file/README.md @@ -0,0 +1,80 @@ +# Secure FileSystem Signer + +This package provides a secure implementation of a signer that stores cryptographic keys on the filesystem. The implementation follows security best practices to ensure that private keys are never stored in plain text on disk. + +## Features + +- **Secure Key Storage**: Private keys are encrypted using AES-GCM before being stored on disk +- **Passphrase Protection**: Keys are protected by a user-provided passphrase +- **In-Memory Operation**: Once loaded, keys remain in memory for signing operations +- **Automatic Key Generation**: If keys don't exist, they are automatically generated +- **Thread Safety**: Concurrent access to the signer is protected by mutex locks + +## Security Measures + +1. **Encryption**: Private keys are encrypted using AES-GCM, a secure authenticated encryption mode +2. **Permissions**: Key files are stored with 0600 permissions (readable and writable only by the owner) +3. **Directory Creation**: Key directories are created with 0700 permissions +4. **No Plain Text**: Private keys are never stored in plain text on disk +5. **Passphrase Derivation**: A key derivation function is used to derive encryption keys from passphrases + +## Usage + +```go +// Create a new signer (or load existing keys) +passphrase := []byte("your-secure-passphrase") +keyPath := "/path/to/secure/keys.json" +signer, err := NewFileSystemSigner(keyPath, passphrase) +if err != nil { + // Handle error +} + +// Sign a message +message := []byte("Message to sign") +signature, err := signer.Sign(message) +if err != nil { + // Handle error +} + +// Get the public key +pubKey, err := signer.GetPublic() +if err != nil { + // Handle error +} +``` + +## Production Considerations + +For production use, consider the following enhancements: + +1. **Stronger KDF**: Replace the simple key derivation function with Argon2 or PBKDF2 +2. **Secure Passphrase Handling**: Implement secure methods for obtaining and handling passphrases +3. **Memory Protection**: Add memory protection to prevent keys from being swapped to disk +4. **Key Rotation**: Implement key rotation policies +5. **Hardware Security**: For high-security environments, consider using hardware security modules (HSMs) + +## Implementation Details + +The `FileSystemSigner` stores keys in a JSON file with the following structure: + +```json +{ + "priv_key_encrypted": "...", // Base64-encoded encrypted private key + "nonce": "...", // Base64-encoded nonce for AES-GCM + "pub_key": "..." // Base64-encoded public key +} +``` + +The encryption process: + +1. Generate a random nonce +2. Derive an encryption key from the passphrase +3. Encrypt the private key using AES-GCM with the derived key and nonce +4. Store the encrypted private key, nonce, and public key in the JSON file + +The decryption process: + +1. Read the JSON file +2. Derive the encryption key from the passphrase +3. Decrypt the private key using AES-GCM with the derived key and stored nonce +4. Load the keys into memory for use diff --git a/pkg/remote_signer/file/example_test.go b/pkg/remote_signer/file/example_test.go new file mode 100644 index 0000000000..5dab037221 --- /dev/null +++ b/pkg/remote_signer/file/example_test.go @@ -0,0 +1,102 @@ +package file + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFileSystemSigner(t *testing.T) { + // Create a temporary directory for the test + tempDir := t.TempDir() + keyPath := filepath.Join(tempDir, "secure_keys.json") + passphrase := []byte("test-passphrase-123") + + // Create a new signer (this will generate and save keys) + signer, err := NewFileSystemSigner(keyPath, passphrase) + require.NoError(t, err) + require.NotNil(t, signer) + + // Verify the key file was created + _, err = os.Stat(keyPath) + require.NoError(t, err) + + // Get the public key + pubKey, err := signer.GetPublic() + require.NoError(t, err) + require.NotNil(t, pubKey) + + // Sign a message + message := []byte("Hello, world!") + signature, err := signer.Sign(message) + require.NoError(t, err) + require.NotNil(t, signature) + + // Verify the signature + valid, err := pubKey.Verify(message, signature) + require.NoError(t, err) + assert.True(t, valid) + + // Create a new signer instance (this will load the existing keys) + signer2, err := NewFileSystemSigner(keyPath, passphrase) + require.NoError(t, err) + require.NotNil(t, signer2) + + // Get the public key from the second signer + pubKey2, err := signer2.GetPublic() + require.NoError(t, err) + require.NotNil(t, pubKey2) + + // Verify that both signers have the same public key + pubKeyBytes1, err := pubKey.Raw() + require.NoError(t, err) + pubKeyBytes2, err := pubKey2.Raw() + require.NoError(t, err) + assert.Equal(t, pubKeyBytes1, pubKeyBytes2) + + // Test with wrong passphrase + wrongPassphrase := []byte("wrong-passphrase") + _, err = NewFileSystemSigner(keyPath, wrongPassphrase) + assert.Error(t, err) +} + +// Example demonstrates how to use the FileSystemSigner +func Example() { + // In a real application, you would use a secure passphrase + passphrase := []byte("your-secure-passphrase") + keyPath := "/path/to/secure/keys.json" + + // Create or load a signer + signer, err := NewFileSystemSigner(keyPath, passphrase) + if err != nil { + panic(err) + } + + // Sign a message + message := []byte("Message to sign") + signature, err := signer.Sign(message) + if err != nil { + panic(err) + } + + // Get the public key + pubKey, err := signer.GetPublic() + if err != nil { + panic(err) + } + + // Verify the signature (typically done by another party) + valid, err := pubKey.Verify(message, signature) + if err != nil { + panic(err) + } + + if valid { + // Signature is valid + } else { + // Signature is invalid + } +} diff --git a/pkg/remote_signer/file/local.go b/pkg/remote_signer/file/local.go new file mode 100644 index 0000000000..48330ab78c --- /dev/null +++ b/pkg/remote_signer/file/local.go @@ -0,0 +1,245 @@ +package file + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "sync" + + "github.com/libp2p/go-libp2p/core/crypto" +) + +// FileSystemSigner implements a signer that securely stores keys on disk +// and loads them into memory only when needed. +type FileSystemSigner struct { + privateKey crypto.PrivKey + publicKey crypto.PubKey + keyFile string + mu sync.RWMutex +} + +// keyData represents the encrypted key data stored on disk +type keyData struct { + PrivKeyEncrypted []byte `json:"priv_key_encrypted"` + Nonce []byte `json:"nonce"` + PubKeyBytes []byte `json:"pub_key"` +} + +// NewFileSystemSigner creates a new signer that stores keys securely on disk. +// If the keys don't exist at the specified paths, it generates new ones. +func NewFileSystemSigner(keyPath string, passphrase []byte) (*FileSystemSigner, error) { + // Create directory if it doesn't exist + dir := filepath.Dir(keyPath) + if err := os.MkdirAll(dir, 0700); err != nil { + return nil, fmt.Errorf("failed to create directory: %w", err) + } + + // Check if key file exists + if _, err := os.Stat(keyPath); os.IsNotExist(err) { + // Generate new keys + return generateAndSaveKeys(keyPath, passphrase) + } + + // Load existing keys + signer := &FileSystemSigner{ + keyFile: keyPath, + } + + // Load keys into memory + if err := signer.loadKeys(passphrase); err != nil { + return nil, err + } + + return signer, nil +} + +// generateAndSaveKeys creates a new key pair and saves it to disk +func generateAndSaveKeys(keyPath string, passphrase []byte) (*FileSystemSigner, error) { + // Generate new Ed25519 key pair + privKey, pubKey, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + if err != nil { + return nil, fmt.Errorf("failed to generate key pair: %w", err) + } + + signer := &FileSystemSigner{ + privateKey: privKey, + publicKey: pubKey, + keyFile: keyPath, + } + + // Save keys to disk + if err := signer.saveKeys(passphrase); err != nil { + return nil, err + } + + return signer, nil +} + +// saveKeys encrypts and saves the private key to disk +func (s *FileSystemSigner) saveKeys(passphrase []byte) error { + s.mu.RLock() + defer s.mu.RUnlock() + + if s.privateKey == nil || s.publicKey == nil { + return fmt.Errorf("keys not initialized") + } + + // Get raw private key bytes + privKeyBytes, err := s.privateKey.Raw() + if err != nil { + return fmt.Errorf("failed to get raw private key: %w", err) + } + + // Get raw public key bytes + pubKeyBytes, err := s.publicKey.Raw() + if err != nil { + return fmt.Errorf("failed to get raw public key: %w", err) + } + + // Create AES cipher from passphrase + // Use a key derivation function in production code + key := deriveKey(passphrase, 32) + block, err := aes.NewCipher(key) + if err != nil { + return fmt.Errorf("failed to create cipher: %w", err) + } + + // Create GCM mode + gcm, err := cipher.NewGCM(block) + if err != nil { + return fmt.Errorf("failed to create GCM: %w", err) + } + + // Create a nonce + nonce := make([]byte, gcm.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return fmt.Errorf("failed to generate nonce: %w", err) + } + + // Encrypt the private key + encryptedPrivKey := gcm.Seal(nil, nonce, privKeyBytes, nil) + + // Create key data structure + data := keyData{ + PrivKeyEncrypted: encryptedPrivKey, + Nonce: nonce, + PubKeyBytes: pubKeyBytes, + } + + // Marshal to JSON + jsonData, err := json.Marshal(data) + if err != nil { + return fmt.Errorf("failed to marshal key data: %w", err) + } + + // Write to file with secure permissions + if err := os.WriteFile(s.keyFile, jsonData, 0600); err != nil { + return fmt.Errorf("failed to write key file: %w", err) + } + + return nil +} + +// loadKeys decrypts and loads the keys from disk into memory +func (s *FileSystemSigner) loadKeys(passphrase []byte) error { + s.mu.Lock() + defer s.mu.Unlock() + + // Read the key file + jsonData, err := os.ReadFile(s.keyFile) + if err != nil { + return fmt.Errorf("failed to read key file: %w", err) + } + + // Unmarshal JSON + var data keyData + if err := json.Unmarshal(jsonData, &data); err != nil { + return fmt.Errorf("failed to unmarshal key data: %w", err) + } + + // Create AES cipher from passphrase + key := deriveKey(passphrase, 32) + block, err := aes.NewCipher(key) + if err != nil { + return fmt.Errorf("failed to create cipher: %w", err) + } + + // Create GCM mode + gcm, err := cipher.NewGCM(block) + if err != nil { + return fmt.Errorf("failed to create GCM: %w", err) + } + + // Decrypt the private key + privKeyBytes, err := gcm.Open(nil, data.Nonce, data.PrivKeyEncrypted, nil) + if err != nil { + return fmt.Errorf("failed to decrypt private key (wrong passphrase?): %w", err) + } + + // Unmarshal the private key + privKey, err := crypto.UnmarshalEd25519PrivateKey(privKeyBytes) + if err != nil { + return fmt.Errorf("failed to unmarshal private key: %w", err) + } + + // Unmarshal the public key + pubKey, err := crypto.UnmarshalEd25519PublicKey(data.PubKeyBytes) + if err != nil { + return fmt.Errorf("failed to unmarshal public key: %w", err) + } + + // Set the keys + s.privateKey = privKey + s.publicKey = pubKey + + return nil +} + +// Sign signs a message using the private key +func (s *FileSystemSigner) Sign(message []byte) ([]byte, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + if s.privateKey == nil { + return nil, fmt.Errorf("private key not loaded") + } + + return s.privateKey.Sign(message) +} + +// GetPublic returns the public key +func (s *FileSystemSigner) GetPublic() (crypto.PubKey, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + if s.publicKey == nil { + return nil, fmt.Errorf("public key not loaded") + } + + return s.publicKey, nil +} + +// deriveKey is a simple key derivation function +// In production, use a proper KDF like Argon2 or PBKDF2 +func deriveKey(passphrase []byte, keyLen int) []byte { + // This is a simplified version for demonstration + // In production, use a proper KDF with salt and iterations + if len(passphrase) >= keyLen { + return passphrase[:keyLen] + } + + key := make([]byte, keyLen) + copy(key, passphrase) + + // Fill the rest with a deterministic pattern based on the passphrase + for i := len(passphrase); i < keyLen; i++ { + key[i] = passphrase[i%len(passphrase)] ^ byte(i) + } + + return key +} diff --git a/pkg/remote_signer/grpc/server.go b/pkg/remote_signer/grpc/server.go new file mode 100644 index 0000000000..05ad5e546b --- /dev/null +++ b/pkg/remote_signer/grpc/server.go @@ -0,0 +1,37 @@ +package grpc + +import ( + "context" + + v1 "github.com/rollkit/rollkit/pkg/remote_signer/v1" +) + +// RemoteSigner implements the SignerService generated interface from the .proto +type RemoteSignerServer struct { + signer v1.SignerServiceServer + v1.UnimplementedSignerServiceServer // Embedded for forward compatibility +} + +func NewRemoteSignerServer(s v1.SignerServiceServer) *RemoteSignerServer { + return &RemoteSignerServer{signer: s} +} + +func (r *RemoteSignerServer) Sign(ctx context.Context, req *v1.SignRequest) (*v1.SignResponse, error) { + sig, err := r.signer.Sign(ctx, req) + if err != nil { + return nil, err + } + return &v1.SignResponse{ + Signature: sig, + }, nil +} + +func (r *RemoteSignerServer) GetPublic(ctx context.Context, _ v1.GetPublicRequest) (*v1.GetPublicResponse, error) { + pub, err := r.signer.GetPublic() + if err != nil { + return nil, err + } + return &v1.GetPublicResponse{ + PublicKey: pub, + }, nil +} diff --git a/pkg/remote_signer/signer.go b/pkg/remote_signer/signer.go new file mode 100644 index 0000000000..023a5da630 --- /dev/null +++ b/pkg/remote_signer/signer.go @@ -0,0 +1,9 @@ +package remote_signer + +type Signer interface { + // Sign takes a message as bytes and returns its signature. + Sign(message []byte) ([]byte, error) + + // GetPublic returns the public key paired with this private key. + GetPublic() ([]byte, error) +} diff --git a/pkg/remote_signer/v1/signer.pb.go b/pkg/remote_signer/v1/signer.pb.go new file mode 100644 index 0000000000..4f258e6c7a --- /dev/null +++ b/pkg/remote_signer/v1/signer.pb.go @@ -0,0 +1,914 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: rollkit/pkg/remote_signer/v1/signer.proto + +package v1 + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// The SignRequest holds the bytes we want to sign. +type SignRequest struct { + Message []byte `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (m *SignRequest) Reset() { *m = SignRequest{} } +func (m *SignRequest) String() string { return proto.CompactTextString(m) } +func (*SignRequest) ProtoMessage() {} +func (*SignRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_fc0896255c20ccbe, []int{0} +} +func (m *SignRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignRequest.Merge(m, src) +} +func (m *SignRequest) XXX_Size() int { + return m.Size() +} +func (m *SignRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SignRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SignRequest proto.InternalMessageInfo + +func (m *SignRequest) GetMessage() []byte { + if m != nil { + return m.Message + } + return nil +} + +// The SignResponse returns the signature bytes. +type SignResponse struct { + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (m *SignResponse) Reset() { *m = SignResponse{} } +func (m *SignResponse) String() string { return proto.CompactTextString(m) } +func (*SignResponse) ProtoMessage() {} +func (*SignResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_fc0896255c20ccbe, []int{1} +} +func (m *SignResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignResponse.Merge(m, src) +} +func (m *SignResponse) XXX_Size() int { + return m.Size() +} +func (m *SignResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SignResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SignResponse proto.InternalMessageInfo + +func (m *SignResponse) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +// The GetPublicRequest is an empty request. +type GetPublicRequest struct { +} + +func (m *GetPublicRequest) Reset() { *m = GetPublicRequest{} } +func (m *GetPublicRequest) String() string { return proto.CompactTextString(m) } +func (*GetPublicRequest) ProtoMessage() {} +func (*GetPublicRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_fc0896255c20ccbe, []int{2} +} +func (m *GetPublicRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetPublicRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetPublicRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetPublicRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetPublicRequest.Merge(m, src) +} +func (m *GetPublicRequest) XXX_Size() int { + return m.Size() +} +func (m *GetPublicRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetPublicRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetPublicRequest proto.InternalMessageInfo + +// The GetPublicResponse returns the public key. +type GetPublicResponse struct { + PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` +} + +func (m *GetPublicResponse) Reset() { *m = GetPublicResponse{} } +func (m *GetPublicResponse) String() string { return proto.CompactTextString(m) } +func (*GetPublicResponse) ProtoMessage() {} +func (*GetPublicResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_fc0896255c20ccbe, []int{3} +} +func (m *GetPublicResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetPublicResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetPublicResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetPublicResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetPublicResponse.Merge(m, src) +} +func (m *GetPublicResponse) XXX_Size() int { + return m.Size() +} +func (m *GetPublicResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetPublicResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetPublicResponse proto.InternalMessageInfo + +func (m *GetPublicResponse) GetPublicKey() []byte { + if m != nil { + return m.PublicKey + } + return nil +} + +func init() { + proto.RegisterType((*SignRequest)(nil), "rollkit.pkg.remote_signer.v1.SignRequest") + proto.RegisterType((*SignResponse)(nil), "rollkit.pkg.remote_signer.v1.SignResponse") + proto.RegisterType((*GetPublicRequest)(nil), "rollkit.pkg.remote_signer.v1.GetPublicRequest") + proto.RegisterType((*GetPublicResponse)(nil), "rollkit.pkg.remote_signer.v1.GetPublicResponse") +} + +func init() { + proto.RegisterFile("rollkit/pkg/remote_signer/v1/signer.proto", fileDescriptor_fc0896255c20ccbe) +} + +var fileDescriptor_fc0896255c20ccbe = []byte{ + // 284 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2c, 0xca, 0xcf, 0xc9, + 0xc9, 0xce, 0x2c, 0xd1, 0x2f, 0xc8, 0x4e, 0xd7, 0x2f, 0x4a, 0xcd, 0xcd, 0x2f, 0x49, 0x8d, 0x2f, + 0xce, 0x4c, 0xcf, 0x4b, 0x2d, 0xd2, 0x2f, 0x33, 0xd4, 0x87, 0xb0, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, + 0xf2, 0x85, 0x64, 0xa0, 0x4a, 0xf5, 0x0a, 0xb2, 0xd3, 0xf5, 0x50, 0x94, 0xea, 0x95, 0x19, 0x2a, + 0xa9, 0x73, 0x71, 0x07, 0x67, 0xa6, 0xe7, 0x05, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x49, + 0x70, 0xb1, 0xe7, 0xa6, 0x16, 0x17, 0x27, 0xa6, 0xa7, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, + 0xc1, 0xb8, 0x4a, 0x3a, 0x5c, 0x3c, 0x10, 0x85, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x32, + 0x5c, 0x9c, 0x20, 0x53, 0x12, 0x4b, 0x4a, 0x8b, 0x60, 0x6a, 0x11, 0x02, 0x4a, 0x42, 0x5c, 0x02, + 0xee, 0xa9, 0x25, 0x01, 0xa5, 0x49, 0x39, 0x99, 0xc9, 0x50, 0xb3, 0x95, 0x8c, 0xb8, 0x04, 0x91, + 0xc4, 0xa0, 0xc6, 0xc8, 0x72, 0x71, 0x15, 0x80, 0x45, 0xe2, 0xb3, 0x53, 0x2b, 0x61, 0xe6, 0x40, + 0x44, 0xbc, 0x53, 0x2b, 0x8d, 0xee, 0x30, 0x72, 0xf1, 0x06, 0x83, 0x1d, 0x1b, 0x9c, 0x5a, 0x54, + 0x96, 0x99, 0x9c, 0x2a, 0x14, 0xcb, 0xc5, 0x02, 0x12, 0x10, 0xd2, 0xd4, 0xc3, 0xe7, 0x2f, 0x3d, + 0x24, 0x4f, 0x49, 0x69, 0x11, 0xa3, 0x14, 0xea, 0x9e, 0x1c, 0x2e, 0x4e, 0xb8, 0x23, 0x85, 0xf4, + 0xf0, 0x6b, 0x44, 0xf7, 0xa1, 0x94, 0x3e, 0xd1, 0xea, 0x21, 0xb6, 0x39, 0x79, 0x9e, 0x78, 0x24, + 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, + 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x7e, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, + 0x72, 0x7e, 0xae, 0x3e, 0x2c, 0xae, 0xf1, 0xc5, 0x79, 0x12, 0x1b, 0x38, 0xb6, 0x8d, 0x01, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x69, 0xc4, 0x09, 0x0f, 0x1a, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// SignerServiceClient is the client API for SignerService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type SignerServiceClient interface { + Sign(ctx context.Context, in *SignRequest, opts ...grpc.CallOption) (*SignResponse, error) + GetPublic(ctx context.Context, in *GetPublicRequest, opts ...grpc.CallOption) (*GetPublicResponse, error) +} + +type signerServiceClient struct { + cc grpc1.ClientConn +} + +func NewSignerServiceClient(cc grpc1.ClientConn) SignerServiceClient { + return &signerServiceClient{cc} +} + +func (c *signerServiceClient) Sign(ctx context.Context, in *SignRequest, opts ...grpc.CallOption) (*SignResponse, error) { + out := new(SignResponse) + err := c.cc.Invoke(ctx, "/rollkit.pkg.remote_signer.v1.SignerService/Sign", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *signerServiceClient) GetPublic(ctx context.Context, in *GetPublicRequest, opts ...grpc.CallOption) (*GetPublicResponse, error) { + out := new(GetPublicResponse) + err := c.cc.Invoke(ctx, "/rollkit.pkg.remote_signer.v1.SignerService/GetPublic", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// SignerServiceServer is the server API for SignerService service. +type SignerServiceServer interface { + Sign(context.Context, *SignRequest) (*SignResponse, error) + GetPublic(context.Context, *GetPublicRequest) (*GetPublicResponse, error) +} + +// UnimplementedSignerServiceServer can be embedded to have forward compatible implementations. +type UnimplementedSignerServiceServer struct { +} + +func (*UnimplementedSignerServiceServer) Sign(ctx context.Context, req *SignRequest) (*SignResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Sign not implemented") +} +func (*UnimplementedSignerServiceServer) GetPublic(ctx context.Context, req *GetPublicRequest) (*GetPublicResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetPublic not implemented") +} + +func RegisterSignerServiceServer(s grpc1.Server, srv SignerServiceServer) { + s.RegisterService(&_SignerService_serviceDesc, srv) +} + +func _SignerService_Sign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SignerServiceServer).Sign(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/rollkit.pkg.remote_signer.v1.SignerService/Sign", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SignerServiceServer).Sign(ctx, req.(*SignRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SignerService_GetPublic_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetPublicRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SignerServiceServer).GetPublic(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/rollkit.pkg.remote_signer.v1.SignerService/GetPublic", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SignerServiceServer).GetPublic(ctx, req.(*GetPublicRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _SignerService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "rollkit.pkg.remote_signer.v1.SignerService", + HandlerType: (*SignerServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Sign", + Handler: _SignerService_Sign_Handler, + }, + { + MethodName: "GetPublic", + Handler: _SignerService_GetPublic_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "rollkit/pkg/remote_signer/v1/signer.proto", +} + +func (m *SignRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Message) > 0 { + i -= len(m.Message) + copy(dAtA[i:], m.Message) + i = encodeVarintSigner(dAtA, i, uint64(len(m.Message))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SignResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signature) > 0 { + i -= len(m.Signature) + copy(dAtA[i:], m.Signature) + i = encodeVarintSigner(dAtA, i, uint64(len(m.Signature))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GetPublicRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetPublicRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetPublicRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetPublicResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetPublicResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetPublicResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.PublicKey) > 0 { + i -= len(m.PublicKey) + copy(dAtA[i:], m.PublicKey) + i = encodeVarintSigner(dAtA, i, uint64(len(m.PublicKey))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintSigner(dAtA []byte, offset int, v uint64) int { + offset -= sovSigner(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *SignRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Message) + if l > 0 { + n += 1 + l + sovSigner(uint64(l)) + } + return n +} + +func (m *SignResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signature) + if l > 0 { + n += 1 + l + sovSigner(uint64(l)) + } + return n +} + +func (m *GetPublicRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetPublicResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.PublicKey) + if l > 0 { + n += 1 + l + sovSigner(uint64(l)) + } + return n +} + +func sovSigner(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozSigner(x uint64) (n int) { + return sovSigner(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *SignRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSigner + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSigner + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthSigner + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthSigner + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Message = append(m.Message[:0], dAtA[iNdEx:postIndex]...) + if m.Message == nil { + m.Message = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipSigner(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthSigner + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSigner + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSigner + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthSigner + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthSigner + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...) + if m.Signature == nil { + m.Signature = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipSigner(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthSigner + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetPublicRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSigner + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetPublicRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetPublicRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipSigner(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthSigner + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetPublicResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSigner + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetPublicResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetPublicResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSigner + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthSigner + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthSigner + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PublicKey = append(m.PublicKey[:0], dAtA[iNdEx:postIndex]...) + if m.PublicKey == nil { + m.PublicKey = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipSigner(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthSigner + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipSigner(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSigner + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSigner + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSigner + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthSigner + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupSigner + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthSigner + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthSigner = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowSigner = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupSigner = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/rollkit/pkg/remote_signer/v1/signer.proto b/proto/rollkit/pkg/remote_signer/v1/signer.proto new file mode 100644 index 0000000000..7b8316652c --- /dev/null +++ b/proto/rollkit/pkg/remote_signer/v1/signer.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package rollkit.pkg.remote_signer.v1; + +option go_package = "github.com/rollkit/rollkit/pkg/remote_signer/v1"; + +// The SignRequest holds the bytes we want to sign. +message SignRequest { + bytes message = 1; +} + +// The SignResponse returns the signature bytes. +message SignResponse { + bytes signature = 1; +} + +// The GetPublicRequest is an empty request. +message GetPublicRequest {} + +// The GetPublicResponse returns the public key. +message GetPublicResponse { + bytes public_key = 1; +} + +// The SignerService defines the RPCs to sign and to retrieve the public key. +service SignerService { + rpc Sign(SignRequest) returns (SignResponse); + rpc GetPublic(GetPublicRequest) returns (GetPublicResponse); +} \ No newline at end of file diff --git a/specs/lazy-adr/adr-012-remote-signer.md b/specs/lazy-adr/adr-012-remote-signer.md new file mode 100644 index 0000000000..01ddaa4572 --- /dev/null +++ b/specs/lazy-adr/adr-012-remote-signer.md @@ -0,0 +1,164 @@ + +# ADR 0012: Remote Signing Service for Fast and Secure Digital Signatures + +## Changelog + +- 2025-03-14: Initial ADR creation including remote and local signing implementations, gRPC client/server flow, . + +## Context + +Rollkit with single or multiple signers requires a fast, secure, and flexible digital signing solution. Currently, nodes perform local signing using keys stored on disk. However, this approach distributes private keys across many nodes, increasing the risk of compromise. By centralizing the signing process behind a remote service—ideally backed by an HSM (Hardware Security Module)—we can both secure our keys and achieve high availability. This remote signing service will also allow clients written in different languages to use a unified API through gRPC. + +## Alternative Approaches + +- **Local File-Based Signing Only:** + While simpler to implement and sufficient for development, this approach requires each node to hold a copy of the private key, increasing the risk of key compromise and reducing overall system security. + +- **REST API for Remote Signing:** + A RESTful service could be implemented for signing, but it would likely have higher latency and overhead compared to gRPC. Additionally, REST is less efficient for binary data transfers required for cryptographic operations. + +- **Direct HSM Integration at Each Node:** + Integrating HSMs directly with every node would be secure but expensive and complex to manage at scale. + +The chosen approach of a centralized, remote signing service via gRPC offers a balance of security, performance, and ease of multi-language support. + +## Decision + +We will implement a remote signing service that uses gRPC to communicate between the client node and the signing server. The signing server will act as a front for our secure key storage (which could be an HSM or similar secure system) to sign messages on demand. Additionally, a local file-based signing implementation will be provided for development and fallback scenarios. The interface for signing remains consistent across implementations: + +```mermaid +graph TD + A[Client Node] -->|gRPC Call: Sign()/GetPublic()| B[HSM / Remote Signing Server] + B -->|Uses| C[Secure Key Storage (HSM)] + B -->|Returns Signature/Public Key| A +``` + +```go +type Signer interface { + // Cryptographically sign the given bytes. + Sign(message []byte) ([]byte, error) + + // Return a public key paired with this private key. + GetPublic() ([]byte, error) +} +``` + +## Detailed Design + +### User Requirements + +- Nodes require a fast and secure way to sign messages. +- The signing service must be accessible from multiple programming languages. +- Private keys must be centrally managed and secured. + +### Affected Systems + +- Node signing functionality. +- Key management system (e.g., HSM or secure file storage). +- gRPC-based communication layer. + +### Data Structures and APIs + +- Data Structures: The Signer interface remains unchanged. The implementation details for private/public key handling may vary. +- APIs: +The gRPC service is defined with the following protobuf: + +```proto +syntax = "proto3"; + +package signer; + +import "google/protobuf/empty.proto"; + +// The SignRequest holds the bytes we want to sign. +message SignRequest { + bytes message = 1; +} + +// The SignResponse returns the signature bytes. +message SignResponse { + bytes signature = 1; +} + +// GetPublicRequest requests the public key +message GetPublicRequest {} + +// The GetPublicResponse returns the public key. +message GetPublicResponse { + bytes public_key = 1; +} + +// The SignerService defines the RPCs to sign and to retrieve the public key. +service SignerService { + rpc Sign(SignRequest) returns (SignResponse); + rpc GetPublic(GetPublicRequest) returns (GetPublicResponse); +} +``` + +### Efficiency Considerations + +- Time: gRPC provides low-latency communication suitable for high-frequency signing operations. +- Space: Efficient binary serialization minimizes payload sizes. + +### Expected Access Patterns + +- High-throughput, low-latency signing requests. +- Frequent public key retrievals for validation. + +### Logging, Monitoring, and Observability + +- Integration with centralized logging systems. +- Metrics collection on signing latency and error rates. +- Alerts for network issues between nodes and the signing service. + +### Security Considerations + +- Centralized key management minimizes the risk of key exposure. +- Use of gRPC ensures secure communication channels (with TLS in production). +- Role-based access and auditing for signing operations. + +### Testing Strategy + +- Unit tests for both local and remote implementations. +- Integration tests to validate end-to-end gRPC communication. +- Performance benchmarks to ensure signing meets throughput requirements. + +### Deployment Considerations + +- Rolling deployment of the signing service with failover strategies. +- Monitoring and logging setups to capture operational metrics. +- Potential need for a breaking release if nodes rely on the remote signing service without fallback. + +## Status + +Proposed + +## Consequences + +## Positive + + • Enhanced Security: Private keys remain secure on a centralized, controlled system. + • High Availability: Multiple instances of the signing service behind a load balancer can provide failover. + • Language Agnosticism: gRPC allows clients in multiple programming languages to use the same service. + +## Negative + + • Increased Complexity: Additional operational overhead for managing a remote service. + • Network Dependency: Nodes depend on network connectivity to access the signing service. + • Potential Latency: Although gRPC is optimized, remote calls add a slight delay compared to local signing. + +## Neutral + + • Fallback Capability: The availability of both local and remote implementations ensures flexibility during development and production. + +## References +- gRPC Documentation +- HSM Best Practices + +⸻ + +Revised Remote Signing Flow Diagram + +This diagram illustrates the updated flow where the client node makes a gRPC call to the HSM-based signing server. + + diff --git a/types/pb/rollkit/rollkit.pb.go b/types/pb/rollkit/rollkit.pb.go index 77105f1111..9a5ef4bf77 100644 --- a/types/pb/rollkit/rollkit.pb.go +++ b/types/pb/rollkit/rollkit.pb.go @@ -6,7 +6,7 @@ package rollkit import ( fmt "fmt" types "github.com/cometbft/cometbft/proto/tendermint/types" - proto "github.com/gogo/protobuf/proto" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" diff --git a/types/pb/rollkit/state.pb.go b/types/pb/rollkit/state.pb.go index 3212ae1f6a..5e3399e0e8 100644 --- a/types/pb/rollkit/state.pb.go +++ b/types/pb/rollkit/state.pb.go @@ -7,9 +7,9 @@ import ( fmt "fmt" state "github.com/cometbft/cometbft/proto/tendermint/state" types "github.com/cometbft/cometbft/proto/tendermint/types" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" _ "github.com/gogo/protobuf/gogoproto" - proto "github.com/gogo/protobuf/proto" - github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" @@ -244,7 +244,7 @@ func (m *State) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x58 } - n2, err2 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime):]) + n2, err2 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastBlockTime):]) if err2 != nil { return 0, err2 } @@ -327,7 +327,7 @@ func (m *State) Size() (n int) { } l = m.LastBlockID.Size() n += 1 + l + sovState(uint64(l)) - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastBlockTime) n += 1 + l + sovState(uint64(l)) if m.DAHeight != 0 { n += 1 + sovState(uint64(m.DAHeight)) @@ -548,7 +548,7 @@ func (m *State) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.LastBlockTime, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.LastBlockTime, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex From f312f497e332f09d6aaf95546f7442d0ae90a522 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Fri, 14 Mar 2025 14:10:46 +0100 Subject: [PATCH 02/29] reduce noise --- specs/lazy-adr/adr-012-remote-signer.md | 58 +++---------------------- 1 file changed, 5 insertions(+), 53 deletions(-) diff --git a/specs/lazy-adr/adr-012-remote-signer.md b/specs/lazy-adr/adr-012-remote-signer.md index 01ddaa4572..054287edfa 100644 --- a/specs/lazy-adr/adr-012-remote-signer.md +++ b/specs/lazy-adr/adr-012-remote-signer.md @@ -7,7 +7,7 @@ ## Context -Rollkit with single or multiple signers requires a fast, secure, and flexible digital signing solution. Currently, nodes perform local signing using keys stored on disk. However, this approach distributes private keys across many nodes, increasing the risk of compromise. By centralizing the signing process behind a remote service—ideally backed by an HSM (Hardware Security Module)—we can both secure our keys and achieve high availability. This remote signing service will also allow clients written in different languages to use a unified API through gRPC. +Rollkit with single or multiple signers requires a fast, secure, and flexible digital signing solution. Currently, nodes perform local signing using keys stored on disk, in plain. However, this approach distributes private keys across many nodes, increasing the risk of compromise. By centralizing the signing process behind a remote service—ideally backed by an HSM (Hardware Security Module)—we can both secure our keys and achieve high availability. This remote signing service will also allow clients written in different languages to use a unified API through gRPC. ## Alternative Approaches @@ -28,8 +28,8 @@ We will implement a remote signing service that uses gRPC to communicate between ```mermaid graph TD - A[Client Node] -->|gRPC Call: Sign()/GetPublic()| B[HSM / Remote Signing Server] - B -->|Uses| C[Secure Key Storage (HSM)] + A[Client Node] -->|"gRPC Call: Sign()/GetPublic()"| B[HSM / Remote Signing Server] + B -->|Uses| C["Secure Key Storage (HSM)"] B -->|Returns Signature/Public Key| A ``` @@ -45,23 +45,7 @@ type Signer interface { ## Detailed Design -### User Requirements - -- Nodes require a fast and secure way to sign messages. -- The signing service must be accessible from multiple programming languages. -- Private keys must be centrally managed and secured. - -### Affected Systems - -- Node signing functionality. -- Key management system (e.g., HSM or secure file storage). -- gRPC-based communication layer. - -### Data Structures and APIs - -- Data Structures: The Signer interface remains unchanged. The implementation details for private/public key handling may vary. -- APIs: -The gRPC service is defined with the following protobuf: +### GRPC API ```proto syntax = "proto3"; @@ -94,40 +78,8 @@ service SignerService { rpc GetPublic(GetPublicRequest) returns (GetPublicResponse); } ``` +Signing operations will typically require very high throughput and minimal latency. Nodes frequently request digital signatures, expecting quick responses. Public key retrievals, while less frequent than signatures, still occur regularly for validation purposes. -### Efficiency Considerations - -- Time: gRPC provides low-latency communication suitable for high-frequency signing operations. -- Space: Efficient binary serialization minimizes payload sizes. - -### Expected Access Patterns - -- High-throughput, low-latency signing requests. -- Frequent public key retrievals for validation. - -### Logging, Monitoring, and Observability - -- Integration with centralized logging systems. -- Metrics collection on signing latency and error rates. -- Alerts for network issues between nodes and the signing service. - -### Security Considerations - -- Centralized key management minimizes the risk of key exposure. -- Use of gRPC ensures secure communication channels (with TLS in production). -- Role-based access and auditing for signing operations. - -### Testing Strategy - -- Unit tests for both local and remote implementations. -- Integration tests to validate end-to-end gRPC communication. -- Performance benchmarks to ensure signing meets throughput requirements. - -### Deployment Considerations - -- Rolling deployment of the signing service with failover strategies. -- Monitoring and logging setups to capture operational metrics. -- Potential need for a breaking release if nodes rely on the remote signing service without fallback. ## Status From 3eb894950aa4a6ad9935ccf8902f31f90085032b Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Fri, 14 Mar 2025 14:12:10 +0100 Subject: [PATCH 03/29] server --- pkg/remote_signer/grpc/server.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/remote_signer/grpc/server.go b/pkg/remote_signer/grpc/server.go index 05ad5e546b..fd0bae1bcd 100644 --- a/pkg/remote_signer/grpc/server.go +++ b/pkg/remote_signer/grpc/server.go @@ -3,21 +3,22 @@ package grpc import ( "context" + "github.com/rollkit/rollkit/pkg/remote_signer" v1 "github.com/rollkit/rollkit/pkg/remote_signer/v1" ) // RemoteSigner implements the SignerService generated interface from the .proto type RemoteSignerServer struct { - signer v1.SignerServiceServer + signer remote_signer.Signer v1.UnimplementedSignerServiceServer // Embedded for forward compatibility } -func NewRemoteSignerServer(s v1.SignerServiceServer) *RemoteSignerServer { +func NewRemoteSignerServer(s remote_signer.Signer) *RemoteSignerServer { return &RemoteSignerServer{signer: s} } func (r *RemoteSignerServer) Sign(ctx context.Context, req *v1.SignRequest) (*v1.SignResponse, error) { - sig, err := r.signer.Sign(ctx, req) + sig, err := r.signer.Sign(req.GetMessage()) if err != nil { return nil, err } From 04c4281fb4afaa0f716a433c13666da4a9e7f997 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Thu, 20 Mar 2025 14:49:27 +0100 Subject: [PATCH 04/29] add more --- block/manager.go | 9 +-- block/manager_test.go | 8 ++- cmd/rollkit/commands/run_node.go | 55 +++++++++-------- config/config.go | 24 ++++++++ config/defaults.go | 4 ++ node/full.go | 10 ++-- node/node.go | 6 +- pkg/remote_signer/file/README.md | 3 - pkg/remote_signer/file/doc.go | 34 +++++++++++ pkg/remote_signer/file/example_test.go | 1 + pkg/remote_signer/file/local.go | 79 +++++++++++++++++++------ pkg/remote_signer/grpc/doc.go | 6 ++ pkg/remote_signer/grpc/server.go | 38 ------------ pkg/remote_signer/noop/doc.go | 6 ++ pkg/remote_signer/noop/signer.go | 37 ++++++++++++ pkg/remote_signer/noop/signer_test.go | 82 ++++++++++++++++++++++++++ pkg/remote_signer/signer.go | 6 +- types/utils.go | 13 +++- 18 files changed, 320 insertions(+), 101 deletions(-) create mode 100644 pkg/remote_signer/file/doc.go create mode 100644 pkg/remote_signer/grpc/doc.go delete mode 100644 pkg/remote_signer/grpc/server.go create mode 100644 pkg/remote_signer/noop/doc.go create mode 100644 pkg/remote_signer/noop/signer.go create mode 100644 pkg/remote_signer/noop/signer_test.go diff --git a/block/manager.go b/block/manager.go index 60deb45403..6fddbbb485 100644 --- a/block/manager.go +++ b/block/manager.go @@ -14,7 +14,6 @@ import ( goheaderstore "github.com/celestiaorg/go-header/store" ds "github.com/ipfs/go-datastore" - "github.com/libp2p/go-libp2p/core/crypto" "github.com/rollkit/go-sequencing" @@ -22,9 +21,11 @@ import ( coreda "github.com/rollkit/rollkit/core/da" coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" + "github.com/rollkit/rollkit/pkg/remote_signer" "github.com/rollkit/rollkit/store" "github.com/rollkit/rollkit/third_party/log" "github.com/rollkit/rollkit/types" + pb "github.com/rollkit/rollkit/types/pb/rollkit/v1" ) @@ -109,7 +110,7 @@ type Manager struct { config config.Config genesis *RollkitGenesis - proposerKey crypto.PrivKey + proposerKey remote_signer.Signer // daHeight is the height of the latest processed DA block daHeight uint64 @@ -231,7 +232,7 @@ func getInitialState(ctx context.Context, genesis *RollkitGenesis, store store.S // NewManager creates new block Manager. func NewManager( ctx context.Context, - proposerKey crypto.PrivKey, + proposerKey remote_signer.Signer, config config.Config, genesis *RollkitGenesis, store store.Store, @@ -405,7 +406,7 @@ func (m *Manager) SetDALC(dalc coreda.Client) { } // isProposer returns whether or not the manager is a proposer -func isProposer(_ crypto.PrivKey, _ types.State) (bool, error) { +func isProposer(_ remote_signer.Signer, _ types.State) (bool, error) { return true, nil } diff --git a/block/manager_test.go b/block/manager_test.go index 923e1fc35b..d01508515b 100644 --- a/block/manager_test.go +++ b/block/manager_test.go @@ -22,6 +22,8 @@ import ( coresequencer "github.com/rollkit/rollkit/core/sequencer" "github.com/rollkit/rollkit/da" damocks "github.com/rollkit/rollkit/da/mocks" + "github.com/rollkit/rollkit/pkg/remote_signer" + noopsigner "github.com/rollkit/rollkit/pkg/remote_signer/noop" "github.com/rollkit/rollkit/store" "github.com/rollkit/rollkit/test/mocks" "github.com/rollkit/rollkit/types" @@ -362,7 +364,7 @@ func Test_isProposer(t *testing.T) { type args struct { state types.State - signerPrivKey crypto.PrivKey + signerPrivKey remote_signer.Signer } tests := []struct { name string @@ -376,9 +378,11 @@ func Test_isProposer(t *testing.T) { genesisData, privKey := types.GetGenesisWithPrivkey("Test_isProposer") s, err := types.NewFromGenesisDoc(genesisData) require.NoError(err) + signer, err := noopsigner.NewNoopSigner() + require.NoError(err) return args{ s, - privKey, + signer, } }(), isProposer: true, diff --git a/cmd/rollkit/commands/run_node.go b/cmd/rollkit/commands/run_node.go index 3598ac2e8a..c425586f59 100644 --- a/cmd/rollkit/commands/run_node.go +++ b/cmd/rollkit/commands/run_node.go @@ -16,7 +16,6 @@ import ( "cosmossdk.io/log" cometprivval "github.com/cometbft/cometbft/privval" comettypes "github.com/cometbft/cometbft/types" - "github.com/libp2p/go-libp2p/core/crypto" "github.com/rs/zerolog" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -31,6 +30,8 @@ import ( "github.com/rollkit/rollkit/da" "github.com/rollkit/rollkit/node" rollos "github.com/rollkit/rollkit/pkg/os" + "github.com/rollkit/rollkit/pkg/remote_signer" + "github.com/rollkit/rollkit/pkg/remote_signer/file" testExecutor "github.com/rollkit/rollkit/test/executors/kv" ) @@ -67,15 +68,15 @@ func NewRunNodeCmd() *cobra.Command { return err } - // TODO: this should be moved elsewhere - privValidatorKeyFile := filepath.Join(nodeConfig.RootDir, nodeConfig.ConfigDir, "priv_validator_key.json") - privValidatorStateFile := filepath.Join(nodeConfig.RootDir, nodeConfig.DBPath, "priv_validator_state.json") - pval := cometprivval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile) + // // TODO: this should be moved elsewhere + // privValidatorKeyFile := filepath.Join(nodeConfig.RootDir, nodeConfig.ConfigDir, "priv_validator_key.json") + // privValidatorStateFile := filepath.Join(nodeConfig.RootDir, nodeConfig.DBPath, "priv_validator_state.json") + // pval := cometprivval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile) - signingKey, err := crypto.UnmarshalEd25519PrivateKey(pval.Key.PrivKey.Bytes()) - if err != nil { - return err - } + // signingKey, err := crypto.UnmarshalEd25519PrivateKey(pval.Key.PrivKey.Bytes()) + // if err != nil { + // return err + // } // initialize the metrics metrics := node.DefaultMetricsProvider(rollconf.DefaultInstrumentationConfig()) @@ -84,22 +85,6 @@ func NewRunNodeCmd() *cobra.Command { if cmd.Flags().Lookup(rollconf.FlagSequencerRollupID).Changed { genDoc.ChainID = nodeConfig.Node.SequencerRollupID } - sequencerRollupID := genDoc.ChainID - // Try and launch a mock gRPC sequencer if there is no sequencer running. - // Only start mock Sequencer if the user did not provide --rollkit.sequencer_address - var seqSrv *grpc.Server = nil - if !cmd.Flags().Lookup(rollconf.FlagSequencerAddress).Changed { - seqSrv, err = tryStartMockSequencerServerGRPC(nodeConfig.Node.SequencerAddress, sequencerRollupID) - if err != nil && !errors.Is(err, errSequencerAlreadyRunning) { - return fmt.Errorf("failed to launch mock sequencing server: %w", err) - } - // nolint:errcheck,gosec - defer func() { - if seqSrv != nil { - seqSrv.Stop() - } - }() - } logger.Info("Executor address", "address", nodeConfig.Node.ExecutorAddress) @@ -107,6 +92,24 @@ func NewRunNodeCmd() *cobra.Command { ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() // Ensure context is cancelled when command exits + //create a new remote signer + var signer remote_signer.Signer + if nodeConfig.RemoteSigner.SignerType == "file" { + passphrase, err := cmd.Flags().GetString(rollconf.FlagRemoteSignerPassphrase) + if err != nil { + return err + } + + signer, err = file.NewFileSystemSigner(nodeConfig.RemoteSigner.SignerPath, []byte(passphrase)) + if err != nil { + return err + } + } else if nodeConfig.RemoteSigner.SignerType == "grpc" { + panic("grpc remote signer not implemented") + } else { + return fmt.Errorf("unknown remote signer type: %s", nodeConfig.RemoteSigner.SignerType) + } + kvExecutor := createDirectKVExecutor(ctx) dummySequencer := coresequencer.NewDummySequencer() @@ -120,7 +123,7 @@ func NewRunNodeCmd() *cobra.Command { kvExecutor, dummySequencer, dummyDALC, - signingKey, + signer, genDoc, metrics, logger, diff --git a/config/config.go b/config/config.go index f7c08493ec..50202a2cc1 100644 --- a/config/config.go +++ b/config/config.go @@ -100,6 +100,16 @@ const ( FlagLogFormat = "log.format" // FlagLogTrace is a flag for enabling stack traces in error logs FlagLogTrace = "log.trace" + + // Remote signer configuration flags + + // FlagRemoteSignerType is a flag for specifying the remote signer type + FlagRemoteSignerType = "remote_signer.type" + // FlagRemoteSignerPath is a flag for specifying the remote signer path + FlagRemoteSignerPath = "remote_signer.path" + + // FlagRemoteSignerPassphrase is a flag for specifying the remote signer passphrase + FlagRemoteSignerPassphrase = "remote_signer.passphrase" ) // DurationWrapper is a wrapper for time.Duration that implements encoding.TextMarshaler and encoding.TextUnmarshaler @@ -142,6 +152,9 @@ type Config struct { // Logging configuration Log LogConfig `mapstructure:"log" yaml:"log"` + + // Remote signer configuration + RemoteSigner RemoteSignerConfig `mapstructure:"remote_signer" yaml:"remote_signer"` } // DAConfig contains all Data Availability configuration parameters @@ -193,6 +206,12 @@ type P2PConfig struct { AllowedPeers string `mapstructure:"allowed_peers" yaml:"allowed_peers" comment:"Comma separated list of peer IDs to allow connections from"` } +// RemoteSignerConfig contains all remote signer configuration parameters +type RemoteSignerConfig struct { + SignerType string `mapstructure:"signer_type" yaml:"signer_type" comment:"Type of remote signer to use (file, grpc)"` + SignerPath string `mapstructure:"signer_path" yaml:"signer_path" comment:"Path to the signer file or address"` +} + // AddFlags adds Rollkit specific configuration options to cobra Command. // // This function is called in cosmos-sdk. @@ -245,6 +264,11 @@ func AddFlags(cmd *cobra.Command) { cmd.Flags().String(FlagLogLevel, "info", "log level (debug, info, warn, error)") cmd.Flags().String(FlagLogFormat, "", "log format (text, json)") cmd.Flags().Bool(FlagLogTrace, false, "enable stack traces in error logs") + + // Remote signer configuration flags + cmd.Flags().String(FlagRemoteSignerType, def.RemoteSigner.SignerType, "type of remote signer to use (file, grpc)") + cmd.Flags().String(FlagRemoteSignerPath, def.RemoteSigner.SignerPath, "path to the signer file or address") + cmd.Flags().String(FlagRemoteSignerPassphrase, "", "passphrase for the remote signer") } // LoadNodeConfig loads the node configuration in the following order of precedence: diff --git a/config/defaults.go b/config/defaults.go index 8a9d48d83a..81dd18ae4b 100644 --- a/config/defaults.go +++ b/config/defaults.go @@ -75,4 +75,8 @@ var DefaultNodeConfig = Config{ Format: "", Trace: false, }, + RemoteSigner: RemoteSignerConfig{ + SignerType: "file", + SignerPath: "", + }, } diff --git a/node/full.go b/node/full.go index e172c3b085..40faca9265 100644 --- a/node/full.go +++ b/node/full.go @@ -14,7 +14,6 @@ import ( cmtypes "github.com/cometbft/cometbft/types" ds "github.com/ipfs/go-datastore" ktds "github.com/ipfs/go-datastore/keytransform" - "github.com/libp2p/go-libp2p/core/crypto" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -24,6 +23,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" "github.com/rollkit/rollkit/p2p" + "github.com/rollkit/rollkit/pkg/remote_signer" "github.com/rollkit/rollkit/pkg/service" "github.com/rollkit/rollkit/store" ) @@ -67,7 +67,7 @@ type FullNode struct { func newFullNode( ctx context.Context, nodeConfig config.Config, - signingKey crypto.PrivKey, + signer remote_signer.Signer, genesis *cmtypes.GenesisDoc, exec coreexecutor.Executor, sequencer coresequencer.Sequencer, @@ -102,7 +102,7 @@ func newFullNode( blockManager, err := initBlockManager( ctx, - signingKey, + signer, exec, nodeConfig, genesis, @@ -184,7 +184,7 @@ func initDataSyncService( func initBlockManager( ctx context.Context, - signingKey crypto.PrivKey, + signer remote_signer.Signer, exec coreexecutor.Executor, nodeConfig config.Config, genesis *cmtypes.GenesisDoc, @@ -209,7 +209,7 @@ func initBlockManager( } blockManager, err := block.NewManager( ctx, - signingKey, + signer, nodeConfig, rollGen, store, diff --git a/node/node.go b/node/node.go index 412255422e..8c04f55b88 100644 --- a/node/node.go +++ b/node/node.go @@ -5,12 +5,12 @@ import ( "cosmossdk.io/log" cmtypes "github.com/cometbft/cometbft/types" - "github.com/libp2p/go-libp2p/core/crypto" "github.com/rollkit/rollkit/config" coreda "github.com/rollkit/rollkit/core/da" coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" + "github.com/rollkit/rollkit/pkg/remote_signer" "github.com/rollkit/rollkit/pkg/service" ) @@ -28,7 +28,7 @@ func NewNode( exec coreexecutor.Executor, sequencer coresequencer.Sequencer, dac coreda.Client, - signingKey crypto.PrivKey, + signer remote_signer.Signer, genesis *cmtypes.GenesisDoc, metricsProvider MetricsProvider, logger log.Logger, @@ -40,7 +40,7 @@ func NewNode( return newFullNode( ctx, conf, - signingKey, + signer, genesis, exec, sequencer, diff --git a/pkg/remote_signer/file/README.md b/pkg/remote_signer/file/README.md index f4db5f7f6c..9936bca874 100644 --- a/pkg/remote_signer/file/README.md +++ b/pkg/remote_signer/file/README.md @@ -49,9 +49,6 @@ For production use, consider the following enhancements: 1. **Stronger KDF**: Replace the simple key derivation function with Argon2 or PBKDF2 2. **Secure Passphrase Handling**: Implement secure methods for obtaining and handling passphrases -3. **Memory Protection**: Add memory protection to prevent keys from being swapped to disk -4. **Key Rotation**: Implement key rotation policies -5. **Hardware Security**: For high-security environments, consider using hardware security modules (HSMs) ## Implementation Details diff --git a/pkg/remote_signer/file/doc.go b/pkg/remote_signer/file/doc.go new file mode 100644 index 0000000000..6c367aa82a --- /dev/null +++ b/pkg/remote_signer/file/doc.go @@ -0,0 +1,34 @@ +/* +File Remote Signer implements the Signer interface using a file to store the keys. + +The keys are stored in a file in the local filesystem. + + passphrase := []byte("your-secure-passphrase") + keyPath := "/path/to/secure/keys.json" + + // Create or load a signer + signer, err := NewFileSystemSigner(keyPath, passphrase) + if err != nil { + panic(err) + } + + // Sign a message + message := []byte("Message to sign") + signature, err := signer.Sign(message) + if err != nil { + panic(err) + } + + // Get the public key + pubKey, err := signer.GetPublic() + if err != nil { + panic(err) + } + + // Verify the signature (typically done by another party) + valid, err := pubKey.Verify(message, signature) + if err != nil { + panic(err) + } +*/ +package file diff --git a/pkg/remote_signer/file/example_test.go b/pkg/remote_signer/file/example_test.go index 5dab037221..60bfbfeea5 100644 --- a/pkg/remote_signer/file/example_test.go +++ b/pkg/remote_signer/file/example_test.go @@ -40,6 +40,7 @@ func TestFileSystemSigner(t *testing.T) { require.NoError(t, err) assert.True(t, valid) + passphrase = []byte("test-passphrase-123") // Create a new signer instance (this will load the existing keys) signer2, err := NewFileSystemSigner(keyPath, passphrase) require.NoError(t, err) diff --git a/pkg/remote_signer/file/local.go b/pkg/remote_signer/file/local.go index 48330ab78c..d0cf3d1745 100644 --- a/pkg/remote_signer/file/local.go +++ b/pkg/remote_signer/file/local.go @@ -12,6 +12,8 @@ import ( "sync" "github.com/libp2p/go-libp2p/core/crypto" + "github.com/rollkit/rollkit/pkg/remote_signer" + "golang.org/x/crypto/argon2" ) // FileSystemSigner implements a signer that securely stores keys on disk @@ -28,11 +30,14 @@ type keyData struct { PrivKeyEncrypted []byte `json:"priv_key_encrypted"` Nonce []byte `json:"nonce"` PubKeyBytes []byte `json:"pub_key"` + Salt []byte `json:"salt,omitempty"` } // NewFileSystemSigner creates a new signer that stores keys securely on disk. // If the keys don't exist at the specified paths, it generates new ones. -func NewFileSystemSigner(keyPath string, passphrase []byte) (*FileSystemSigner, error) { +func NewFileSystemSigner(keyPath string, passphrase []byte) (remote_signer.Signer, error) { + defer zeroBytes(passphrase) // Wipe passphrase from memory after use + // Create directory if it doesn't exist dir := filepath.Dir(keyPath) if err := os.MkdirAll(dir, 0700); err != nil { @@ -60,6 +65,8 @@ func NewFileSystemSigner(keyPath string, passphrase []byte) (*FileSystemSigner, // generateAndSaveKeys creates a new key pair and saves it to disk func generateAndSaveKeys(keyPath string, passphrase []byte) (*FileSystemSigner, error) { + defer zeroBytes(passphrase) + // Generate new Ed25519 key pair privKey, pubKey, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) if err != nil { @@ -89,6 +96,12 @@ func (s *FileSystemSigner) saveKeys(passphrase []byte) error { return fmt.Errorf("keys not initialized") } + // Create or reuse a random salt for Argon2 + salt := make([]byte, 16) + if _, err := rand.Read(salt); err != nil { + return fmt.Errorf("failed to generate salt: %w", err) + } + // Get raw private key bytes privKeyBytes, err := s.privateKey.Raw() if err != nil { @@ -101,10 +114,14 @@ func (s *FileSystemSigner) saveKeys(passphrase []byte) error { return fmt.Errorf("failed to get raw public key: %w", err) } - // Create AES cipher from passphrase - // Use a key derivation function in production code - key := deriveKey(passphrase, 32) - block, err := aes.NewCipher(key) + // Derive a key with Argon2 + derivedKey := deriveKeyArgon2(passphrase, salt, 32) + + // Zero out passphrase from memory once we have our derived key + zeroBytes(passphrase) + + // Create AES cipher + block, err := aes.NewCipher(derivedKey) if err != nil { return fmt.Errorf("failed to create cipher: %w", err) } @@ -129,6 +146,7 @@ func (s *FileSystemSigner) saveKeys(passphrase []byte) error { PrivKeyEncrypted: encryptedPrivKey, Nonce: nonce, PubKeyBytes: pubKeyBytes, + Salt: salt, } // Marshal to JSON @@ -142,6 +160,10 @@ func (s *FileSystemSigner) saveKeys(passphrase []byte) error { return fmt.Errorf("failed to write key file: %w", err) } + // Zero out derivedKey bytes for security + zeroBytes(derivedKey) + zeroBytes(privKeyBytes) + return nil } @@ -149,6 +171,7 @@ func (s *FileSystemSigner) saveKeys(passphrase []byte) error { func (s *FileSystemSigner) loadKeys(passphrase []byte) error { s.mu.Lock() defer s.mu.Unlock() + defer zeroBytes(passphrase) // Wipe passphrase from memory after use // Read the key file jsonData, err := os.ReadFile(s.keyFile) @@ -162,14 +185,20 @@ func (s *FileSystemSigner) loadKeys(passphrase []byte) error { return fmt.Errorf("failed to unmarshal key data: %w", err) } - // Create AES cipher from passphrase - key := deriveKey(passphrase, 32) - block, err := aes.NewCipher(key) + // If there's no salt in the file, fallback to older naive deriveKey (for backward-compatibility) + var derivedKey []byte + if len(data.Salt) == 0 { + // fallback to naive approach + derivedKey = fallbackDeriveKey(passphrase, 32) + } else { + derivedKey = deriveKeyArgon2(passphrase, data.Salt, 32) + } + + block, err := aes.NewCipher(derivedKey) if err != nil { return fmt.Errorf("failed to create cipher: %w", err) } - // Create GCM mode gcm, err := cipher.NewGCM(block) if err != nil { return fmt.Errorf("failed to create GCM: %w", err) @@ -197,6 +226,10 @@ func (s *FileSystemSigner) loadKeys(passphrase []byte) error { s.privateKey = privKey s.publicKey = pubKey + // Zero out sensitive data + zeroBytes(derivedKey) + zeroBytes(privKeyBytes) + return nil } @@ -224,22 +257,34 @@ func (s *FileSystemSigner) GetPublic() (crypto.PubKey, error) { return s.publicKey, nil } -// deriveKey is a simple key derivation function -// In production, use a proper KDF like Argon2 or PBKDF2 -func deriveKey(passphrase []byte, keyLen int) []byte { - // This is a simplified version for demonstration - // In production, use a proper KDF with salt and iterations +// deriveKeyArgon2 uses Argon2id for key derivation +func deriveKeyArgon2(passphrase, salt []byte, keyLen uint32) []byte { + // Using some default parameters: + // Time (iterations) = 3 + // Memory = 32MB + // Threads = 4 + // You can tune these parameters for your security/performance needs. + return argon2.IDKey(passphrase, salt, 3, 32*1024, 4, keyLen) +} + +// fallbackDeriveKey is the old naive approach for backwards compatibility. +// Will be used if a key file has no salt field. +func fallbackDeriveKey(passphrase []byte, keyLen int) []byte { if len(passphrase) >= keyLen { return passphrase[:keyLen] } key := make([]byte, keyLen) copy(key, passphrase) - - // Fill the rest with a deterministic pattern based on the passphrase for i := len(passphrase); i < keyLen; i++ { key[i] = passphrase[i%len(passphrase)] ^ byte(i) } - return key } + +// zeroBytes overwrites a byte slice with zeros +func zeroBytes(b []byte) { + for i := range b { + b[i] = 0 + } +} diff --git a/pkg/remote_signer/grpc/doc.go b/pkg/remote_signer/grpc/doc.go new file mode 100644 index 0000000000..6fb2df45f9 --- /dev/null +++ b/pkg/remote_signer/grpc/doc.go @@ -0,0 +1,6 @@ +/* +GRPC Remote Signer implements the SignerService generated interface from the .proto file. + +The implementation run on the node is the client, the server is remote and must be implemented by the user. +*/ +package grpc diff --git a/pkg/remote_signer/grpc/server.go b/pkg/remote_signer/grpc/server.go deleted file mode 100644 index fd0bae1bcd..0000000000 --- a/pkg/remote_signer/grpc/server.go +++ /dev/null @@ -1,38 +0,0 @@ -package grpc - -import ( - "context" - - "github.com/rollkit/rollkit/pkg/remote_signer" - v1 "github.com/rollkit/rollkit/pkg/remote_signer/v1" -) - -// RemoteSigner implements the SignerService generated interface from the .proto -type RemoteSignerServer struct { - signer remote_signer.Signer - v1.UnimplementedSignerServiceServer // Embedded for forward compatibility -} - -func NewRemoteSignerServer(s remote_signer.Signer) *RemoteSignerServer { - return &RemoteSignerServer{signer: s} -} - -func (r *RemoteSignerServer) Sign(ctx context.Context, req *v1.SignRequest) (*v1.SignResponse, error) { - sig, err := r.signer.Sign(req.GetMessage()) - if err != nil { - return nil, err - } - return &v1.SignResponse{ - Signature: sig, - }, nil -} - -func (r *RemoteSignerServer) GetPublic(ctx context.Context, _ v1.GetPublicRequest) (*v1.GetPublicResponse, error) { - pub, err := r.signer.GetPublic() - if err != nil { - return nil, err - } - return &v1.GetPublicResponse{ - PublicKey: pub, - }, nil -} diff --git a/pkg/remote_signer/noop/doc.go b/pkg/remote_signer/noop/doc.go new file mode 100644 index 0000000000..afe1ec7fb2 --- /dev/null +++ b/pkg/remote_signer/noop/doc.go @@ -0,0 +1,6 @@ +/* +Noop remote signer implements the Signer interface using a no-op signer. + +This is useful for testing and development purposes. +*/ +package noop diff --git a/pkg/remote_signer/noop/signer.go b/pkg/remote_signer/noop/signer.go new file mode 100644 index 0000000000..1ffe8446a3 --- /dev/null +++ b/pkg/remote_signer/noop/signer.go @@ -0,0 +1,37 @@ +package noop + +import ( + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/rollkit/rollkit/pkg/remote_signer" +) + +// NoopSigner implements the remote_signer.Signer interface. +// It generates a new Ed25519 key pair for each instance. +type NoopSigner struct { + privKey crypto.PrivKey + pubKey crypto.PubKey +} + +// NewNoopSigner creates a new signer with a fresh Ed25519 key pair. +func NewNoopSigner() (remote_signer.Signer, error) { + // Generate new Ed25519 key pair + priv, pub, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + if err != nil { + return nil, err + } + + return &NoopSigner{ + privKey: priv, + pubKey: pub, + }, nil +} + +// Sign implements the Signer interface by signing the message with the Ed25519 private key. +func (n *NoopSigner) Sign(message []byte) ([]byte, error) { + return n.privKey.Sign(message) +} + +// GetPublic implements the Signer interface by returning the Ed25519 public key. +func (n *NoopSigner) GetPublic() (crypto.PubKey, error) { + return n.pubKey, nil +} diff --git a/pkg/remote_signer/noop/signer_test.go b/pkg/remote_signer/noop/signer_test.go new file mode 100644 index 0000000000..c03d3bd0fc --- /dev/null +++ b/pkg/remote_signer/noop/signer_test.go @@ -0,0 +1,82 @@ +package noop + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNoopSigner(t *testing.T) { + t.Run("create new signer", func(t *testing.T) { + signer, err := NewNoopSigner() + require.NoError(t, err) + require.NotNil(t, signer) + }) + + t.Run("get public key", func(t *testing.T) { + signer, err := NewNoopSigner() + require.NoError(t, err) + + pubKey, err := signer.GetPublic() + require.NoError(t, err) + require.NotNil(t, pubKey) + }) + + t.Run("sign and verify", func(t *testing.T) { + signer, err := NewNoopSigner() + require.NoError(t, err) + + message := []byte("test message") + signature, err := signer.Sign(message) + require.NoError(t, err) + require.NotNil(t, signature) + + // Verify signature using the public key + pubKey, err := signer.GetPublic() + require.NoError(t, err) + + valid, err := pubKey.Verify(message, signature) + require.NoError(t, err) + require.True(t, valid) + }) + + t.Run("different signers have different keys", func(t *testing.T) { + signer1, err := NewNoopSigner() + require.NoError(t, err) + + signer2, err := NewNoopSigner() + require.NoError(t, err) + + pub1, err := signer1.GetPublic() + require.NoError(t, err) + + pub2, err := signer2.GetPublic() + require.NoError(t, err) + + pub1Bytes, err := pub1.Raw() + require.NoError(t, err) + + pub2Bytes, err := pub2.Raw() + require.NoError(t, err) + + require.NotEqual(t, pub1Bytes, pub2Bytes) + }) + + t.Run("verify wrong message fails", func(t *testing.T) { + signer, err := NewNoopSigner() + require.NoError(t, err) + + message := []byte("test message") + wrongMessage := []byte("wrong message") + + signature, err := signer.Sign(message) + require.NoError(t, err) + + pubKey, err := signer.GetPublic() + require.NoError(t, err) + + valid, err := pubKey.Verify(wrongMessage, signature) + require.NoError(t, err) + require.False(t, valid) + }) +} diff --git a/pkg/remote_signer/signer.go b/pkg/remote_signer/signer.go index 023a5da630..615ecf7418 100644 --- a/pkg/remote_signer/signer.go +++ b/pkg/remote_signer/signer.go @@ -1,9 +1,13 @@ package remote_signer +import ( + "github.com/libp2p/go-libp2p/core/crypto" +) + type Signer interface { // Sign takes a message as bytes and returns its signature. Sign(message []byte) ([]byte, error) // GetPublic returns the public key paired with this private key. - GetPublic() ([]byte, error) + GetPublic() (crypto.PubKey, error) } diff --git a/types/utils.go b/types/utils.go index 9ebb8f01b8..4d286947e9 100644 --- a/types/utils.go +++ b/types/utils.go @@ -12,6 +12,7 @@ import ( cmbytes "github.com/cometbft/cometbft/libs/bytes" cmtypes "github.com/cometbft/cometbft/types" "github.com/libp2p/go-libp2p/core/crypto" + noopsigner "github.com/rollkit/rollkit/pkg/remote_signer/noop" ) // DefaultSigningKeyType is the key type used by the sequencer signing key @@ -288,8 +289,16 @@ func GetValidatorSetFromGenesis(g *cmtypes.GenesisDoc) cmtypes.ValidatorSet { // GetGenesisWithPrivkey returns a genesis doc with a single validator and a signing key func GetGenesisWithPrivkey(chainID string) (*cmtypes.GenesisDoc, crypto.PrivKey) { - genesisValidatorKey := ed25519.GenPrivKey() - pubKey := genesisValidatorKey.PubKey() + + signer, err := noopsigner.NewNoopSigner() + if err != nil { + panic(err) + } + + pubKey, err := signer.GetPublic() + if err != nil { + panic(err) + } genesisValidators := []cmtypes.GenesisValidator{{ Address: pubKey.Address(), From 01990f62c254611a8c70bbcfd3aeedaf8439c043 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Tue, 25 Mar 2025 15:03:35 +0100 Subject: [PATCH 05/29] remove comet --- go.mod | 1 - go.sum | 6 ------ types/hashing.go | 16 ++++++++++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index cde749d001..c1b023bc35 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,6 @@ require ( cosmossdk.io/log v1.5.0 github.com/celestiaorg/go-header v0.6.4 github.com/celestiaorg/utils v0.1.0 - github.com/cometbft/cometbft v0.38.15 github.com/cosmos/gogoproto v1.7.0 github.com/go-kit/kit v0.13.0 github.com/goccy/go-yaml v1.16.0 diff --git a/go.sum b/go.sum index 1eab06ca35..fca7972878 100644 --- a/go.sum +++ b/go.sum @@ -133,8 +133,6 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.15 h1:5veFd8k1uXM27PBg9sMO3hAfRJ3vbh4OmmLf6cVrqXg= -github.com/cometbft/cometbft v0.38.15/go.mod h1:+wh6ap6xctVG+JOHwbl8pPKZ0GeqdPYqISu7F4b43cQ= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= @@ -820,8 +818,6 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= @@ -951,8 +947,6 @@ github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgY github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= -github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= diff --git a/types/hashing.go b/types/hashing.go index d6295db62f..491019bc10 100644 --- a/types/hashing.go +++ b/types/hashing.go @@ -2,8 +2,11 @@ package types import ( "crypto/sha256" + "hash" +) - "github.com/cometbft/cometbft/crypto/merkle" +var ( + leafPrefix = []byte{0} ) // Hash returns hash of the header @@ -21,7 +24,12 @@ func (d *Data) Hash() Hash { // Ignoring the marshal error for now to satisfy the go-header interface // Later on the usage of Hash should be replaced with DA commitment dBytes, _ := d.MarshalBinary() - return merkle.HashFromByteSlices([][]byte{ - dBytes, - }) + return leafHashOpt(sha256.New(), dBytes) +} + +func leafHashOpt(s hash.Hash, leaf []byte) []byte { + s.Reset() + s.Write(leafPrefix) + s.Write(leaf) + return s.Sum(nil) } From 9f300d60573ecf6c618686daf1cc7a6d75c8cd99 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Tue, 25 Mar 2025 15:04:36 +0100 Subject: [PATCH 06/29] tidy-all --- sequencers/single/go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sequencers/single/go.sum b/sequencers/single/go.sum index 965b848974..5566be7ea4 100644 --- a/sequencers/single/go.sum +++ b/sequencers/single/go.sum @@ -48,8 +48,8 @@ github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= From 4e83815bc975087e30da044caa0262e22eb5c3f3 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Tue, 25 Mar 2025 15:19:15 +0100 Subject: [PATCH 07/29] build --- block/manager.go | 1 - block/manager_test.go | 19 +++++++++++-------- cmd/rollkit/commands/run_node.go | 1 - node/full_node_integration_test.go | 17 ++++++++++++----- node/helpers_test.go | 7 +++++-- node/node_integration_test.go | 7 +++++-- node/node_test.go | 7 +++++-- pkg/remote_signer/file/local.go | 3 ++- pkg/remote_signer/noop/signer.go | 12 ++++-------- pkg/remote_signer/noop/signer_test.go | 25 +++++++++++++++++++------ pkg/remote_signer/signer.go | 1 + 11 files changed, 64 insertions(+), 36 deletions(-) diff --git a/block/manager.go b/block/manager.go index 97f413139c..ad77d04ad8 100644 --- a/block/manager.go +++ b/block/manager.go @@ -27,7 +27,6 @@ import ( "github.com/rollkit/rollkit/pkg/remote_signer" "github.com/rollkit/rollkit/pkg/store" "github.com/rollkit/rollkit/types" - pb "github.com/rollkit/rollkit/types/pb/rollkit/v1" ) diff --git a/block/manager_test.go b/block/manager_test.go index 374ccd2849..5a0b824990 100644 --- a/block/manager_test.go +++ b/block/manager_test.go @@ -175,21 +175,24 @@ func TestSignVerifySignature(t *testing.T) { require := require.New(t) m := getManager(t, coreda.NewDummyDA(100_000, 0, 0), -1, -1) payload := []byte("test") - privKey, pubKey, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + privKey, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + require.NoError(err) + signer, err := noopsigner.NewNoopSigner(privKey) require.NoError(err) cases := []struct { - name string - privKey crypto.PrivKey - pubKey crypto.PubKey + name string + signer remote_signer.Signer }{ - {"ed25519", privKey, pubKey}, + {"ed25519", signer}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - m.proposerKey = c.privKey + m.proposerKey = c.signer signature, err := m.proposerKey.Sign(payload) require.NoError(err) - ok, err := c.pubKey.Verify(payload, signature) + pubKey, err := c.signer.GetPublic() + require.NoError(err) + ok, err := pubKey.Verify(payload, signature) require.NoError(err) require.True(ok) }) @@ -374,7 +377,7 @@ func Test_isProposer(t *testing.T) { genesisData, privKey, _ := types.GetGenesisWithPrivkey("Test_isProposer") s, err := types.NewFromGenesisDoc(genesisData) require.NoError(err) - signer, err := noopsigner.NewNoopSigner() + signer, err := noopsigner.NewNoopSigner(privKey) require.NoError(err) return args{ s, diff --git a/cmd/rollkit/commands/run_node.go b/cmd/rollkit/commands/run_node.go index 9477d38398..e9e928f9a5 100644 --- a/cmd/rollkit/commands/run_node.go +++ b/cmd/rollkit/commands/run_node.go @@ -14,7 +14,6 @@ import ( "time" "cosmossdk.io/log" - "github.com/rs/zerolog" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/node/full_node_integration_test.go b/node/full_node_integration_test.go index 27a23e5fac..55e346203d 100644 --- a/node/full_node_integration_test.go +++ b/node/full_node_integration_test.go @@ -17,6 +17,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" + remote_signer "github.com/rollkit/rollkit/pkg/remote_signer/noop" "github.com/rollkit/rollkit/types" ) @@ -62,13 +63,15 @@ func (s *FullNodeTestSuite) SetupTest() { // Create genesis with current time genesis, genesisValidatorKey, _ := types.GetGenesisWithPrivkey("test-chain") + remoteSigner, err := remote_signer.NewNoopSigner(genesisValidatorKey) + require.NoError(s.T(), err) dummyExec := coreexecutor.NewDummyExecutor() dummySequencer := coresequencer.NewDummySequencer() dummyDA := coreda.NewDummyDA(100_000, 0, 0) dummyClient := coreda.NewDummyClient(dummyDA, []byte(MockDANamespace)) - err := InitFiles(config.RootDir) + err = InitFiles(config.RootDir) require.NoError(s.T(), err) node, err := NewNode( @@ -77,7 +80,7 @@ func (s *FullNodeTestSuite) SetupTest() { dummyExec, dummySequencer, dummyClient, - genesisValidatorKey, + remoteSigner, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(s.T()), @@ -314,13 +317,15 @@ func (s *FullNodeTestSuite) TestMaxPending() { config.Node.MaxPendingBlocks = 2 genesis, genesisValidatorKey, _ := types.GetGenesisWithPrivkey("test-chain") + remoteSigner, err := remote_signer.NewNoopSigner(genesisValidatorKey) + require.NoError(err) dummyExec := coreexecutor.NewDummyExecutor() dummySequencer := coresequencer.NewDummySequencer() dummyDA := coreda.NewDummyDA(100_000, 0, 0) dummyClient := coreda.NewDummyClient(dummyDA, []byte(MockDANamespace)) - err := InitFiles(config.RootDir) + err = InitFiles(config.RootDir) require.NoError(err) node, err := NewNode( @@ -329,7 +334,7 @@ func (s *FullNodeTestSuite) TestMaxPending() { dummyExec, dummySequencer, dummyClient, - genesisValidatorKey, + remoteSigner, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(s.T()), @@ -398,6 +403,8 @@ func (s *FullNodeTestSuite) TestStateRecovery() { // Create a NEW node instance instead of reusing the old one config := getTestConfig(s.T(), 1) genesis, genesisValidatorKey, _ := types.GetGenesisWithPrivkey("test-chain") + remoteSigner, err := remote_signer.NewNoopSigner(genesisValidatorKey) + require.NoError(err) dummyExec := coreexecutor.NewDummyExecutor() dummySequencer := coresequencer.NewDummySequencer() @@ -410,7 +417,7 @@ func (s *FullNodeTestSuite) TestStateRecovery() { dummyExec, dummySequencer, dummyClient, - genesisValidatorKey, + remoteSigner, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(s.T()), diff --git a/node/helpers_test.go b/node/helpers_test.go index f8022a64ba..cbf28828df 100644 --- a/node/helpers_test.go +++ b/node/helpers_test.go @@ -13,6 +13,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" + remote_signer "github.com/rollkit/rollkit/pkg/remote_signer/noop" "github.com/rollkit/rollkit/types" ) @@ -44,13 +45,15 @@ func setupTestNodeWithCleanup(t *testing.T) (*FullNode, func()) { // Generate genesis and keys genesis, genesisValidatorKey, _ := types.GetGenesisWithPrivkey("test-chain") + remoteSigner, err := remote_signer.NewNoopSigner(genesisValidatorKey) + require.NoError(t, err) dummyExec := coreexecutor.NewDummyExecutor() dummySequencer := coresequencer.NewDummySequencer() dummyDA := coreda.NewDummyDA(100_000, 0, 0) dummyClient := coreda.NewDummyClient(dummyDA, []byte(MockDANamespace)) - err := InitFiles(config.RootDir) + err = InitFiles(config.RootDir) require.NoError(t, err) node, err := NewNode( @@ -59,7 +62,7 @@ func setupTestNodeWithCleanup(t *testing.T) (*FullNode, func()) { dummyExec, dummySequencer, dummyClient, - genesisValidatorKey, + remoteSigner, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(t), diff --git a/node/node_integration_test.go b/node/node_integration_test.go index 010616deaa..c477ed7ad8 100644 --- a/node/node_integration_test.go +++ b/node/node_integration_test.go @@ -18,6 +18,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" + remote_signer "github.com/rollkit/rollkit/pkg/remote_signer/noop" "github.com/rollkit/rollkit/types" ) @@ -44,6 +45,8 @@ func (s *NodeIntegrationTestSuite) SetupTest() { config.Node.MaxPendingBlocks = 100 // Allow more pending blocks genesis, genesisValidatorKey, _ := types.GetGenesisWithPrivkey("test-chain") + remoteSigner, err := remote_signer.NewNoopSigner(genesisValidatorKey) + require.NoError(s.T(), err) s.seqSrv = startMockSequencerServerGRPC(MockSequencerAddress) require.NotNil(s.T(), s.seqSrv) @@ -53,7 +56,7 @@ func (s *NodeIntegrationTestSuite) SetupTest() { dummyDA := coreda.NewDummyDA(100_000, 0, 0) dummyClient := coreda.NewDummyClient(dummyDA, []byte(MockDANamespace)) - err := InitFiles(config.RootDir) + err = InitFiles(config.RootDir) require.NoError(s.T(), err) node, err := NewNode( @@ -62,7 +65,7 @@ func (s *NodeIntegrationTestSuite) SetupTest() { dummyExec, dummySequencer, dummyClient, - genesisValidatorKey, + remoteSigner, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(s.T()), diff --git a/node/node_test.go b/node/node_test.go index 9a970bb0f5..3c330d66a6 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -20,6 +20,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" + remote_signer "github.com/rollkit/rollkit/pkg/remote_signer/noop" "github.com/rollkit/rollkit/types" ) @@ -179,13 +180,15 @@ func newTestNode(ctx context.Context, t *testing.T, nodeType NodeType, chainID s } genesis, genesisValidatorKey, _ := types.GetGenesisWithPrivkey(chainID) + remoteSigner, err := remote_signer.NewNoopSigner(genesisValidatorKey) + require.NoError(t, err) dummyExec := coreexecutor.NewDummyExecutor() dummySequencer := coresequencer.NewDummySequencer() dummyDA := coreda.NewDummyDA(100_000, 0, 0) dummyClient := coreda.NewDummyClient(dummyDA, []byte(MockDANamespace)) - err := InitFiles(config.RootDir) + err = InitFiles(config.RootDir) require.NoError(t, err) logger := log.NewTestLogger(t) @@ -196,7 +199,7 @@ func newTestNode(ctx context.Context, t *testing.T, nodeType NodeType, chainID s dummyExec, dummySequencer, dummyClient, - genesisValidatorKey, + remoteSigner, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), logger, diff --git a/pkg/remote_signer/file/local.go b/pkg/remote_signer/file/local.go index d0cf3d1745..e747ccb22a 100644 --- a/pkg/remote_signer/file/local.go +++ b/pkg/remote_signer/file/local.go @@ -12,8 +12,9 @@ import ( "sync" "github.com/libp2p/go-libp2p/core/crypto" - "github.com/rollkit/rollkit/pkg/remote_signer" "golang.org/x/crypto/argon2" + + "github.com/rollkit/rollkit/pkg/remote_signer" ) // FileSystemSigner implements a signer that securely stores keys on disk diff --git a/pkg/remote_signer/noop/signer.go b/pkg/remote_signer/noop/signer.go index 1ffe8446a3..2c12ecd4a9 100644 --- a/pkg/remote_signer/noop/signer.go +++ b/pkg/remote_signer/noop/signer.go @@ -2,6 +2,7 @@ package noop import ( "github.com/libp2p/go-libp2p/core/crypto" + "github.com/rollkit/rollkit/pkg/remote_signer" ) @@ -13,16 +14,11 @@ type NoopSigner struct { } // NewNoopSigner creates a new signer with a fresh Ed25519 key pair. -func NewNoopSigner() (remote_signer.Signer, error) { - // Generate new Ed25519 key pair - priv, pub, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) - if err != nil { - return nil, err - } +func NewNoopSigner(privKey crypto.PrivKey) (remote_signer.Signer, error) { return &NoopSigner{ - privKey: priv, - pubKey: pub, + privKey: privKey, + pubKey: privKey.GetPublic(), }, nil } diff --git a/pkg/remote_signer/noop/signer_test.go b/pkg/remote_signer/noop/signer_test.go index c03d3bd0fc..a3ec506ba5 100644 --- a/pkg/remote_signer/noop/signer_test.go +++ b/pkg/remote_signer/noop/signer_test.go @@ -3,18 +3,23 @@ package noop import ( "testing" + "github.com/libp2p/go-libp2p/core/crypto" "github.com/stretchr/testify/require" ) func TestNoopSigner(t *testing.T) { t.Run("create new signer", func(t *testing.T) { - signer, err := NewNoopSigner() + privKey, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + require.NoError(t, err) + signer, err := NewNoopSigner(privKey) require.NoError(t, err) require.NotNil(t, signer) }) t.Run("get public key", func(t *testing.T) { - signer, err := NewNoopSigner() + privKey, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + require.NoError(t, err) + signer, err := NewNoopSigner(privKey) require.NoError(t, err) pubKey, err := signer.GetPublic() @@ -23,7 +28,9 @@ func TestNoopSigner(t *testing.T) { }) t.Run("sign and verify", func(t *testing.T) { - signer, err := NewNoopSigner() + privKey, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + require.NoError(t, err) + signer, err := NewNoopSigner(privKey) require.NoError(t, err) message := []byte("test message") @@ -41,10 +48,14 @@ func TestNoopSigner(t *testing.T) { }) t.Run("different signers have different keys", func(t *testing.T) { - signer1, err := NewNoopSigner() + privKey1, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + require.NoError(t, err) + signer1, err := NewNoopSigner(privKey1) require.NoError(t, err) - signer2, err := NewNoopSigner() + privKey2, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + require.NoError(t, err) + signer2, err := NewNoopSigner(privKey2) require.NoError(t, err) pub1, err := signer1.GetPublic() @@ -63,7 +74,9 @@ func TestNoopSigner(t *testing.T) { }) t.Run("verify wrong message fails", func(t *testing.T) { - signer, err := NewNoopSigner() + privKey, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) + require.NoError(t, err) + signer, err := NewNoopSigner(privKey) require.NoError(t, err) message := []byte("test message") diff --git a/pkg/remote_signer/signer.go b/pkg/remote_signer/signer.go index 615ecf7418..72a9bb11d2 100644 --- a/pkg/remote_signer/signer.go +++ b/pkg/remote_signer/signer.go @@ -4,6 +4,7 @@ import ( "github.com/libp2p/go-libp2p/core/crypto" ) +// Signer is an interface for signing and verifying messages. type Signer interface { // Sign takes a message as bytes and returns its signature. Sign(message []byte) ([]byte, error) From c02e810df6524d055cc4d425dbb8851ef90eb3a6 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 26 Mar 2025 15:31:13 +0100 Subject: [PATCH 08/29] fix sequencer --- sequencers/single/go.mod | 4 +--- sequencers/single/go.sum | 4 ---- sequencers/single/queue.go | 5 +++-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/sequencers/single/go.mod b/sequencers/single/go.mod index 9fa8d8dc56..7cf5165efd 100644 --- a/sequencers/single/go.mod +++ b/sequencers/single/go.mod @@ -16,6 +16,7 @@ require ( github.com/rollkit/rollkit v0.0.0-00010101000000-000000000000 github.com/rollkit/rollkit/core v0.0.0-00010101000000-000000000000 github.com/rollkit/rollkit/da v0.0.0-00010101000000-000000000000 + google.golang.org/protobuf v1.36.5 ) require ( @@ -25,9 +26,7 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect - github.com/cosmos/gogoproto v1.7.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect @@ -42,5 +41,4 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/sys v0.30.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect ) diff --git a/sequencers/single/go.sum b/sequencers/single/go.sum index 5566be7ea4..2313cec212 100644 --- a/sequencers/single/go.sum +++ b/sequencers/single/go.sum @@ -16,8 +16,6 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= -github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -27,8 +25,6 @@ github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4F github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= diff --git a/sequencers/single/queue.go b/sequencers/single/queue.go index 0091b6f702..e4faac4491 100644 --- a/sequencers/single/queue.go +++ b/sequencers/single/queue.go @@ -9,6 +9,7 @@ import ( ktds "github.com/ipfs/go-datastore/keytransform" "github.com/ipfs/go-datastore/query" coresequencer "github.com/rollkit/rollkit/core/sequencer" + "google.golang.org/protobuf/proto" pb "github.com/rollkit/rollkit/types/pb/rollkit/v1" ) @@ -45,7 +46,7 @@ func (bq *BatchQueue) AddBatch(ctx context.Context, batch coresequencer.Batch) e Txs: batch.Transactions, } - encodedBatch, err := pbBatch.Marshal() + encodedBatch, err := proto.Marshal(pbBatch) if err != nil { return err } @@ -108,7 +109,7 @@ func (bq *BatchQueue) Load(ctx context.Context) error { // Load each batch for result := range results.Next() { pbBatch := &pb.Batch{} - err := pbBatch.Unmarshal(result.Value) + err := proto.Unmarshal(result.Value, pbBatch) if err != nil { fmt.Printf("Error decoding batch: %v\n", err) continue From 8729c1daf197e96e203ed14507db78f6b4afb096 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 26 Mar 2025 15:44:15 +0100 Subject: [PATCH 09/29] fix linting and rename to signer --- block/manager.go | 8 +- block/manager_test.go | 12 +- cmd/rollkit/commands/init.go | 34 ++ cmd/rollkit/commands/run_node.go | 71 +---- cmd/rollkit/commands/run_node_test.go | 94 ------ node/full.go | 6 +- node/full_node_integration_test.go | 2 +- node/helpers_test.go | 2 +- node/node.go | 4 +- node/node_integration_test.go | 2 +- node/node_test.go | 2 +- pkg/config/config.go | 1 + pkg/remote_signer/grpc/doc.go | 6 - pkg/{remote_signer => signer}/file/README.md | 0 pkg/{remote_signer => signer}/file/doc.go | 0 .../file/example_test.go | 0 pkg/{remote_signer => signer}/file/local.go | 4 +- pkg/{remote_signer => signer}/noop/doc.go | 0 pkg/{remote_signer => signer}/noop/signer.go | 4 +- .../noop/signer_test.go | 0 pkg/{remote_signer => signer}/signer.go | 2 +- pkg/{remote_signer => signer}/v1/signer.pb.go | 0 specs/lazy-adr/adr-017-node-pruning.md | 291 +++++++++--------- 23 files changed, 225 insertions(+), 320 deletions(-) delete mode 100644 pkg/remote_signer/grpc/doc.go rename pkg/{remote_signer => signer}/file/README.md (100%) rename pkg/{remote_signer => signer}/file/doc.go (100%) rename pkg/{remote_signer => signer}/file/example_test.go (100%) rename pkg/{remote_signer => signer}/file/local.go (98%) rename pkg/{remote_signer => signer}/noop/doc.go (100%) rename pkg/{remote_signer => signer}/noop/signer.go (86%) rename pkg/{remote_signer => signer}/noop/signer_test.go (100%) rename pkg/{remote_signer => signer}/signer.go (94%) rename pkg/{remote_signer => signer}/v1/signer.pb.go (100%) diff --git a/block/manager.go b/block/manager.go index 49eb39c23e..6d2a49c0fe 100644 --- a/block/manager.go +++ b/block/manager.go @@ -25,7 +25,7 @@ import ( "github.com/rollkit/rollkit/pkg/config" "github.com/rollkit/rollkit/pkg/genesis" "github.com/rollkit/rollkit/pkg/queue" - "github.com/rollkit/rollkit/pkg/remote_signer" + "github.com/rollkit/rollkit/pkg/signer" "github.com/rollkit/rollkit/pkg/store" "github.com/rollkit/rollkit/types" pb "github.com/rollkit/rollkit/types/pb/rollkit/v1" @@ -107,7 +107,7 @@ type Manager struct { config config.Config genesis genesis.Genesis - proposerKey remote_signer.Signer + proposerKey signer.Signer // daHeight is the height of the latest processed DA block daHeight uint64 @@ -221,7 +221,7 @@ func getInitialState(ctx context.Context, genesis genesis.Genesis, store store.S // NewManager creates new block Manager. func NewManager( ctx context.Context, - proposerKey remote_signer.Signer, + proposerKey signer.Signer, config config.Config, genesis genesis.Genesis, store store.Store, @@ -395,7 +395,7 @@ func (m *Manager) SetDALC(dalc coreda.Client) { } // isProposer returns whether or not the manager is a proposer -func isProposer(_ remote_signer.Signer, _ types.State) (bool, error) { +func isProposer(_ signer.Signer, _ types.State) (bool, error) { return true, nil } diff --git a/block/manager_test.go b/block/manager_test.go index 5a0b824990..dc3b16c19c 100644 --- a/block/manager_test.go +++ b/block/manager_test.go @@ -24,8 +24,8 @@ import ( "github.com/rollkit/rollkit/pkg/config" genesispkg "github.com/rollkit/rollkit/pkg/genesis" "github.com/rollkit/rollkit/pkg/queue" - "github.com/rollkit/rollkit/pkg/remote_signer" - noopsigner "github.com/rollkit/rollkit/pkg/remote_signer/noop" + "github.com/rollkit/rollkit/pkg/signer" + noopsigner "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/pkg/store" "github.com/rollkit/rollkit/test/mocks" "github.com/rollkit/rollkit/types" @@ -177,13 +177,13 @@ func TestSignVerifySignature(t *testing.T) { payload := []byte("test") privKey, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 256) require.NoError(err) - signer, err := noopsigner.NewNoopSigner(privKey) + noopSigner, err := noopsigner.NewNoopSigner(privKey) require.NoError(err) cases := []struct { name string - signer remote_signer.Signer + signer signer.Signer }{ - {"ed25519", signer}, + {"ed25519", noopSigner}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { @@ -363,7 +363,7 @@ func Test_isProposer(t *testing.T) { type args struct { state types.State - signerPrivKey remote_signer.Signer + signerPrivKey signer.Signer } tests := []struct { name string diff --git a/cmd/rollkit/commands/init.go b/cmd/rollkit/commands/init.go index 64ce463c3b..ae5de3dbfb 100644 --- a/cmd/rollkit/commands/init.go +++ b/cmd/rollkit/commands/init.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" rollconf "github.com/rollkit/rollkit/pkg/config" + "github.com/rollkit/rollkit/pkg/signer/file" ) // InitCmd initializes a new rollkit.yaml file in the current directory @@ -65,6 +66,34 @@ var InitCmd = &cobra.Command{ return fmt.Errorf("error creating directory %s: %w", homePath, err) } + // If using local file signer, initialize the key + if config.RemoteSigner.SignerType == "file" { + // Get passphrase if local signing is enabled + passphrase, err := cmd.Flags().GetString(rollconf.FlagRemoteSignerPassphrase) + if err != nil { + return fmt.Errorf("error reading passphrase flag: %w", err) + } + + if passphrase == "" { + return fmt.Errorf("passphrase is required when using local file signer") + } + + // Create signer directory if it doesn't exist + signerDir := filepath.Join(homePath, "signer") + if err := os.MkdirAll(signerDir, rollconf.DefaultDirPerm); err != nil { + return fmt.Errorf("failed to create signer directory: %w", err) + } + + // Set signer path + config.RemoteSigner.SignerPath = filepath.Join(signerDir, "key.json") + + // Initialize the signer + _, err = file.NewFileSystemSigner(config.RemoteSigner.SignerPath, []byte(passphrase)) + if err != nil { + return fmt.Errorf("failed to initialize signer: %w", err) + } + } + // Use writeYamlConfig instead of manual marshaling and file writing if err := rollconf.WriteYamlConfig(config); err != nil { return fmt.Errorf("error writing rollkit.yaml file: %w", err) @@ -74,3 +103,8 @@ var InitCmd = &cobra.Command{ return nil }, } + +func init() { + // Add passphrase flag + InitCmd.Flags().String(rollconf.FlagRemoteSignerPassphrase, "", "Passphrase for encrypting the local signer key (required when using local file signer)") +} diff --git a/cmd/rollkit/commands/run_node.go b/cmd/rollkit/commands/run_node.go index e9e928f9a5..d8320d453a 100644 --- a/cmd/rollkit/commands/run_node.go +++ b/cmd/rollkit/commands/run_node.go @@ -5,22 +5,16 @@ import ( "encoding/json" "errors" "fmt" - "net" "net/http" "os" "path/filepath" "strings" - "syscall" "time" "cosmossdk.io/log" "github.com/rs/zerolog" "github.com/spf13/cobra" "github.com/spf13/viper" - "google.golang.org/grpc" - - seqGRPC "github.com/rollkit/go-sequencing/proxy/grpc" - seqTest "github.com/rollkit/go-sequencing/test" coreda "github.com/rollkit/rollkit/core/da" coresequencer "github.com/rollkit/rollkit/core/sequencer" @@ -29,8 +23,8 @@ import ( rollconf "github.com/rollkit/rollkit/pkg/config" genesispkg "github.com/rollkit/rollkit/pkg/genesis" rollos "github.com/rollkit/rollkit/pkg/os" - "github.com/rollkit/rollkit/pkg/remote_signer" - "github.com/rollkit/rollkit/pkg/remote_signer/file" + "github.com/rollkit/rollkit/pkg/signer" + "github.com/rollkit/rollkit/pkg/signer/file" testExecutor "github.com/rollkit/rollkit/test/executors/kv" ) @@ -40,8 +34,6 @@ var ( // initialize the logger with the cometBFT defaults logger = log.NewLogger(os.Stdout) - - errSequencerAlreadyRunning = errors.New("sequencer already running") ) // NewRunNodeCmd returns the command that allows the CLI to start a node. @@ -64,17 +56,18 @@ func NewRunNodeCmd() *cobra.Command { ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() // Ensure context is cancelled when command exits - kvExecutor := createDirectKVExecutor(ctx) - - // // TODO: this should be moved elsewhere - // privValidatorKeyFile := filepath.Join(nodeConfig.RootDir, nodeConfig.ConfigDir, "priv_validator_key.json") - // privValidatorStateFile := filepath.Join(nodeConfig.RootDir, nodeConfig.DBPath, "priv_validator_state.json") - // pval := cometprivval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile) + // Check if passphrase is required and provided + if nodeConfig.Node.Aggregator && nodeConfig.RemoteSigner.SignerType == "file" { + passphrase, err := cmd.Flags().GetString(rollconf.FlagRemoteSignerPassphrase) + if err != nil { + return err + } + if passphrase == "" { + return fmt.Errorf("passphrase is required for aggregator nodes using local file signer") + } + } - // signingKey, err := crypto.UnmarshalEd25519PrivateKey(pval.Key.PrivKey.Bytes()) - // if err != nil { - // return err - // } + kvExecutor := createDirectKVExecutor(ctx) // initialize the metrics metrics := node.DefaultMetricsProvider(rollconf.DefaultInstrumentationConfig()) @@ -82,7 +75,7 @@ func NewRunNodeCmd() *cobra.Command { logger.Info("Executor address", "address", nodeConfig.Node.ExecutorAddress) //create a new remote signer - var signer remote_signer.Signer + var signer signer.Signer if nodeConfig.RemoteSigner.SignerType == "file" { passphrase, err := cmd.Flags().GetString(rollconf.FlagRemoteSignerPassphrase) if err != nil { @@ -239,30 +232,13 @@ func addNodeFlags(cmd *cobra.Command) { // This is for testing only cmd.Flags().String("kv-executor-http", ":40042", "address for the KV executor HTTP server (empty to disable)") + // Add passphrase flag + cmd.Flags().String(rollconf.FlagRemoteSignerPassphrase, "", "Passphrase for decrypting the local signer key (required for aggregator nodes using local file signer)") + // Add Rollkit flags rollconf.AddFlags(cmd) } -// tryStartMockSequencerServerGRPC will try and start a mock gRPC server with the given listenAddress. -func tryStartMockSequencerServerGRPC(listenAddress string, rollupId string) (*grpc.Server, error) { - dummySeq := seqTest.NewDummySequencer([]byte(rollupId)) - server := seqGRPC.NewServer(dummySeq, dummySeq, dummySeq) - lis, err := net.Listen("tcp", listenAddress) - if err != nil { - if errors.Is(err, syscall.EADDRINUSE) || errors.Is(err, syscall.EADDRNOTAVAIL) { - logger.Info(errSequencerAlreadyRunning.Error(), "address", listenAddress) - logger.Info("make sure your rollupID matches your sequencer", "rollupID", rollupId) - return nil, errSequencerAlreadyRunning - } - return nil, err - } - go func() { - _ = server.Serve(lis) - }() - logger.Info("Starting mock sequencer", "address", listenAddress, "rollupID", rollupId) - return server, nil -} - // createDirectKVExecutor creates a KVExecutor for testing func createDirectKVExecutor(ctx context.Context) *testExecutor.KVExecutor { kvExecutor := testExecutor.NewKVExecutor() @@ -305,19 +281,6 @@ func initFiles() error { return fmt.Errorf("failed to create data directory: %w", err) } - // // Generate the private validator config files - // cometprivvalKeyFile := filepath.Join(configDir, "priv_validator_key.json") - // cometprivvalStateFile := filepath.Join(dataDir, "priv_validator_state.json") - // if rollos.FileExists(cometprivvalKeyFile) { - // logger.Info("Found private validator", "keyFile", cometprivvalKeyFile, - // "stateFile", cometprivvalStateFile) - // } else { - // pv := cometprivval.GenFilePV(cometprivvalKeyFile, cometprivvalStateFile) - // pv.Save() - // logger.Info("Generated private validator", "keyFile", cometprivvalKeyFile, - // "stateFile", cometprivvalStateFile) - // } - // Generate the genesis file genFile := filepath.Join(configDir, "genesis.json") if rollos.FileExists(genFile) { diff --git a/cmd/rollkit/commands/run_node_test.go b/cmd/rollkit/commands/run_node_test.go index ab90fa9138..07e32bc32b 100644 --- a/cmd/rollkit/commands/run_node_test.go +++ b/cmd/rollkit/commands/run_node_test.go @@ -2,8 +2,6 @@ package commands import ( "context" - "crypto/rand" - "encoding/binary" "fmt" "net" "net/http" @@ -208,98 +206,6 @@ func TestCentralizedAddresses(t *testing.T) { } } -func TestStartMockSequencerServer(t *testing.T) { - // Use a random base port to avoid conflicts - var randomBytes [2]byte - if _, err := rand.Read(randomBytes[:]); err != nil { - t.Fatalf("Failed to generate random port: %v", err) - } - basePort := 60000 + int(binary.LittleEndian.Uint16(randomBytes[:]))%5000 - - tests := []struct { - name string - seqAddress string - expectedErr error - setup func() (*net.Listener, error) - teardown func(*net.Listener) - }{ - { - name: "Success", - seqAddress: fmt.Sprintf("localhost:%d", basePort), - expectedErr: nil, - }, - { - name: "Invalid URL", - seqAddress: "://invalid", - expectedErr: &net.OpError{}, - }, - { - name: "Server Already Running", - seqAddress: fmt.Sprintf("localhost:%d", basePort+1), - expectedErr: errSequencerAlreadyRunning, - setup: func() (*net.Listener, error) { - // Start a TCP listener to simulate a running server - l, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", basePort+1)) - if err != nil { - return nil, err - } - // Keep the connection open - go func() { - for { - conn, err := l.Accept() - if err != nil { - return - } - if err := conn.Close(); err != nil { - t.Errorf("Failed to close connection: %v", err) - return - } - } - }() - return &l, nil - }, - teardown: func(l *net.Listener) { - if l != nil { - if err := (*l).Close(); err != nil { - t.Errorf("Failed to close listener: %v", err) - } - } - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var listener *net.Listener - if tt.setup != nil { - var err error - listener, err = tt.setup() - if err != nil { - t.Fatal(err) - } - } - - if tt.teardown != nil && listener != nil { - defer tt.teardown(listener) - } - - srv, err := tryStartMockSequencerServerGRPC(tt.seqAddress, "test-rollup-id") - if srv != nil { - srv.Stop() - } - - if tt.expectedErr != nil { - assert.Error(t, err) - assert.IsType(t, tt.expectedErr, err) - assert.Nil(t, srv) - } else { - assert.NoError(t, err) - assert.NotNil(t, srv) - } - }) - } -} - func TestInitFiles(t *testing.T) { // Save the original nodeConfig origNodeConfig := nodeConfig diff --git a/node/full.go b/node/full.go index b58d310bb6..1d5432e1f4 100644 --- a/node/full.go +++ b/node/full.go @@ -23,9 +23,9 @@ import ( "github.com/rollkit/rollkit/pkg/config" genesispkg "github.com/rollkit/rollkit/pkg/genesis" "github.com/rollkit/rollkit/pkg/p2p" - "github.com/rollkit/rollkit/pkg/remote_signer" rpcserver "github.com/rollkit/rollkit/pkg/rpc/server" "github.com/rollkit/rollkit/pkg/service" + "github.com/rollkit/rollkit/pkg/signer" "github.com/rollkit/rollkit/pkg/store" "github.com/rollkit/rollkit/pkg/sync" ) @@ -68,7 +68,7 @@ type FullNode struct { func newFullNode( ctx context.Context, nodeConfig config.Config, - signer remote_signer.Signer, + signer signer.Signer, genesis genesispkg.Genesis, exec coreexecutor.Executor, sequencer coresequencer.Sequencer, @@ -185,7 +185,7 @@ func initDataSyncService( func initBlockManager( ctx context.Context, - signer remote_signer.Signer, + signer signer.Signer, exec coreexecutor.Executor, nodeConfig config.Config, genesis genesispkg.Genesis, diff --git a/node/full_node_integration_test.go b/node/full_node_integration_test.go index 55e346203d..c3c33e62d9 100644 --- a/node/full_node_integration_test.go +++ b/node/full_node_integration_test.go @@ -17,7 +17,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" - remote_signer "github.com/rollkit/rollkit/pkg/remote_signer/noop" + remote_signer "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/types" ) diff --git a/node/helpers_test.go b/node/helpers_test.go index cbf28828df..b92d2a8730 100644 --- a/node/helpers_test.go +++ b/node/helpers_test.go @@ -13,7 +13,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" - remote_signer "github.com/rollkit/rollkit/pkg/remote_signer/noop" + remote_signer "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/types" ) diff --git a/node/node.go b/node/node.go index eeb4512c28..1408ea304d 100644 --- a/node/node.go +++ b/node/node.go @@ -10,8 +10,8 @@ import ( coresequencer "github.com/rollkit/rollkit/core/sequencer" "github.com/rollkit/rollkit/pkg/config" "github.com/rollkit/rollkit/pkg/genesis" - "github.com/rollkit/rollkit/pkg/remote_signer" "github.com/rollkit/rollkit/pkg/service" + "github.com/rollkit/rollkit/pkg/signer" ) // Node is the interface for a rollup node @@ -28,7 +28,7 @@ func NewNode( exec coreexecutor.Executor, sequencer coresequencer.Sequencer, dac coreda.Client, - signer remote_signer.Signer, + signer signer.Signer, genesis genesis.Genesis, metricsProvider MetricsProvider, logger log.Logger, diff --git a/node/node_integration_test.go b/node/node_integration_test.go index c477ed7ad8..7b3e2e0c91 100644 --- a/node/node_integration_test.go +++ b/node/node_integration_test.go @@ -18,7 +18,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" - remote_signer "github.com/rollkit/rollkit/pkg/remote_signer/noop" + remote_signer "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/types" ) diff --git a/node/node_test.go b/node/node_test.go index 3c330d66a6..8eefb876d9 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -20,7 +20,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" - remote_signer "github.com/rollkit/rollkit/pkg/remote_signer/noop" + remote_signer "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/types" ) diff --git a/pkg/config/config.go b/pkg/config/config.go index bc362cf986..bdbc537a5c 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -109,6 +109,7 @@ const ( FlagRemoteSignerPath = "remote_signer.path" // FlagRemoteSignerPassphrase is a flag for specifying the remote signer passphrase + //nolint:gosec FlagRemoteSignerPassphrase = "remote_signer.passphrase" // RPC configuration flags diff --git a/pkg/remote_signer/grpc/doc.go b/pkg/remote_signer/grpc/doc.go deleted file mode 100644 index 6fb2df45f9..0000000000 --- a/pkg/remote_signer/grpc/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -/* -GRPC Remote Signer implements the SignerService generated interface from the .proto file. - -The implementation run on the node is the client, the server is remote and must be implemented by the user. -*/ -package grpc diff --git a/pkg/remote_signer/file/README.md b/pkg/signer/file/README.md similarity index 100% rename from pkg/remote_signer/file/README.md rename to pkg/signer/file/README.md diff --git a/pkg/remote_signer/file/doc.go b/pkg/signer/file/doc.go similarity index 100% rename from pkg/remote_signer/file/doc.go rename to pkg/signer/file/doc.go diff --git a/pkg/remote_signer/file/example_test.go b/pkg/signer/file/example_test.go similarity index 100% rename from pkg/remote_signer/file/example_test.go rename to pkg/signer/file/example_test.go diff --git a/pkg/remote_signer/file/local.go b/pkg/signer/file/local.go similarity index 98% rename from pkg/remote_signer/file/local.go rename to pkg/signer/file/local.go index e747ccb22a..4a8049f42f 100644 --- a/pkg/remote_signer/file/local.go +++ b/pkg/signer/file/local.go @@ -14,7 +14,7 @@ import ( "github.com/libp2p/go-libp2p/core/crypto" "golang.org/x/crypto/argon2" - "github.com/rollkit/rollkit/pkg/remote_signer" + "github.com/rollkit/rollkit/pkg/signer" ) // FileSystemSigner implements a signer that securely stores keys on disk @@ -36,7 +36,7 @@ type keyData struct { // NewFileSystemSigner creates a new signer that stores keys securely on disk. // If the keys don't exist at the specified paths, it generates new ones. -func NewFileSystemSigner(keyPath string, passphrase []byte) (remote_signer.Signer, error) { +func NewFileSystemSigner(keyPath string, passphrase []byte) (signer.Signer, error) { defer zeroBytes(passphrase) // Wipe passphrase from memory after use // Create directory if it doesn't exist diff --git a/pkg/remote_signer/noop/doc.go b/pkg/signer/noop/doc.go similarity index 100% rename from pkg/remote_signer/noop/doc.go rename to pkg/signer/noop/doc.go diff --git a/pkg/remote_signer/noop/signer.go b/pkg/signer/noop/signer.go similarity index 86% rename from pkg/remote_signer/noop/signer.go rename to pkg/signer/noop/signer.go index 2c12ecd4a9..02698e41b5 100644 --- a/pkg/remote_signer/noop/signer.go +++ b/pkg/signer/noop/signer.go @@ -3,7 +3,7 @@ package noop import ( "github.com/libp2p/go-libp2p/core/crypto" - "github.com/rollkit/rollkit/pkg/remote_signer" + "github.com/rollkit/rollkit/pkg/signer" ) // NoopSigner implements the remote_signer.Signer interface. @@ -14,7 +14,7 @@ type NoopSigner struct { } // NewNoopSigner creates a new signer with a fresh Ed25519 key pair. -func NewNoopSigner(privKey crypto.PrivKey) (remote_signer.Signer, error) { +func NewNoopSigner(privKey crypto.PrivKey) (signer.Signer, error) { return &NoopSigner{ privKey: privKey, diff --git a/pkg/remote_signer/noop/signer_test.go b/pkg/signer/noop/signer_test.go similarity index 100% rename from pkg/remote_signer/noop/signer_test.go rename to pkg/signer/noop/signer_test.go diff --git a/pkg/remote_signer/signer.go b/pkg/signer/signer.go similarity index 94% rename from pkg/remote_signer/signer.go rename to pkg/signer/signer.go index 72a9bb11d2..ccbb50216d 100644 --- a/pkg/remote_signer/signer.go +++ b/pkg/signer/signer.go @@ -1,4 +1,4 @@ -package remote_signer +package signer import ( "github.com/libp2p/go-libp2p/core/crypto" diff --git a/pkg/remote_signer/v1/signer.pb.go b/pkg/signer/v1/signer.pb.go similarity index 100% rename from pkg/remote_signer/v1/signer.pb.go rename to pkg/signer/v1/signer.pb.go diff --git a/specs/lazy-adr/adr-017-node-pruning.md b/specs/lazy-adr/adr-017-node-pruning.md index 5a3abdb33d..f7559ea756 100644 --- a/specs/lazy-adr/adr-017-node-pruning.md +++ b/specs/lazy-adr/adr-017-node-pruning.md @@ -50,13 +50,13 @@ graph TB Store --> PM Store --> VM Store --> Cache - + PM --> VM VM --> MV VM --> HV VM --> WV VM --> CV - + PS --> PM VC --> VM PC --> VM @@ -64,7 +64,7 @@ graph TB classDef configNode fill:#f9f,stroke:#333,stroke-width:2px,color:black classDef volumeNode fill:#bbf,stroke:#333,stroke-width:2px,color:black classDef nodeComponent fill:#bfb,stroke:#333,stroke-width:2px,color:black - + class PS,VC,PC configNode class MV,HV,WV,CV volumeNode class API,Store,PM,VM,Cache nodeComponent @@ -111,91 +111,92 @@ The pruning system is designed to work with various types of storage volumes and 1. **Local Storage Volumes**: - **Linux Logical Volumes (LVM)**: - * Flexible volume management allowing dynamic resizing - * Ability to stripe data across multiple physical devices - * Snapshot capabilities for backup purposes + - Flexible volume management allowing dynamic resizing + - Ability to stripe data across multiple physical devices + - Snapshot capabilities for backup purposes - **Direct Mount Points**: - * Traditional filesystem mounts (ext4, xfs, etc.) - * Direct attached storage devices - * RAID arrays + - Traditional filesystem mounts (ext4, xfs, etc.) + - Direct attached storage devices + - RAID arrays - **Bind Mounts**: - * Remapping directories to different locations - * Useful for reorganizing storage without changing physical layout + - Remapping directories to different locations + - Useful for reorganizing storage without changing physical layout 2. **Network Storage**: - **NFS (Network File System)**: - * Remote filesystem mounts - * Shared storage across multiple nodes - * Suitable for warm storage tiers + - Remote filesystem mounts + - Shared storage across multiple nodes + - Suitable for warm storage tiers - **SAN (Storage Area Network)**: - * High-performance block storage - * Suitable for hot storage tiers - * iSCSI or Fiber Channel connectivity + - High-performance block storage + - Suitable for hot storage tiers + - iSCSI or Fiber Channel connectivity 3. **Cloud Storage Systems**: - **Object Storage**: - * Amazon S3 and compatible systems - * Google Cloud Storage - * Azure Blob Storage - * Suitable for cold storage tiers + - Amazon S3 and compatible systems + - Google Cloud Storage + - Azure Blob Storage + - Suitable for cold storage tiers - **Archive Storage**: - * Amazon S3 Glacier - * Google Cloud Archive Storage - * Azure Archive Storage - * Lowest cost, highest latency + - Amazon S3 Glacier + - Google Cloud Archive Storage + - Azure Archive Storage + - Lowest cost, highest latency - **File Storage**: - * Amazon EFS - * Google Filestore - * Azure Files - * Mountable as network filesystems + - Amazon EFS + - Google Filestore + - Azure Files + - Mountable as network filesystems 4. **Volume Performance Classifications**: - **Hot Storage** (Lowest Latency): - * Local NVMe SSDs - * High-performance SAN volumes - * Used for recent blocks and frequently accessed data + - Local NVMe SSDs + - High-performance SAN volumes + - Used for recent blocks and frequently accessed data - **Warm Storage** (Medium Latency): - * Local HDDs - * NFS mounts - * Network block storage - * Used for moderately old or occasionally accessed data + - Local HDDs + - NFS mounts + - Network block storage + - Used for moderately old or occasionally accessed data - **Cold Storage** (High Latency): - * Object storage - * Archive storage - * Used for historical data with infrequent access + - Object storage + - Archive storage + - Used for historical data with infrequent access 5. **Implementation Considerations**: - **Local Volumes**: - * Direct filesystem access - * Native OS-level caching - * Immediate consistency + - Direct filesystem access + - Native OS-level caching + - Immediate consistency - **Network Volumes**: - * Connection management - * Caching strategies - * Network latency handling + - Connection management + - Caching strategies + - Network latency handling - **Cloud Storage**: - * API-based access - * Eventual consistency - * Bandwidth costs - * Lifecycle management + - API-based access + - Eventual consistency + - Bandwidth costs + - Lifecycle management 6. **Volume Interface Requirements**: Each volume type must implement: + ```go type VolumeInterface interface { // Core operations Read(ctx context.Context, key []byte) ([]byte, error) Write(ctx context.Context, key []byte, value []byte) error Delete(ctx context.Context, key []byte) error - + // Performance metrics GetLatency() time.Duration GetThroughput() int64 - + // Storage type GetStorageType() StorageType GetTier() StorageTier - + // Lifecycle Mount(ctx context.Context) error Unmount(ctx context.Context) error @@ -203,6 +204,7 @@ The pruning system is designed to work with various types of storage volumes and ``` 7. **Storage Type Configuration**: + ```yaml volumes: - path: "/data/rollkit/volumes/volume-hot-1" @@ -222,6 +224,7 @@ The pruning system is designed to work with various types of storage volumes and ``` This variety of storage options allows node operators to: + - Implement cost-effective tiered storage strategies - Scale storage capacity independently of compute resources - Optimize for different performance requirements @@ -352,10 +355,10 @@ The volume management system is designed to work in harmony with node operators' - Performance tiers (e.g., "fast" for SSD, "standard" for HDD, "cold" for archival storage) - Query statistics are built over time to optimize data placement and retrieval - System automatically routes queries to the most appropriate volume based on: - * Query patterns - * Data access frequency - * Volume performance characteristics - * Historical latency measurements + - Query patterns + - Data access frequency + - Volume performance characteristics + - Historical latency measurements 3. **Node Operator Responsibilities**: - Create the base volume directory structure @@ -378,43 +381,44 @@ The volume management system is designed to work in harmony with node operators' - Logs warning if no suitable subdirectory is found - Node operator must ensure appropriate devices are mounted before volumes can be created -Example directory structure with performance tiers: + Example directory structure with performance tiers: -```bash -/data/rollkit/volumes/ # VolumesDirectory -├── volume-main/ # Main volume (fast tier - NVMe SSD) -├── volume-hot-1/ # Hot data volume (fast tier - SSD) -├── volume-hot-2/ # Hot data volume (fast tier - SSD) -├── volume-warm-1/ # Warm data volume (standard tier - HDD) -├── volume-warm-2/ # Warm data volume (standard tier - HDD) -└── volume-cold-1/ # Cold storage volume (cold tier - HDD) -``` + ```bash + /data/rollkit/volumes/ # VolumesDirectory + ├── volume-main/ # Main volume (fast tier - NVMe SSD) + ├── volume-hot-1/ # Hot data volume (fast tier - SSD) + ├── volume-hot-2/ # Hot data volume (fast tier - SSD) + ├── volume-warm-1/ # Warm data volume (standard tier - HDD) + ├── volume-warm-2/ # Warm data volume (standard tier - HDD) + └── volume-cold-1/ # Cold storage volume (cold tier - HDD) + ``` 6. **Configuration Example with Performance Tiers**: -```yaml -pruning: - volume_config: - enabled: true - main_volume_path: "/data/rollkit/volumes/volume-main" - volumes_directory: "/data/rollkit/volumes" - volume_pattern: "volume-*" - auto_create_volumes: true - target_max_volume_size: 1099511627776 # 1 TB - size_monitoring_interval: 1000 - volumes: - - path: "/data/rollkit/volumes/volume-hot-1" - performance: - tier: "fast" - estimated_latency_ms: 5 - - path: "/data/rollkit/volumes/volume-warm-1" - performance: - tier: "standard" - estimated_latency_ms: 20 - - path: "/data/rollkit/volumes/volume-cold-1" - performance: - tier: "cold" - estimated_latency_ms: 100 -``` + + ```yaml + pruning: + volume_config: + enabled: true + main_volume_path: "/data/rollkit/volumes/volume-main" + volumes_directory: "/data/rollkit/volumes" + volume_pattern: "volume-*" + auto_create_volumes: true + target_max_volume_size: 1099511627776 # 1 TB + size_monitoring_interval: 1000 + volumes: + - path: "/data/rollkit/volumes/volume-hot-1" + performance: + tier: "fast" + estimated_latency_ms: 5 + - path: "/data/rollkit/volumes/volume-warm-1" + performance: + tier: "standard" + estimated_latency_ms: 20 + - path: "/data/rollkit/volumes/volume-cold-1" + performance: + tier: "cold" + estimated_latency_ms: 100 + ``` 7. **Query Optimization**: - System maintains statistics about query patterns per volume @@ -424,6 +428,7 @@ pruning: - Multiple volumes on the same physical device share underlying performance characteristics This approach ensures: + - Clear separation of concerns between system-level disk management and application-level volume management - Node operators maintain control over physical storage allocation - Application remains storage-agnostic while respecting operator's disk management choices @@ -525,6 +530,7 @@ The Volume Registry will implement a size-based monitoring system to manage volu - Monitor growth rate and project volume utilization 2. **Dynamic Block Height Calculation**: + ```go type VolumeStats struct { CurrentSize int64 @@ -552,6 +558,7 @@ The Volume Registry will implement a size-based monitoring system to manage volu - Volume growth rate This approach provides several advantages: + - More accurate capacity planning based on actual data size - Adaptation to varying block sizes - Early warning for volume transitions @@ -668,52 +675,52 @@ rollkit migrate-storage [subcommand] [flags] 1. **analyze**: Scans existing data and plans migration -```bash -rollkit migrate-storage analyze [--data-dir=] -``` + ```bash + rollkit migrate-storage analyze [--data-dir=] + ``` -- Estimates storage requirements -- Generates migration plan with volume configuration -- Reports potential issues -- Estimates duration and resource needs + - Estimates storage requirements + - Generates migration plan with volume configuration + - Reports potential issues + - Estimates duration and resource needs 2. **backup**: Creates pre-migration backup -```bash -rollkit migrate-storage backup [--data-dir=] [--backup-dir=] -``` + ```bash + rollkit migrate-storage backup [--data-dir=] [--backup-dir=] + ``` -- Full backup with checksums -- Backup metadata and manifest generation + - Full backup with checksums + - Backup metadata and manifest generation 3. **execute**: Performs migration -```bash -rollkit migrate-storage execute [--config=] [--data-dir=] [--dry-run] [--parallel=] -``` + ```bash + rollkit migrate-storage execute [--config=] [--data-dir=] [--dry-run] [--parallel=] + ``` -- Supports resumable operations -- Dry-run mode for testing -- Configurable parallelism + - Supports resumable operations + - Dry-run mode for testing + - Configurable parallelism 4. **verify**: Validates migration -```bash -rollkit migrate-storage verify [--data-dir=] -``` + ```bash + rollkit migrate-storage verify [--data-dir=] + ``` -- Data integrity checks -- Block height continuity validation -- Volume configuration verification + - Data integrity checks + - Block height continuity validation + - Volume configuration verification 5. **rollback**: Reverts migration -```bash -rollkit migrate-storage rollback [--data-dir=] [--backup-dir=] -``` + ```bash + rollkit migrate-storage rollback [--data-dir=] [--backup-dir=] + ``` -- Restores from backup -- Validates restoration + - Restores from backup + - Validates restoration #### Migration Configuration @@ -740,19 +747,19 @@ migration: performance: tier: "cold" estimated_latency_ms: 100 - + settings: parallel_workers: 4 batch_size: 10000 checkpoint_interval: 1000 validate_checksums: true size_monitoring_interval: 1000 - + backup: enabled: true path: /path/to/backup compress: true - + monitoring: log_level: "info" metrics_enabled: true @@ -834,30 +841,30 @@ type MonitoringConfig struct { 1. Pre-migration analysis and backup: -```bash -# Analyze existing data -rollkit migrate-storage analyze --data-dir=/path/to/node + ```bash + # Analyze existing data + rollkit migrate-storage analyze --data-dir=/path/to/node -# Create backup -rollkit migrate-storage backup --data-dir=/path/to/node --backup-dir=/path/to/backup -``` + # Create backup + rollkit migrate-storage backup --data-dir=/path/to/node --backup-dir=/path/to/backup + ``` 2. Execute migration and verify: -```bash -# Perform migration -rollkit migrate-storage execute --config=migration-config.yaml + ```bash + # Perform migration + rollkit migrate-storage execute --config=migration-config.yaml -# Verify results -rollkit migrate-storage verify --data-dir=/path/to/node -``` + # Verify results + rollkit migrate-storage verify --data-dir=/path/to/node + ``` 3. Rollback if needed: -```bash -# Revert changes -rollkit migrate-storage rollback --data-dir=/path/to/node --backup-dir=/path/to/backup -``` + ```bash + # Revert changes + rollkit migrate-storage rollback --data-dir=/path/to/node --backup-dir=/path/to/backup + ``` This CLI-based approach provides a structured and safe way to migrate existing nodes while addressing key challenges: @@ -879,11 +886,11 @@ Proposed 1. **Reduced Storage Requirements**: Nodes will require less disk space, especially for long-running chains 2. **Improved Performance**: Database operations may become faster with a smaller dataset and optimized volume management 3. **Lower Barrier to Entry**: New node operators can join with less storage overhead -4. **Flexible Storage Management**: +4. **Flexible Storage Management**: - Operators can choose pruning strategies that fit their needs - Support for multiple storage tiers (hot, warm, cold) - Dynamic volume management based on access patterns -5. **Cost Optimization**: +5. **Cost Optimization**: - Efficient use of available storage resources - Less frequently accessed data can be stored on cheaper storage tiers - Automatic data placement based on access patterns @@ -894,7 +901,7 @@ Proposed ### Negative -1. **Limited Historical Queries**: +1. **Limited Historical Queries**: - Depending on the pruning strategy, some historical data may not be immediately available - Increased latency for accessing archived data 2. **Implementation Complexity**: @@ -937,4 +944,4 @@ Proposed - [Rollkit Store Implementation](https://github.com/rollkit/rollkit/blob/main/store/store.go) - [Block Manager](https://github.com/rollkit/rollkit/blob/main/block/manager.go) -- [Store Interface](https://github.com/rollkit/rollkit/blob/main/store/types.go) \ No newline at end of file +- [Store Interface](https://github.com/rollkit/rollkit/blob/main/store/types.go) From 4bc7597cb211e5867b69ebbe0a4d7a8a85f0a3d1 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 26 Mar 2025 16:14:25 +0100 Subject: [PATCH 10/29] fix proto --- buf.gen.yaml | 8 +- buf.yaml | 8 +- go.mod | 2 +- .../{pkg/remote_signer => }/v1/signer.proto | 6 +- sequencers/single/go.mod | 1 - sequencers/single/go.sum | 31 -- types/pb/rollkit/v1/rollkit.pb.go | 9 +- types/pb/rollkit/v1/signer.pb.go | 267 ++++++++++++++++++ types/pb/rollkit/v1/state.pb.go | 7 +- .../pb/rollkit/v1/v1connect/signer.connect.go | 140 +++++++++ 10 files changed, 425 insertions(+), 54 deletions(-) rename proto/rollkit/{pkg/remote_signer => }/v1/signer.proto (78%) create mode 100644 types/pb/rollkit/v1/signer.pb.go create mode 100644 types/pb/rollkit/v1/v1connect/signer.connect.go diff --git a/buf.gen.yaml b/buf.gen.yaml index 3bf3a54bc8..f678a7e8e7 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -1,14 +1,12 @@ version: v2 -# The plugins to run. + plugins: - # The name of the plugin. - remote: buf.build/protocolbuffers/go - # The relative output directory. out: types/pb - # Any options to provide to the plugin. opt: paths=source_relative - - remote: buf.build/connectrpc/go out: types/pb opt: paths=source_relative +inputs: + - directory: proto diff --git a/buf.yaml b/buf.yaml index 5ac36fe320..bf7debf7cc 100644 --- a/buf.yaml +++ b/buf.yaml @@ -1,9 +1,7 @@ -version: v1beta1 +version: v2 -build: - roots: - - proto - - third_party/proto +modules: + - path: proto lint: use: - COMMENTS diff --git a/go.mod b/go.mod index 46d5087da6..d57e3e26fc 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/cosmos/gogoproto v1.7.0 github.com/go-kit/kit v0.13.0 github.com/goccy/go-yaml v1.16.0 - github.com/gogo/protobuf v1.3.2 github.com/ipfs/go-datastore v0.7.0 github.com/ipfs/go-ds-badger4 v0.1.5 github.com/libp2p/go-libp2p v0.40.0 @@ -68,6 +67,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.2.4 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect diff --git a/proto/rollkit/pkg/remote_signer/v1/signer.proto b/proto/rollkit/v1/signer.proto similarity index 78% rename from proto/rollkit/pkg/remote_signer/v1/signer.proto rename to proto/rollkit/v1/signer.proto index 7b8316652c..82c10dbd06 100644 --- a/proto/rollkit/pkg/remote_signer/v1/signer.proto +++ b/proto/rollkit/v1/signer.proto @@ -1,8 +1,8 @@ syntax = "proto3"; -package rollkit.pkg.remote_signer.v1; +package rollkit.v1; -option go_package = "github.com/rollkit/rollkit/pkg/remote_signer/v1"; +option go_package = "github.com/rollkit/rollkit/types/pb/rollkit/v1"; // The SignRequest holds the bytes we want to sign. message SignRequest { @@ -24,6 +24,8 @@ message GetPublicResponse { // The SignerService defines the RPCs to sign and to retrieve the public key. service SignerService { + // Sign signs the given message. rpc Sign(SignRequest) returns (SignResponse); + // GetPublic returns the public key. rpc GetPublic(GetPublicRequest) returns (GetPublicResponse); } \ No newline at end of file diff --git a/sequencers/single/go.mod b/sequencers/single/go.mod index 7cf5165efd..2d5d0a4470 100644 --- a/sequencers/single/go.mod +++ b/sequencers/single/go.mod @@ -26,7 +26,6 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect diff --git a/sequencers/single/go.sum b/sequencers/single/go.sum index 2313cec212..1976192b64 100644 --- a/sequencers/single/go.sum +++ b/sequencers/single/go.sum @@ -23,8 +23,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -34,8 +32,6 @@ github.com/ipfs/go-datastore v0.7.0/go.mod h1:ucOWMfbOPI6ZEyaIB1q/+78RPLBPERfuUV github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -85,40 +81,13 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/types/pb/rollkit/v1/rollkit.pb.go b/types/pb/rollkit/v1/rollkit.pb.go index 1ced8f8d16..07ae027078 100644 --- a/types/pb/rollkit/v1/rollkit.pb.go +++ b/types/pb/rollkit/v1/rollkit.pb.go @@ -7,7 +7,6 @@ package v1 import ( - _ "github.com/gogo/protobuf/gogoproto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" @@ -559,7 +558,7 @@ var File_rollkit_v1_rollkit_proto protoreflect.FileDescriptor const file_rollkit_v1_rollkit_proto_rawDesc = "" + "\n" + "\x18rollkit/v1/rollkit.proto\x12\n" + - "rollkit.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x14gogoproto/gogo.proto\"1\n" + + "rollkit.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"1\n" + "\aVersion\x12\x14\n" + "\x05block\x18\x01 \x01(\x04R\x05block\x12\x10\n" + "\x03app\x18\x02 \x01(\x04R\x03app\"\xaf\x03\n" + @@ -591,11 +590,11 @@ const file_rollkit_v1_rollkit_proto_rawDesc = "" + "\x0elast_data_hash\x18\x04 \x01(\fR\flastDataHash\"J\n" + "\x04Data\x120\n" + "\bmetadata\x18\x01 \x01(\v2\x14.rollkit.v1.MetadataR\bmetadata\x12\x10\n" + - "\x03txs\x18\x02 \x03(\fR\x03txs\"\xce\x01\n" + + "\x03txs\x18\x02 \x03(\fR\x03txs\"\xc4\x01\n" + "\x04Vote\x12\x19\n" + "\bchain_id\x18\x01 \x01(\tR\achainId\x12\x16\n" + - "\x06height\x18\x02 \x01(\x04R\x06height\x12B\n" + - "\ttimestamp\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampB\b\xc8\xde\x1f\x00\x90\xdf\x1f\x01R\ttimestamp\x12\"\n" + + "\x06height\x18\x02 \x01(\x04R\x06height\x128\n" + + "\ttimestamp\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\ttimestamp\x12\"\n" + "\rblock_id_hash\x18\x04 \x01(\fR\vblockIdHash\x12+\n" + "\x11validator_address\x18\x05 \x01(\fR\x10validatorAddressB0Z.github.com/rollkit/rollkit/types/pb/rollkit/v1b\x06proto3" diff --git a/types/pb/rollkit/v1/signer.pb.go b/types/pb/rollkit/v1/signer.pb.go new file mode 100644 index 0000000000..bc71ca0428 --- /dev/null +++ b/types/pb/rollkit/v1/signer.pb.go @@ -0,0 +1,267 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc (unknown) +// source: rollkit/v1/signer.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The SignRequest holds the bytes we want to sign. +type SignRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Message []byte `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SignRequest) Reset() { + *x = SignRequest{} + mi := &file_rollkit_v1_signer_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SignRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignRequest) ProtoMessage() {} + +func (x *SignRequest) ProtoReflect() protoreflect.Message { + mi := &file_rollkit_v1_signer_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignRequest.ProtoReflect.Descriptor instead. +func (*SignRequest) Descriptor() ([]byte, []int) { + return file_rollkit_v1_signer_proto_rawDescGZIP(), []int{0} +} + +func (x *SignRequest) GetMessage() []byte { + if x != nil { + return x.Message + } + return nil +} + +// The SignResponse returns the signature bytes. +type SignResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SignResponse) Reset() { + *x = SignResponse{} + mi := &file_rollkit_v1_signer_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SignResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignResponse) ProtoMessage() {} + +func (x *SignResponse) ProtoReflect() protoreflect.Message { + mi := &file_rollkit_v1_signer_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignResponse.ProtoReflect.Descriptor instead. +func (*SignResponse) Descriptor() ([]byte, []int) { + return file_rollkit_v1_signer_proto_rawDescGZIP(), []int{1} +} + +func (x *SignResponse) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +// The GetPublicRequest is an empty request. +type GetPublicRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPublicRequest) Reset() { + *x = GetPublicRequest{} + mi := &file_rollkit_v1_signer_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPublicRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPublicRequest) ProtoMessage() {} + +func (x *GetPublicRequest) ProtoReflect() protoreflect.Message { + mi := &file_rollkit_v1_signer_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPublicRequest.ProtoReflect.Descriptor instead. +func (*GetPublicRequest) Descriptor() ([]byte, []int) { + return file_rollkit_v1_signer_proto_rawDescGZIP(), []int{2} +} + +// The GetPublicResponse returns the public key. +type GetPublicResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPublicResponse) Reset() { + *x = GetPublicResponse{} + mi := &file_rollkit_v1_signer_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPublicResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPublicResponse) ProtoMessage() {} + +func (x *GetPublicResponse) ProtoReflect() protoreflect.Message { + mi := &file_rollkit_v1_signer_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPublicResponse.ProtoReflect.Descriptor instead. +func (*GetPublicResponse) Descriptor() ([]byte, []int) { + return file_rollkit_v1_signer_proto_rawDescGZIP(), []int{3} +} + +func (x *GetPublicResponse) GetPublicKey() []byte { + if x != nil { + return x.PublicKey + } + return nil +} + +var File_rollkit_v1_signer_proto protoreflect.FileDescriptor + +const file_rollkit_v1_signer_proto_rawDesc = "" + + "\n" + + "\x17rollkit/v1/signer.proto\x12\n" + + "rollkit.v1\"'\n" + + "\vSignRequest\x12\x18\n" + + "\amessage\x18\x01 \x01(\fR\amessage\",\n" + + "\fSignResponse\x12\x1c\n" + + "\tsignature\x18\x01 \x01(\fR\tsignature\"\x12\n" + + "\x10GetPublicRequest\"2\n" + + "\x11GetPublicResponse\x12\x1d\n" + + "\n" + + "public_key\x18\x01 \x01(\fR\tpublicKey2\x94\x01\n" + + "\rSignerService\x129\n" + + "\x04Sign\x12\x17.rollkit.v1.SignRequest\x1a\x18.rollkit.v1.SignResponse\x12H\n" + + "\tGetPublic\x12\x1c.rollkit.v1.GetPublicRequest\x1a\x1d.rollkit.v1.GetPublicResponseB0Z.github.com/rollkit/rollkit/types/pb/rollkit/v1b\x06proto3" + +var ( + file_rollkit_v1_signer_proto_rawDescOnce sync.Once + file_rollkit_v1_signer_proto_rawDescData []byte +) + +func file_rollkit_v1_signer_proto_rawDescGZIP() []byte { + file_rollkit_v1_signer_proto_rawDescOnce.Do(func() { + file_rollkit_v1_signer_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_rollkit_v1_signer_proto_rawDesc), len(file_rollkit_v1_signer_proto_rawDesc))) + }) + return file_rollkit_v1_signer_proto_rawDescData +} + +var file_rollkit_v1_signer_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_rollkit_v1_signer_proto_goTypes = []any{ + (*SignRequest)(nil), // 0: rollkit.v1.SignRequest + (*SignResponse)(nil), // 1: rollkit.v1.SignResponse + (*GetPublicRequest)(nil), // 2: rollkit.v1.GetPublicRequest + (*GetPublicResponse)(nil), // 3: rollkit.v1.GetPublicResponse +} +var file_rollkit_v1_signer_proto_depIdxs = []int32{ + 0, // 0: rollkit.v1.SignerService.Sign:input_type -> rollkit.v1.SignRequest + 2, // 1: rollkit.v1.SignerService.GetPublic:input_type -> rollkit.v1.GetPublicRequest + 1, // 2: rollkit.v1.SignerService.Sign:output_type -> rollkit.v1.SignResponse + 3, // 3: rollkit.v1.SignerService.GetPublic:output_type -> rollkit.v1.GetPublicResponse + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_rollkit_v1_signer_proto_init() } +func file_rollkit_v1_signer_proto_init() { + if File_rollkit_v1_signer_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_rollkit_v1_signer_proto_rawDesc), len(file_rollkit_v1_signer_proto_rawDesc)), + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_rollkit_v1_signer_proto_goTypes, + DependencyIndexes: file_rollkit_v1_signer_proto_depIdxs, + MessageInfos: file_rollkit_v1_signer_proto_msgTypes, + }.Build() + File_rollkit_v1_signer_proto = out.File + file_rollkit_v1_signer_proto_goTypes = nil + file_rollkit_v1_signer_proto_depIdxs = nil +} diff --git a/types/pb/rollkit/v1/state.pb.go b/types/pb/rollkit/v1/state.pb.go index 9cf51853a9..46cef39037 100644 --- a/types/pb/rollkit/v1/state.pb.go +++ b/types/pb/rollkit/v1/state.pb.go @@ -7,7 +7,6 @@ package v1 import ( - _ "github.com/gogo/protobuf/gogoproto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" @@ -129,13 +128,13 @@ var File_rollkit_v1_state_proto protoreflect.FileDescriptor const file_rollkit_v1_state_proto_rawDesc = "" + "\n" + "\x16rollkit/v1/state.proto\x12\n" + - "rollkit.v1\x1a\x14gogoproto/gogo.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x18rollkit/v1/rollkit.proto\"\xd6\x02\n" + + "rollkit.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x18rollkit/v1/rollkit.proto\"\xcc\x02\n" + "\x05State\x12-\n" + "\aversion\x18\x01 \x01(\v2\x13.rollkit.v1.VersionR\aversion\x12\x19\n" + "\bchain_id\x18\x02 \x01(\tR\achainId\x12%\n" + "\x0einitial_height\x18\x03 \x01(\x04R\rinitialHeight\x12*\n" + - "\x11last_block_height\x18\x04 \x01(\x04R\x0flastBlockHeight\x12L\n" + - "\x0flast_block_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampB\b\xc8\xde\x1f\x00\x90\xdf\x1f\x01R\rlastBlockTime\x12\x1b\n" + + "\x11last_block_height\x18\x04 \x01(\x04R\x0flastBlockHeight\x12B\n" + + "\x0flast_block_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\rlastBlockTime\x12\x1b\n" + "\tda_height\x18\x06 \x01(\x04R\bdaHeight\x12*\n" + "\x11last_results_hash\x18\a \x01(\fR\x0flastResultsHash\x12\x19\n" + "\bapp_hash\x18\b \x01(\fR\aappHashB0Z.github.com/rollkit/rollkit/types/pb/rollkit/v1b\x06proto3" diff --git a/types/pb/rollkit/v1/v1connect/signer.connect.go b/types/pb/rollkit/v1/v1connect/signer.connect.go new file mode 100644 index 0000000000..ff668b9ec2 --- /dev/null +++ b/types/pb/rollkit/v1/v1connect/signer.connect.go @@ -0,0 +1,140 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: rollkit/v1/signer.proto + +package v1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/rollkit/rollkit/types/pb/rollkit/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // SignerServiceName is the fully-qualified name of the SignerService service. + SignerServiceName = "rollkit.v1.SignerService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // SignerServiceSignProcedure is the fully-qualified name of the SignerService's Sign RPC. + SignerServiceSignProcedure = "/rollkit.v1.SignerService/Sign" + // SignerServiceGetPublicProcedure is the fully-qualified name of the SignerService's GetPublic RPC. + SignerServiceGetPublicProcedure = "/rollkit.v1.SignerService/GetPublic" +) + +// SignerServiceClient is a client for the rollkit.v1.SignerService service. +type SignerServiceClient interface { + // Sign signs the given message. + Sign(context.Context, *connect.Request[v1.SignRequest]) (*connect.Response[v1.SignResponse], error) + // GetPublic returns the public key. + GetPublic(context.Context, *connect.Request[v1.GetPublicRequest]) (*connect.Response[v1.GetPublicResponse], error) +} + +// NewSignerServiceClient constructs a client for the rollkit.v1.SignerService service. By default, +// it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and +// sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() +// or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewSignerServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) SignerServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + signerServiceMethods := v1.File_rollkit_v1_signer_proto.Services().ByName("SignerService").Methods() + return &signerServiceClient{ + sign: connect.NewClient[v1.SignRequest, v1.SignResponse]( + httpClient, + baseURL+SignerServiceSignProcedure, + connect.WithSchema(signerServiceMethods.ByName("Sign")), + connect.WithClientOptions(opts...), + ), + getPublic: connect.NewClient[v1.GetPublicRequest, v1.GetPublicResponse]( + httpClient, + baseURL+SignerServiceGetPublicProcedure, + connect.WithSchema(signerServiceMethods.ByName("GetPublic")), + connect.WithClientOptions(opts...), + ), + } +} + +// signerServiceClient implements SignerServiceClient. +type signerServiceClient struct { + sign *connect.Client[v1.SignRequest, v1.SignResponse] + getPublic *connect.Client[v1.GetPublicRequest, v1.GetPublicResponse] +} + +// Sign calls rollkit.v1.SignerService.Sign. +func (c *signerServiceClient) Sign(ctx context.Context, req *connect.Request[v1.SignRequest]) (*connect.Response[v1.SignResponse], error) { + return c.sign.CallUnary(ctx, req) +} + +// GetPublic calls rollkit.v1.SignerService.GetPublic. +func (c *signerServiceClient) GetPublic(ctx context.Context, req *connect.Request[v1.GetPublicRequest]) (*connect.Response[v1.GetPublicResponse], error) { + return c.getPublic.CallUnary(ctx, req) +} + +// SignerServiceHandler is an implementation of the rollkit.v1.SignerService service. +type SignerServiceHandler interface { + // Sign signs the given message. + Sign(context.Context, *connect.Request[v1.SignRequest]) (*connect.Response[v1.SignResponse], error) + // GetPublic returns the public key. + GetPublic(context.Context, *connect.Request[v1.GetPublicRequest]) (*connect.Response[v1.GetPublicResponse], error) +} + +// NewSignerServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewSignerServiceHandler(svc SignerServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + signerServiceMethods := v1.File_rollkit_v1_signer_proto.Services().ByName("SignerService").Methods() + signerServiceSignHandler := connect.NewUnaryHandler( + SignerServiceSignProcedure, + svc.Sign, + connect.WithSchema(signerServiceMethods.ByName("Sign")), + connect.WithHandlerOptions(opts...), + ) + signerServiceGetPublicHandler := connect.NewUnaryHandler( + SignerServiceGetPublicProcedure, + svc.GetPublic, + connect.WithSchema(signerServiceMethods.ByName("GetPublic")), + connect.WithHandlerOptions(opts...), + ) + return "/rollkit.v1.SignerService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case SignerServiceSignProcedure: + signerServiceSignHandler.ServeHTTP(w, r) + case SignerServiceGetPublicProcedure: + signerServiceGetPublicHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedSignerServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedSignerServiceHandler struct{} + +func (UnimplementedSignerServiceHandler) Sign(context.Context, *connect.Request[v1.SignRequest]) (*connect.Response[v1.SignResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("rollkit.v1.SignerService.Sign is not implemented")) +} + +func (UnimplementedSignerServiceHandler) GetPublic(context.Context, *connect.Request[v1.GetPublicRequest]) (*connect.Response[v1.GetPublicResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("rollkit.v1.SignerService.GetPublic is not implemented")) +} From 75a4d9eef5ba79f1ae67e6db2386a9a013898c91 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 26 Mar 2025 18:10:28 +0100 Subject: [PATCH 11/29] fix test by defaulting aggregator to false --- cmd/rollkit/commands/init.go | 2 +- pkg/config/defaults.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/rollkit/commands/init.go b/cmd/rollkit/commands/init.go index ae5de3dbfb..5365f660ad 100644 --- a/cmd/rollkit/commands/init.go +++ b/cmd/rollkit/commands/init.go @@ -67,7 +67,7 @@ var InitCmd = &cobra.Command{ } // If using local file signer, initialize the key - if config.RemoteSigner.SignerType == "file" { + if config.RemoteSigner.SignerType == "file" && config.Node.Aggregator { // Get passphrase if local signing is enabled passphrase, err := cmd.Flags().GetString(rollconf.FlagRemoteSignerPassphrase) if err != nil { diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 3223ca150d..1609c6e62e 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -52,7 +52,7 @@ var DefaultNodeConfig = Config{ Seeds: "", }, Node: NodeConfig{ - Aggregator: true, + Aggregator: false, BlockTime: DurationWrapper{1 * time.Second}, LazyAggregator: false, LazyBlockTime: DurationWrapper{60 * time.Second}, From 56eeb50ab439c1f45a017b9ae2cfc89f577af389 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 26 Mar 2025 18:10:46 +0100 Subject: [PATCH 12/29] fix config test --- pkg/config/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 70ade67e42..973f17971f 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -88,7 +88,7 @@ func TestAddFlags(t *testing.T) { // Verify that there are no additional flags // Count the number of flags we're explicitly checking - expectedFlagCount := 36 // Update this number if you add more flag checks above + expectedFlagCount := 39 // Update this number if you add more flag checks above // Get the actual number of flags actualFlagCount := 0 From 199d511f6a93ce100a3b1fd5c795bdd0a39c7e11 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Wed, 26 Mar 2025 18:13:38 +0100 Subject: [PATCH 13/29] fix test --- cmd/rollkit/commands/init.go | 10 +++++----- cmd/rollkit/commands/run_node.go | 17 +++++++---------- pkg/config/config.go | 28 ++++++++++++++-------------- pkg/config/defaults.go | 2 +- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/cmd/rollkit/commands/init.go b/cmd/rollkit/commands/init.go index 5365f660ad..331ad08edb 100644 --- a/cmd/rollkit/commands/init.go +++ b/cmd/rollkit/commands/init.go @@ -67,9 +67,9 @@ var InitCmd = &cobra.Command{ } // If using local file signer, initialize the key - if config.RemoteSigner.SignerType == "file" && config.Node.Aggregator { + if config.Signer.SignerType == "file" && config.Node.Aggregator { // Get passphrase if local signing is enabled - passphrase, err := cmd.Flags().GetString(rollconf.FlagRemoteSignerPassphrase) + passphrase, err := cmd.Flags().GetString(rollconf.FlagSignerPassphrase) if err != nil { return fmt.Errorf("error reading passphrase flag: %w", err) } @@ -85,10 +85,10 @@ var InitCmd = &cobra.Command{ } // Set signer path - config.RemoteSigner.SignerPath = filepath.Join(signerDir, "key.json") + config.Signer.SignerPath = filepath.Join(signerDir, "key.json") // Initialize the signer - _, err = file.NewFileSystemSigner(config.RemoteSigner.SignerPath, []byte(passphrase)) + _, err = file.NewFileSystemSigner(config.Signer.SignerPath, []byte(passphrase)) if err != nil { return fmt.Errorf("failed to initialize signer: %w", err) } @@ -106,5 +106,5 @@ var InitCmd = &cobra.Command{ func init() { // Add passphrase flag - InitCmd.Flags().String(rollconf.FlagRemoteSignerPassphrase, "", "Passphrase for encrypting the local signer key (required when using local file signer)") + InitCmd.Flags().String(rollconf.FlagSignerPassphrase, "", "Passphrase for encrypting the local signer key (required when using local file signer)") } diff --git a/cmd/rollkit/commands/run_node.go b/cmd/rollkit/commands/run_node.go index d8320d453a..ee3fbf9daa 100644 --- a/cmd/rollkit/commands/run_node.go +++ b/cmd/rollkit/commands/run_node.go @@ -57,8 +57,8 @@ func NewRunNodeCmd() *cobra.Command { defer cancel() // Ensure context is cancelled when command exits // Check if passphrase is required and provided - if nodeConfig.Node.Aggregator && nodeConfig.RemoteSigner.SignerType == "file" { - passphrase, err := cmd.Flags().GetString(rollconf.FlagRemoteSignerPassphrase) + if nodeConfig.Node.Aggregator && nodeConfig.Signer.SignerType == "file" { + passphrase, err := cmd.Flags().GetString(rollconf.FlagSignerPassphrase) if err != nil { return err } @@ -76,20 +76,20 @@ func NewRunNodeCmd() *cobra.Command { //create a new remote signer var signer signer.Signer - if nodeConfig.RemoteSigner.SignerType == "file" { - passphrase, err := cmd.Flags().GetString(rollconf.FlagRemoteSignerPassphrase) + if nodeConfig.Signer.SignerType == "file" { + passphrase, err := cmd.Flags().GetString(rollconf.FlagSignerPassphrase) if err != nil { return err } - signer, err = file.NewFileSystemSigner(nodeConfig.RemoteSigner.SignerPath, []byte(passphrase)) + signer, err = file.NewFileSystemSigner(nodeConfig.Signer.SignerPath, []byte(passphrase)) if err != nil { return err } - } else if nodeConfig.RemoteSigner.SignerType == "grpc" { + } else if nodeConfig.Signer.SignerType == "grpc" { panic("grpc remote signer not implemented") } else { - return fmt.Errorf("unknown remote signer type: %s", nodeConfig.RemoteSigner.SignerType) + return fmt.Errorf("unknown remote signer type: %s", nodeConfig.Signer.SignerType) } dummySequencer := coresequencer.NewDummySequencer() @@ -232,9 +232,6 @@ func addNodeFlags(cmd *cobra.Command) { // This is for testing only cmd.Flags().String("kv-executor-http", ":40042", "address for the KV executor HTTP server (empty to disable)") - // Add passphrase flag - cmd.Flags().String(rollconf.FlagRemoteSignerPassphrase, "", "Passphrase for decrypting the local signer key (required for aggregator nodes using local file signer)") - // Add Rollkit flags rollconf.AddFlags(cmd) } diff --git a/pkg/config/config.go b/pkg/config/config.go index bdbc537a5c..4179475c48 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -101,16 +101,16 @@ const ( // FlagLogTrace is a flag for enabling stack traces in error logs FlagLogTrace = "log.trace" - // Remote signer configuration flags + // Signer configuration flags - // FlagRemoteSignerType is a flag for specifying the remote signer type - FlagRemoteSignerType = "remote_signer.type" - // FlagRemoteSignerPath is a flag for specifying the remote signer path - FlagRemoteSignerPath = "remote_signer.path" + // FlagSignerType is a flag for specifying the signer type + FlagSignerType = "signer.type" + // FlagSignerPath is a flag for specifying the signer path + FlagSignerPath = "signer.path" - // FlagRemoteSignerPassphrase is a flag for specifying the remote signer passphrase + // FlagSignerPassphrase is a flag for specifying the signer passphrase //nolint:gosec - FlagRemoteSignerPassphrase = "remote_signer.passphrase" + FlagSignerPassphrase = "signer.passphrase" // RPC configuration flags @@ -165,7 +165,7 @@ type Config struct { Log LogConfig `mapstructure:"log" yaml:"log"` // Remote signer configuration - RemoteSigner RemoteSignerConfig `mapstructure:"remote_signer" yaml:"remote_signer"` + Signer SignerConfig `mapstructure:"signer" yaml:"signer"` } // DAConfig contains all Data Availability configuration parameters @@ -217,8 +217,8 @@ type P2PConfig struct { AllowedPeers string `mapstructure:"allowed_peers" yaml:"allowed_peers" comment:"Comma separated list of peer IDs to allow connections from"` } -// RemoteSignerConfig contains all remote signer configuration parameters -type RemoteSignerConfig struct { +// SignerConfig contains all signer configuration parameters +type SignerConfig struct { SignerType string `mapstructure:"signer_type" yaml:"signer_type" comment:"Type of remote signer to use (file, grpc)"` SignerPath string `mapstructure:"signer_path" yaml:"signer_path" comment:"Path to the signer file or address"` } @@ -286,10 +286,10 @@ func AddFlags(cmd *cobra.Command) { cmd.Flags().String(FlagLogFormat, "", "log format (text, json)") cmd.Flags().Bool(FlagLogTrace, false, "enable stack traces in error logs") - // Remote signer configuration flags - cmd.Flags().String(FlagRemoteSignerType, def.RemoteSigner.SignerType, "type of remote signer to use (file, grpc)") - cmd.Flags().String(FlagRemoteSignerPath, def.RemoteSigner.SignerPath, "path to the signer file or address") - cmd.Flags().String(FlagRemoteSignerPassphrase, "", "passphrase for the remote signer") + // Signer configuration flags + cmd.Flags().String(FlagSignerType, def.Signer.SignerType, "type of signer to use (file, grpc)") + cmd.Flags().String(FlagSignerPath, def.Signer.SignerPath, "path to the signer file or address") + cmd.Flags().String(FlagSignerPassphrase, "", "passphrase for the signer") } // LoadNodeConfig loads the node configuration in the following order of precedence: diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 1609c6e62e..8e2c8daea5 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -75,7 +75,7 @@ var DefaultNodeConfig = Config{ Format: "", Trace: false, }, - RemoteSigner: RemoteSignerConfig{ + Signer: SignerConfig{ SignerType: "file", SignerPath: "", }, From 342744d3454dc7c92df2a6e745fdc3da2bb91535 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 11:10:59 +0200 Subject: [PATCH 14/29] fix suthelper --- test/e2e/sut_helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/sut_helper.go b/test/e2e/sut_helper.go index b775a2d7be..9760cea3d7 100644 --- a/test/e2e/sut_helper.go +++ b/test/e2e/sut_helper.go @@ -76,7 +76,7 @@ func (s *SystemUnderTest) AwaitNodeUp(t *testing.T, rpcAddr string, timeout time go func() { // query for a non empty block on status page t.Logf("Checking node status: %s\n", rpcAddr) for { - con, err := rpchttp.New(rpcAddr, "/websocket") + con, err := rpchttp.New(rpcAddr) if err != nil || con.Start() != nil { time.Sleep(100 * time.Millisecond) continue From c1fff12e6123fac81275d51f2c680eebe9be34f2 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 16:57:41 +0200 Subject: [PATCH 15/29] cleanup --- node/full.go | 4 +- node/full_node_integration_test.go | 14 ++++++ node/helpers_test.go | 6 +++ node/light.go | 4 +- node/node.go | 5 ++- node/node_integration_test.go | 6 +++ node/node_test.go | 6 +++ pkg/cmd/init.go | 21 ++++++++- pkg/cmd/run_node.go | 70 ++++-------------------------- pkg/cmd/run_node_test.go | 49 --------------------- pkg/config/yaml.go | 2 +- pkg/p2p/client.go | 16 +++---- pkg/p2p/client_test.go | 10 ++++- pkg/p2p/utils_test.go | 5 +++ 14 files changed, 92 insertions(+), 126 deletions(-) diff --git a/node/full.go b/node/full.go index 420b0b8c54..f31c9b9a23 100644 --- a/node/full.go +++ b/node/full.go @@ -23,6 +23,7 @@ import ( "github.com/rollkit/rollkit/pkg/config" genesispkg "github.com/rollkit/rollkit/pkg/genesis" "github.com/rollkit/rollkit/pkg/p2p" + "github.com/rollkit/rollkit/pkg/p2p/key" rpcserver "github.com/rollkit/rollkit/pkg/rpc/server" "github.com/rollkit/rollkit/pkg/service" "github.com/rollkit/rollkit/pkg/signer" @@ -69,6 +70,7 @@ func newFullNode( ctx context.Context, nodeConfig config.Config, signer signer.Signer, + nodeKey key.NodeKey, genesis genesispkg.Genesis, exec coreexecutor.Executor, sequencer coresequencer.Sequencer, @@ -83,7 +85,7 @@ func newFullNode( return nil, err } - p2pClient, err := p2p.NewClient(nodeConfig, genesis.ChainID, baseKV, logger.With("module", "p2p"), p2pMetrics) + p2pClient, err := p2p.NewClient(nodeConfig, genesis.ChainID, baseKV, logger.With("module", "p2p"), p2pMetrics, nodeKey) if err != nil { return nil, err } diff --git a/node/full_node_integration_test.go b/node/full_node_integration_test.go index c3c33e62d9..e81ad3126f 100644 --- a/node/full_node_integration_test.go +++ b/node/full_node_integration_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "path/filepath" "sync" "testing" "time" @@ -17,6 +18,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" + "github.com/rollkit/rollkit/pkg/p2p/key" remote_signer "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/types" ) @@ -74,6 +76,9 @@ func (s *FullNodeTestSuite) SetupTest() { err = InitFiles(config.RootDir) require.NoError(s.T(), err) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(config.RootDir, "node_key.json")) + require.NoError(s.T(), err) + node, err := NewNode( s.ctx, config, @@ -81,6 +86,7 @@ func (s *FullNodeTestSuite) SetupTest() { dummySequencer, dummyClient, remoteSigner, + *nodeKey, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(s.T()), @@ -320,6 +326,9 @@ func (s *FullNodeTestSuite) TestMaxPending() { remoteSigner, err := remote_signer.NewNoopSigner(genesisValidatorKey) require.NoError(err) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(config.RootDir, "config", "node_key.json")) + require.NoError(err) + dummyExec := coreexecutor.NewDummyExecutor() dummySequencer := coresequencer.NewDummySequencer() dummyDA := coreda.NewDummyDA(100_000, 0, 0) @@ -335,6 +344,7 @@ func (s *FullNodeTestSuite) TestMaxPending() { dummySequencer, dummyClient, remoteSigner, + *nodeKey, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(s.T()), @@ -411,6 +421,9 @@ func (s *FullNodeTestSuite) TestStateRecovery() { dummyDA := coreda.NewDummyDA(100_000, 0, 0) dummyClient := coreda.NewDummyClient(dummyDA, []byte(MockDANamespace)) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(config.RootDir, "config", "node_key.json")) + require.NoError(err) + node, err := NewNode( s.ctx, config, @@ -418,6 +431,7 @@ func (s *FullNodeTestSuite) TestStateRecovery() { dummySequencer, dummyClient, remoteSigner, + *nodeKey, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(s.T()), diff --git a/node/helpers_test.go b/node/helpers_test.go index b2b4b1db97..95d6c9e168 100644 --- a/node/helpers_test.go +++ b/node/helpers_test.go @@ -3,6 +3,7 @@ package node import ( "context" "fmt" + "path/filepath" "testing" "time" @@ -13,6 +14,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" + "github.com/rollkit/rollkit/pkg/p2p/key" remote_signer "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/types" ) @@ -57,6 +59,9 @@ func setupTestNodeWithCleanup(t *testing.T) (*FullNode, func()) { err = InitFiles(config.RootDir) require.NoError(t, err) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(config.RootDir, "node_key.json")) + require.NoError(t, err) + node, err := NewNode( ctx, config, @@ -64,6 +69,7 @@ func setupTestNodeWithCleanup(t *testing.T) (*FullNode, func()) { dummySequencer, dummyClient, remoteSigner, + *nodeKey, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(t), diff --git a/node/light.go b/node/light.go index e618998a50..2b92024e40 100644 --- a/node/light.go +++ b/node/light.go @@ -13,6 +13,7 @@ import ( "github.com/rollkit/rollkit/pkg/config" "github.com/rollkit/rollkit/pkg/genesis" "github.com/rollkit/rollkit/pkg/p2p" + "github.com/rollkit/rollkit/pkg/p2p/key" rpcserver "github.com/rollkit/rollkit/pkg/rpc/server" "github.com/rollkit/rollkit/pkg/service" "github.com/rollkit/rollkit/pkg/store" @@ -37,6 +38,7 @@ func newLightNode( conf config.Config, genesis genesis.Genesis, metricsProvider MetricsProvider, + nodeKey key.NodeKey, logger log.Logger, ) (ln *LightNode, err error) { @@ -46,7 +48,7 @@ func newLightNode( if err != nil { return nil, err } - client, err := p2p.NewClient(conf, genesis.ChainID, datastore, logger.With("module", "p2p"), p2pMetrics) + client, err := p2p.NewClient(conf, genesis.ChainID, datastore, logger.With("module", "p2p"), p2pMetrics, nodeKey) if err != nil { return nil, err } diff --git a/node/node.go b/node/node.go index 1a654b0a76..7921d48360 100644 --- a/node/node.go +++ b/node/node.go @@ -10,6 +10,7 @@ import ( coresequencer "github.com/rollkit/rollkit/core/sequencer" "github.com/rollkit/rollkit/pkg/config" "github.com/rollkit/rollkit/pkg/genesis" + "github.com/rollkit/rollkit/pkg/p2p/key" "github.com/rollkit/rollkit/pkg/service" "github.com/rollkit/rollkit/pkg/signer" ) @@ -31,18 +32,20 @@ func NewNode( sequencer coresequencer.Sequencer, dac coreda.Client, signer signer.Signer, + nodeKey key.NodeKey, genesis genesis.Genesis, metricsProvider MetricsProvider, logger log.Logger, ) (Node, error) { if conf.Node.Light { - return newLightNode(conf, genesis, metricsProvider, logger) + return newLightNode(conf, genesis, metricsProvider, nodeKey, logger) } return newFullNode( ctx, conf, signer, + nodeKey, genesis, exec, sequencer, diff --git a/node/node_integration_test.go b/node/node_integration_test.go index 7b3e2e0c91..a19f1be46c 100644 --- a/node/node_integration_test.go +++ b/node/node_integration_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "path/filepath" "sync" "testing" "time" @@ -18,6 +19,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" + "github.com/rollkit/rollkit/pkg/p2p/key" remote_signer "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/types" ) @@ -59,6 +61,9 @@ func (s *NodeIntegrationTestSuite) SetupTest() { err = InitFiles(config.RootDir) require.NoError(s.T(), err) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(config.RootDir, "config", "node_key.json")) + require.NoError(s.T(), err) + node, err := NewNode( s.ctx, config, @@ -66,6 +71,7 @@ func (s *NodeIntegrationTestSuite) SetupTest() { dummySequencer, dummyClient, remoteSigner, + *nodeKey, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), log.NewTestLogger(s.T()), diff --git a/node/node_test.go b/node/node_test.go index 8eefb876d9..668871cf81 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "net" + "path/filepath" "sync" "testing" "time" @@ -20,6 +21,7 @@ import ( coreexecutor "github.com/rollkit/rollkit/core/execution" coresequencer "github.com/rollkit/rollkit/core/sequencer" rollkitconfig "github.com/rollkit/rollkit/pkg/config" + "github.com/rollkit/rollkit/pkg/p2p/key" remote_signer "github.com/rollkit/rollkit/pkg/signer/noop" "github.com/rollkit/rollkit/types" ) @@ -191,6 +193,9 @@ func newTestNode(ctx context.Context, t *testing.T, nodeType NodeType, chainID s err = InitFiles(config.RootDir) require.NoError(t, err) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(config.RootDir, "config", "node_key.json")) + require.NoError(t, err) + logger := log.NewTestLogger(t) node, err := NewNode( @@ -200,6 +205,7 @@ func newTestNode(ctx context.Context, t *testing.T, nodeType NodeType, chainID s dummySequencer, dummyClient, remoteSigner, + *nodeKey, genesis, DefaultMetricsProvider(rollkitconfig.DefaultInstrumentationConfig()), logger, diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go index 4043aa0c4e..e5613820de 100644 --- a/pkg/cmd/init.go +++ b/pkg/cmd/init.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" rollconf "github.com/rollkit/rollkit/pkg/config" + "github.com/rollkit/rollkit/pkg/p2p/key" "github.com/rollkit/rollkit/pkg/signer/file" ) @@ -45,8 +46,17 @@ var InitCmd = &cobra.Command{ return fmt.Errorf("error creating directory %s: %w", homePath, err) } + aggregator, err := cmd.Flags().GetBool(rollconf.FlagAggregator) + if err != nil { + return fmt.Errorf("error reading aggregator flag: %w", err) + } + + if aggregator { + config.Node.Aggregator = true + } + // If using local file signer, initialize the key - if config.Signer.SignerType == "file" && config.Node.Aggregator { + if config.Signer.SignerType == "file" && aggregator { // Get passphrase if local signing is enabled passphrase, err := cmd.Flags().GetString(rollconf.FlagSignerPassphrase) if err != nil { @@ -64,7 +74,7 @@ var InitCmd = &cobra.Command{ } // Set signer path - config.Signer.SignerPath = filepath.Join(signerDir, "key.json") + config.Signer.SignerPath = filepath.Join(signerDir, "priv_key.json") // Initialize the signer _, err = file.NewFileSystemSigner(config.Signer.SignerPath, []byte(passphrase)) @@ -78,6 +88,12 @@ var InitCmd = &cobra.Command{ return fmt.Errorf("error writing rollkit.yaml file: %w", err) } + nodeKeyFile := filepath.Join(homePath, "config", "node_key.json") + _, err = key.LoadOrGenNodeKey(nodeKeyFile) + if err != nil { + return fmt.Errorf("failed to create node key: %w", err) + } + fmt.Printf("Initialized %s file in %s\n", rollconf.RollkitConfigYaml, homePath) return nil }, @@ -86,4 +102,5 @@ var InitCmd = &cobra.Command{ func init() { // Add passphrase flag InitCmd.Flags().String(rollconf.FlagSignerPassphrase, "", "Passphrase for encrypting the local signer key (required when using local file signer)") + InitCmd.Flags().Bool(rollconf.FlagAggregator, false, "Run node in aggregator mode") } diff --git a/pkg/cmd/run_node.go b/pkg/cmd/run_node.go index b3fae34240..cbee7a5345 100644 --- a/pkg/cmd/run_node.go +++ b/pkg/cmd/run_node.go @@ -2,7 +2,6 @@ package cmd import ( "context" - "encoding/json" "errors" "fmt" "os" @@ -21,7 +20,7 @@ import ( "github.com/rollkit/rollkit/node" rollconf "github.com/rollkit/rollkit/pkg/config" genesispkg "github.com/rollkit/rollkit/pkg/genesis" - rollos "github.com/rollkit/rollkit/pkg/os" + "github.com/rollkit/rollkit/pkg/p2p/key" "github.com/rollkit/rollkit/pkg/signer" "github.com/rollkit/rollkit/pkg/signer/file" ) @@ -115,16 +114,6 @@ func NewRunNodeCmd( Use: "start", Aliases: []string{"node", "run"}, Short: "Run the rollkit node", - // PersistentPreRunE is used to parse the config and initial the config files - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - if err := parseConfig(cmd); err != nil { - return err - } - - logger = setupLogger(nodeConfig.Log) - - return initConfigFiles() - }, RunE: func(cmd *cobra.Command, args []string) error { return startNode(cmd, executor, sequencer, dac) }, @@ -136,52 +125,6 @@ func NewRunNodeCmd( return cmd } -// initConfigFiles initializes the config and data directories -func initConfigFiles() error { - // Create config and data directories using nodeConfig values - configDir := filepath.Join(nodeConfig.RootDir, nodeConfig.ConfigDir) - dataDir := filepath.Join(nodeConfig.RootDir, nodeConfig.DBPath) - - if err := os.MkdirAll(configDir, rollconf.DefaultDirPerm); err != nil { - return fmt.Errorf("failed to create config directory: %w", err) - } - - if err := os.MkdirAll(dataDir, rollconf.DefaultDirPerm); err != nil { - return fmt.Errorf("failed to create data directory: %w", err) - } - - //todo: generate keys - - // Generate the genesis file - genFile := filepath.Join(configDir, "genesis.json") - if rollos.FileExists(genFile) { - logger.Info("Found genesis file", "path", genFile) - } else { - // Create a default genesis - genesis := genesispkg.NewGenesis( - "test-chain", - uint64(1), - time.Now(), - genesispkg.GenesisExtraData{}, // No proposer address for now - nil, // No raw bytes for now - ) - - // Marshal the genesis struct directly - genesisBytes, err := json.MarshalIndent(genesis, "", " ") - if err != nil { - return fmt.Errorf("failed to marshal genesis: %w", err) - } - - // Write genesis bytes directly to file - if err := os.WriteFile(genFile, genesisBytes, 0600); err != nil { - return fmt.Errorf("failed to write genesis file: %w", err) - } - logger.Info("Generated genesis file", "path", genFile) - } - - return nil -} - // startNode handles the node startup logic func startNode(cmd *cobra.Command, executor coreexecutor.Executor, sequencer coresequencer.Sequencer, dac coreda.Client) error { ctx, cancel := context.WithCancel(cmd.Context()) @@ -191,10 +134,6 @@ func startNode(cmd *cobra.Command, executor coreexecutor.Executor, sequencer cor return fmt.Errorf("failed to parse config: %w", err) } - if err := initConfigFiles(); err != nil { - return fmt.Errorf("failed to initialize files: %w", err) - } - //create a new remote signer var signer signer.Signer if nodeConfig.Signer.SignerType == "file" { @@ -213,6 +152,12 @@ func startNode(cmd *cobra.Command, executor coreexecutor.Executor, sequencer cor return fmt.Errorf("unknown remote signer type: %s", nodeConfig.Signer.SignerType) } + nodeKeyFile := filepath.Join(nodeConfig.RootDir, "config", "node_key.json") + nodeKey, err := key.LoadOrGenNodeKey(nodeKeyFile) + if err != nil { + return fmt.Errorf("failed to load node key: %w", err) + } + metrics := node.DefaultMetricsProvider(rollconf.DefaultInstrumentationConfig()) genesisPath := filepath.Join(nodeConfig.RootDir, nodeConfig.ConfigDir, "genesis.json") @@ -229,6 +174,7 @@ func startNode(cmd *cobra.Command, executor coreexecutor.Executor, sequencer cor sequencer, dac, signer, + *nodeKey, genesis, metrics, logger, diff --git a/pkg/cmd/run_node_test.go b/pkg/cmd/run_node_test.go index 352d061e65..60c20e53a8 100644 --- a/pkg/cmd/run_node_test.go +++ b/pkg/cmd/run_node_test.go @@ -3,7 +3,6 @@ package cmd import ( "context" "os" - "path/filepath" "reflect" "testing" "time" @@ -225,51 +224,3 @@ func TestCentralizedAddresses(t *testing.T) { t.Error("Expected flag \"rollkit.sequencer_rollup_id\" to be marked as changed") } } - -func TestInitFiles(t *testing.T) { - // Save the original nodeConfig - origNodeConfig := nodeConfig - - // Create a temporary directory for the test - tempDir, err := os.MkdirTemp("", "rollkit-test") - assert.NoError(t, err) - defer func() { - err := os.RemoveAll(tempDir) - assert.NoError(t, err) - }() - - // Create the necessary subdirectories - configDir := filepath.Join(tempDir, "config") - dataDir := filepath.Join(tempDir, "data") - err = os.MkdirAll(configDir, rollconf.DefaultDirPerm) - assert.NoError(t, err) - err = os.MkdirAll(dataDir, rollconf.DefaultDirPerm) - assert.NoError(t, err) - - // Set the nodeConfig to use the temporary directory - nodeConfig = rollconf.Config{ - RootDir: tempDir, - ConfigDir: "config", - DBPath: "data", - } - - // Restore the original nodeConfig when the test completes - defer func() { - nodeConfig = origNodeConfig - }() - - // Call initFiles - err = initConfigFiles() - assert.NoError(t, err) - - // Verify that the expected files were created - files := []string{ - filepath.Join(tempDir, "config", "priv_validator_key.json"), - filepath.Join(tempDir, "data", "priv_validator_state.json"), - filepath.Join(tempDir, "config", "genesis.json"), - } - - for _, file := range files { - assert.FileExists(t, file) - } -} diff --git a/pkg/config/yaml.go b/pkg/config/yaml.go index 3bb5dccc4b..5d9696fe28 100644 --- a/pkg/config/yaml.go +++ b/pkg/config/yaml.go @@ -124,7 +124,7 @@ func findConfigFile(startDir string) (string, error) { // It ensures the directory exists and writes the configuration with proper permissions. func WriteYamlConfig(config Config) error { // Configure the output file - configPath := filepath.Join(config.RootDir, RollkitConfigYaml) + configPath := filepath.Join(config.RootDir, "config", RollkitConfigYaml) // Ensure the directory exists if err := os.MkdirAll(filepath.Dir(configPath), DefaultDirPerm); err != nil { diff --git a/pkg/p2p/client.go b/pkg/p2p/client.go index dbd573977e..45df0e055e 100644 --- a/pkg/p2p/client.go +++ b/pkg/p2p/client.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "errors" "fmt" - "path/filepath" "strings" "time" @@ -64,7 +63,14 @@ type Client struct { // // Basic checks on parameters are done, and default parameters are provided for unset-configuration // TODO(tzdybal): consider passing entire config, not just P2P config, to reduce number of arguments -func NewClient(conf config.Config, chainID string, ds datastore.Datastore, logger log.Logger, metrics *Metrics) (*Client, error) { +func NewClient( + conf config.Config, + chainID string, + ds datastore.Datastore, + logger log.Logger, + metrics *Metrics, + nodeKey key.NodeKey, +) (*Client, error) { if conf.RootDir == "" { return nil, fmt.Errorf("rootDir is required") } @@ -78,12 +84,6 @@ func NewClient(conf config.Config, chainID string, ds datastore.Datastore, logge return nil, fmt.Errorf("failed to create connection gater: %w", err) } - nodeKeyFile := filepath.Join(conf.RootDir, "config", "node_key.json") - nodeKey, err := key.LoadOrGenNodeKey(nodeKeyFile) - if err != nil { - return nil, err - } - return &Client{ conf: conf.P2P, gater: gater, diff --git a/pkg/p2p/client_test.go b/pkg/p2p/client_test.go index a054df5e36..7cee013e0c 100644 --- a/pkg/p2p/client_test.go +++ b/pkg/p2p/client_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/rollkit/rollkit/pkg/config" + "github.com/rollkit/rollkit/pkg/p2p/key" ) func TestClientStartup(t *testing.T) { @@ -57,8 +58,11 @@ func TestClientStartup(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.desc, func(t *testing.T) { + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(testCase.conf.RootDir, "config", "node_key.json")) + require.NoError(t, err) + client, err := NewClient(testCase.conf, "TestChain", - dssync.MutexWrap(datastore.NewMapDatastore()), log.NewTestLogger(t), NopMetrics()) + dssync.MutexWrap(datastore.NewMapDatastore()), log.NewTestLogger(t), NopMetrics(), *nodeKey) assert.NoError(err) assert.NotNil(client) @@ -157,12 +161,16 @@ func TestSeedStringParsing(t *testing.T) { tempDir := t.TempDir() ClientInitFiles(t, tempDir) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(tempDir, "config", "node_key.json")) + require.NoError(err) + client, err := NewClient( config.Config{RootDir: tempDir}, "TestNetwork", dssync.MutexWrap(datastore.NewMapDatastore()), logger, NopMetrics(), + *nodeKey, ) require.NoError(err) require.NotNil(client) diff --git a/pkg/p2p/utils_test.go b/pkg/p2p/utils_test.go index 94ea151330..aaf1bda265 100644 --- a/pkg/p2p/utils_test.go +++ b/pkg/p2p/utils_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/rollkit/rollkit/pkg/config" + "github.com/rollkit/rollkit/pkg/p2p/key" ) type testNet []*Client @@ -108,6 +109,9 @@ func startTestNetwork(ctx context.Context, t *testing.T, n int, conf map[int]hos for i := 0; i < n; i++ { tempDir := filepath.Join(t.TempDir(), fmt.Sprintf("client_%d", i)) ClientInitFiles(t, tempDir) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(tempDir, "config", "node_key.json")) + require.NoError(err) + client, err := NewClient( config.Config{ RootDir: tempDir, @@ -119,6 +123,7 @@ func startTestNetwork(ctx context.Context, t *testing.T, n int, conf map[int]hos sync.MutexWrap(datastore.NewMapDatastore()), logger, NopMetrics(), + *nodeKey, ) require.NoError(err) require.NotNil(client) From 373ee816d4a9e44cce5b71de27b3dc37309d3949 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 17:00:07 +0200 Subject: [PATCH 16/29] fix test --- node/full_node_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/full_node_integration_test.go b/node/full_node_integration_test.go index e81ad3126f..318b6f38a3 100644 --- a/node/full_node_integration_test.go +++ b/node/full_node_integration_test.go @@ -76,7 +76,7 @@ func (s *FullNodeTestSuite) SetupTest() { err = InitFiles(config.RootDir) require.NoError(s.T(), err) - nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(config.RootDir, "node_key.json")) + nodeKey, err := key.LoadOrGenNodeKey(filepath.Join(config.RootDir, "config", "node_key.json")) require.NoError(s.T(), err) node, err := NewNode( From 318345f6c5e67c614997538aecdb8fb503392e23 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 17:03:14 +0200 Subject: [PATCH 17/29] minor fix --- pkg/cmd/init.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go index e5613820de..847c911501 100644 --- a/pkg/cmd/init.go +++ b/pkg/cmd/init.go @@ -46,16 +46,18 @@ var InitCmd = &cobra.Command{ return fmt.Errorf("error creating directory %s: %w", homePath, err) } + // we check if the aggregator flag is set aggregator, err := cmd.Flags().GetBool(rollconf.FlagAggregator) if err != nil { return fmt.Errorf("error reading aggregator flag: %w", err) } + // if the aggregator flag is set, we set the aggregator to true if aggregator { config.Node.Aggregator = true } - // If using local file signer, initialize the key + // If using local file signer and aggregator is enabled, initialize the key if config.Signer.SignerType == "file" && aggregator { // Get passphrase if local signing is enabled passphrase, err := cmd.Flags().GetString(rollconf.FlagSignerPassphrase) From 27e0ca854af4a65a8c7f471b1f97eccc546b54db Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 17:09:43 +0200 Subject: [PATCH 18/29] use setuplogger --- pkg/cmd/run_node.go | 23 +++++++++++------------ pkg/cmd/run_node_test.go | 16 ++++++++++------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/pkg/cmd/run_node.go b/pkg/cmd/run_node.go index cbee7a5345..84dd71af69 100644 --- a/pkg/cmd/run_node.go +++ b/pkg/cmd/run_node.go @@ -26,38 +26,35 @@ import ( ) var ( - // initialize the rollkit node configuration - nodeConfig = rollconf.DefaultNodeConfig +// initialize the rollkit node configuration - // initialize the logger with the cometBFT defaults - logger = log.NewLogger(os.Stdout) ) -func parseConfig(cmd *cobra.Command) error { +func parseConfig(cmd *cobra.Command) (rollconf.Config, error) { // Load configuration with the correct order of precedence: // DefaultNodeConfig -> Yaml -> Flags var err error - nodeConfig, err = rollconf.LoadNodeConfig(cmd) + nodeConfig, err := rollconf.LoadNodeConfig(cmd) if err != nil { - return fmt.Errorf("failed to load node config: %w", err) + return rollconf.Config{}, fmt.Errorf("failed to load node config: %w", err) } // Validate the root directory if err := rollconf.EnsureRoot(nodeConfig.RootDir); err != nil { - return fmt.Errorf("failed to ensure root directory: %w", err) + return rollconf.Config{}, fmt.Errorf("failed to ensure root directory: %w", err) } - return nil + return nodeConfig, nil } -// setupLogger configures and returns a logger based on the provided configuration. +// SetupLogger configures and returns a logger based on the provided configuration. // It applies the following settings from the config: // - Log format (text or JSON) // - Log level (debug, info, warn, error) // - Stack traces for error logs // // The returned logger is already configured with the "module" field set to "main". -func setupLogger(config rollconf.LogConfig) log.Logger { +func SetupLogger(config rollconf.LogConfig) log.Logger { var logOptions []log.Option // Configure logger format @@ -130,9 +127,11 @@ func startNode(cmd *cobra.Command, executor coreexecutor.Executor, sequencer cor ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() - if err := parseConfig(cmd); err != nil { + nodeConfig, err := parseConfig(cmd) + if err != nil { return fmt.Errorf("failed to parse config: %w", err) } + logger := SetupLogger(nodeConfig.Log) //create a new remote signer var signer signer.Signer diff --git a/pkg/cmd/run_node_test.go b/pkg/cmd/run_node_test.go index 60c20e53a8..f3494dc360 100644 --- a/pkg/cmd/run_node_test.go +++ b/pkg/cmd/run_node_test.go @@ -30,7 +30,7 @@ func createTestComponents(ctx context.Context) (coreexecutor.Executor, coreseque func TestParseFlags(t *testing.T) { // Initialize nodeConfig with default values to avoid issues with instrument - nodeConfig = rollconf.DefaultNodeConfig + nodeConfig := rollconf.DefaultNodeConfig flags := []string{ "--home", "custom/root/dir", @@ -82,7 +82,8 @@ func TestParseFlags(t *testing.T) { t.Errorf("Error: %v", err) } - if err := parseConfig(newRunNodeCmd); err != nil { + nodeConfig, err := parseConfig(newRunNodeCmd) + if err != nil { t.Errorf("Error: %v", err) } @@ -157,7 +158,8 @@ func TestAggregatorFlagInvariants(t *testing.T) { t.Errorf("Error: %v", err) } - if err := parseConfig(newRunNodeCmd); err != nil { + nodeConfig, err := parseConfig(newRunNodeCmd) + if err != nil { t.Errorf("Error: %v", err) } @@ -171,7 +173,7 @@ func TestAggregatorFlagInvariants(t *testing.T) { // when no flag is specified func TestDefaultAggregatorValue(t *testing.T) { // Reset nodeConfig to default values - nodeConfig = rollconf.DefaultNodeConfig + nodeConfig := rollconf.DefaultNodeConfig // Create a new command without specifying any flags args := []string{"start"} @@ -183,7 +185,8 @@ func TestDefaultAggregatorValue(t *testing.T) { t.Errorf("Error parsing flags: %v", err) } - if err := parseConfig(newRunNodeCmd); err != nil { + nodeConfig, err := parseConfig(newRunNodeCmd) + if err != nil { t.Errorf("Error parsing config: %v", err) } @@ -207,7 +210,8 @@ func TestCentralizedAddresses(t *testing.T) { if err := cmd.ParseFlags(args); err != nil { t.Fatalf("ParseFlags error: %v", err) } - if err := parseConfig(cmd); err != nil { + nodeConfig, err := parseConfig(cmd) + if err != nil { t.Fatalf("parseConfig error: %v", err) } From 262ee2a5a47d913551ebd7707281ec41ba6bd2c2 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 17:10:30 +0200 Subject: [PATCH 19/29] remove one todo --- node/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/node.go b/node/node.go index 7921d48360..e8024ffca2 100644 --- a/node/node.go +++ b/node/node.go @@ -24,7 +24,7 @@ type Node interface { // NewNode returns a new Full or Light Node based on the config // This is the entry point for composing a node, when compiling a node, you need to provide an executor -// Example executors can be found: TODO: add link +// Example executors can be found in rollups/ func NewNode( ctx context.Context, conf config.Config, From 569587f4b1b9e45841f9a04a0ecf6daa7b752639 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 17:23:20 +0200 Subject: [PATCH 20/29] cleanup --- pkg/cmd/init_test.go | 4 ++-- pkg/cmd/run_node_test.go | 2 +- pkg/config/config_test.go | 4 ++-- pkg/config/defaults.go | 2 +- pkg/config/yaml_test.go | 14 +++++++++----- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pkg/cmd/init_test.go b/pkg/cmd/init_test.go index d05b97e23e..67e0fa7150 100644 --- a/pkg/cmd/init_test.go +++ b/pkg/cmd/init_test.go @@ -27,7 +27,7 @@ func TestInitCommand(t *testing.T) { require.NoError(t, os.Chdir(dir)) // Remove any existing rollkit.yaml files in the test directory - configPath := filepath.Join(dir, rollconf.RollkitConfigYaml) + configPath := filepath.Join(dir, "config", rollconf.RollkitConfigYaml) _ = os.Remove(configPath) // Ignore error if file doesn't exist // Create a new test-specific command @@ -54,7 +54,7 @@ func TestInitCommand(t *testing.T) { require.NoError(t, err) // Verify the config can be read - _, err = rollconf.ReadYaml(dir) + _, err = rollconf.ReadYaml(filepath.Join(dir, "config")) require.NoError(t, err) // Read the file content directly to verify the YAML structure diff --git a/pkg/cmd/run_node_test.go b/pkg/cmd/run_node_test.go index f3494dc360..961b687bd2 100644 --- a/pkg/cmd/run_node_test.go +++ b/pkg/cmd/run_node_test.go @@ -191,7 +191,7 @@ func TestDefaultAggregatorValue(t *testing.T) { } // Verify that Aggregator is true by default - assert.True(t, nodeConfig.Node.Aggregator, "Expected Aggregator to be true by default") + assert.False(t, nodeConfig.Node.Aggregator, "Expected Aggregator to be false by default") } // TestCentralizedAddresses verifies that when centralized service flags are provided, diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index c4e66d8bbd..d84547bcfa 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -19,7 +19,7 @@ func TestDefaultNodeConfig(t *testing.T) { assert.Equal(t, DefaultRootDir(), def.RootDir) assert.Equal(t, "data", def.DBPath) - assert.Equal(t, true, def.Node.Aggregator) + assert.Equal(t, false, def.Node.Aggregator) assert.Equal(t, false, def.Node.Light) assert.Equal(t, DefaultDAAddress, def.DA.Address) assert.Equal(t, "", def.DA.AuthToken) @@ -97,7 +97,7 @@ func TestAddFlags(t *testing.T) { assertFlagValue(t, persistentFlags, FlagLogTrace, false) // Count the number of flags we're explicitly checking - expectedFlagCount := 41 // Update this number if you add more flag checks above + expectedFlagCount := 44 // Update this number if you add more flag checks above // Get the actual number of flags (both regular and persistent) actualFlagCount := 0 diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 4a587f2b44..af2724e161 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -35,7 +35,7 @@ const ( // DefaultRootDir returns the default root directory for rollkit func DefaultRootDir() string { - return DefaultRootDirWithName("rollkit") + return DefaultRootDirWithName(".rollkit") } // DefaultRootDirWithName returns the default root directory for an application, diff --git a/pkg/config/yaml_test.go b/pkg/config/yaml_test.go index 94b09ac5d6..a3dd6e33b6 100644 --- a/pkg/config/yaml_test.go +++ b/pkg/config/yaml_test.go @@ -55,7 +55,8 @@ func TestReadYaml(t *testing.T) { name: "sets RootDir even if empty yaml", setup: func(t *testing.T, dir string) error { // Create empty YAML file - return os.WriteFile(filepath.Join(dir, RollkitConfigYaml), []byte(""), 0600) + os.MkdirAll(filepath.Join(dir, "config"), 0755) + return os.WriteFile(filepath.Join(dir, "config", RollkitConfigYaml), []byte(""), 0600) }, validate: func(t *testing.T, cfg Config, err error) { require.NoError(t, err) @@ -66,7 +67,8 @@ func TestReadYaml(t *testing.T) { name: "returns error if config file cannot be decoded", setup: func(t *testing.T, dir string) error { // Create invalid YAML file - return os.WriteFile(filepath.Join(dir, RollkitConfigYaml), []byte("invalid: yaml: content"), 0600) + os.MkdirAll(filepath.Join(dir, "config"), 0755) + return os.WriteFile(filepath.Join(dir, "config", RollkitConfigYaml), []byte("invalid: yaml: content"), 0600) }, validate: func(t *testing.T, cfg Config, err error) { require.Error(t, err) @@ -85,7 +87,7 @@ func TestReadYaml(t *testing.T) { require.NoError(t, err) // Read the config - cfg, err := ReadYaml(tempDir) + cfg, err := ReadYaml(filepath.Join(tempDir, "config")) // Validate the result tc.validate(t, cfg, err) @@ -143,16 +145,18 @@ func TestYamlConfigOperations(t *testing.T) { // Create a temporary directory for each test case tempDir := t.TempDir() + path := filepath.Join(tempDir, "config") + // Setup the test case and write the initial config tc.setup(t, tempDir) // Verify the config file exists - configPath := filepath.Join(tempDir, RollkitConfigYaml) + configPath := filepath.Join(path, RollkitConfigYaml) _, err := os.Stat(configPath) require.NoError(t, err, "Config file should exist") // Read the config back - cfg, err := ReadYaml(tempDir) + cfg, err := ReadYaml(path) require.NoError(t, err) // Validate the config From ffa54c012766dfc03b721b5750d5b0f85ae7e3b4 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 17:25:59 +0200 Subject: [PATCH 21/29] fix lint --- pkg/config/yaml_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/config/yaml_test.go b/pkg/config/yaml_test.go index a3dd6e33b6..56e53eab6e 100644 --- a/pkg/config/yaml_test.go +++ b/pkg/config/yaml_test.go @@ -55,7 +55,8 @@ func TestReadYaml(t *testing.T) { name: "sets RootDir even if empty yaml", setup: func(t *testing.T, dir string) error { // Create empty YAML file - os.MkdirAll(filepath.Join(dir, "config"), 0755) + err := os.MkdirAll(filepath.Join(dir, "config"), 0755) + require.NoError(t, err) return os.WriteFile(filepath.Join(dir, "config", RollkitConfigYaml), []byte(""), 0600) }, validate: func(t *testing.T, cfg Config, err error) { @@ -67,7 +68,8 @@ func TestReadYaml(t *testing.T) { name: "returns error if config file cannot be decoded", setup: func(t *testing.T, dir string) error { // Create invalid YAML file - os.MkdirAll(filepath.Join(dir, "config"), 0755) + err := os.MkdirAll(filepath.Join(dir, "config"), 0755) + require.NoError(t, err) return os.WriteFile(filepath.Join(dir, "config", RollkitConfigYaml), []byte("invalid: yaml: content"), 0600) }, validate: func(t *testing.T, cfg Config, err error) { From 1c399dcf34a1b3169a148437adb44da1282989f8 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 18:20:33 +0200 Subject: [PATCH 22/29] start on e2e --- Makefile | 2 +- go.mod | 28 -------- go.sum | 76 --------------------- pkg/rpc/client/client.go | 16 ++--- pkg/rpc/client/client_test.go | 4 +- pkg/rpc/example/example.go | 2 +- sequencers/single/go.sum | 4 +- test/e2e/base_test.go | 123 +++++++++++++++------------------- test/e2e/sut_helper.go | 23 +++---- 9 files changed, 76 insertions(+), 202 deletions(-) diff --git a/Makefile b/Makefile index f36da4c38e..1315326e74 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,7 @@ test: vet ## test-e2e: Running e2e tests test-e2e: build @echo "--> Running e2e tests" - @go test -mod=readonly -failfast -timeout=15m -tags='e2e' ./test/e2e/... --binary=$(CURDIR)/build/rollkit + @go test -mod=readonly -failfast -timeout=15m -tags='e2e' ./test/e2e/... --binary=$(CURDIR)/build/testapp .PHONY: test-e2e ## proto-gen: Generate protobuf files. Requires docker. diff --git a/go.mod b/go.mod index 5258c38ce5..4884ecb1a3 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,6 @@ require ( cosmossdk.io/log v1.5.0 github.com/celestiaorg/go-header v0.6.4 github.com/celestiaorg/utils v0.1.0 - github.com/cometbft/cometbft v1.0.1 github.com/cosmos/gogoproto v1.7.0 github.com/go-kit/kit v0.13.0 github.com/goccy/go-yaml v1.16.0 @@ -41,7 +40,6 @@ require ( ) require ( - github.com/DataDog/zstd v1.4.5 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic v1.12.3 // indirect @@ -50,14 +48,6 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect - github.com/cockroachdb/errors v1.11.3 // indirect - github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect - github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v1.1.2 // indirect - github.com/cockroachdb/redact v1.1.5 // indirect - github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft-db v1.0.1 // indirect - github.com/cometbft/cometbft/api v1.0.0 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect @@ -72,18 +62,12 @@ require ( github.com/flynn/noise v1.1.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/getsentry/sentry-go v0.27.0 // indirect - github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/btree v1.1.3 // indirect github.com/google/flatbuffers v24.12.23+incompatible // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gopacket v1.1.19 // indirect @@ -106,12 +90,9 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect - github.com/jmhodges/levigo v1.0.0 // indirect github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/koron/go-ssdp v0.0.5 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.2.0 // indirect @@ -124,7 +105,6 @@ require ( github.com/libp2p/go-netroute v0.2.2 // indirect github.com/libp2p/go-reuseport v0.4.0 // indirect github.com/libp2p/go-yamux/v5 v5.0.0 // indirect - github.com/linxGnu/grocksdb v1.9.3 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -144,13 +124,11 @@ require ( github.com/multiformats/go-multistream v0.6.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae // indirect github.com/onsi/ginkgo/v2 v2.22.2 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pion/datachannel v1.5.10 // indirect github.com/pion/dtls/v2 v2.2.12 // indirect github.com/pion/dtls/v3 v3.0.4 // indirect @@ -180,24 +158,18 @@ require ( github.com/quic-go/quic-go v0.50.0 // indirect github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/supranational/blst v0.3.13 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect github.com/wlynxg/anet v0.0.5 // indirect - go.etcd.io/bbolt v1.3.11 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect diff --git a/go.sum b/go.sum index 49aff93f32..9b9c9976a7 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,6 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= -github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -85,10 +83,7 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= -github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= @@ -139,27 +134,7 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= -github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= -github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= -github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= -github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA= -github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= -github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= -github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v1.0.1 h1:JNVgbpL76sA4kXmBnyZ7iPjFAxi6HVp2l+rdT2RXVUs= -github.com/cometbft/cometbft v1.0.1/go.mod h1:r9fEwrbU6Oxs11I2bLsfAiG37OMn0Vip0w9arYU0Nw0= -github.com/cometbft/cometbft-db v1.0.1 h1:SylKuLseMLQKw3+i8y8KozZyJcQSL98qEe2CGMCGTYE= -github.com/cometbft/cometbft-db v1.0.1/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= -github.com/cometbft/cometbft/api v1.0.0 h1:gGBwvsJi/gnHJEtwYfjPIGs2AKg/Vfa1ZuKCPD1/Ko4= -github.com/cometbft/cometbft/api v1.0.0/go.mod h1:EkQiqVSu/p2ebrZEnB2z6Re7r8XNe//M7ylR0qEwWm0= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= @@ -183,7 +158,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -234,8 +208,6 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -248,13 +220,9 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= -github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -265,14 +233,10 @@ github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= -github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -332,12 +296,8 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= -github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/flatbuffers v24.12.23+incompatible h1:ubBKR94NR4pXUCY/MUsRVzd9umNW7ht7EG9hHfS9FX8= github.com/google/flatbuffers v24.12.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -361,8 +321,6 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= -github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -498,8 +456,6 @@ github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0 github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= -github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -551,8 +507,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-addr-util v0.1.0/go.mod h1:6I3ZYuFr2O/9D+SoyM0zEw0EF3YkldtTX406BpdQMqw= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= @@ -671,8 +625,6 @@ github.com/libp2p/go-yamux/v5 v5.0.0/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUK github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= -github.com/linxGnu/grocksdb v1.9.3/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= github.com/lucas-clemente/quic-go v0.27.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= @@ -723,8 +675,6 @@ github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKo github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= -github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= @@ -823,10 +773,6 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= -github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae h1:FatpGJD2jmJfhZiFDElaC0QhZUDQnxUeAwTGkfAHN3I= -github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= @@ -837,7 +783,6 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= @@ -873,12 +818,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= -github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= @@ -921,7 +862,6 @@ github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM= github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA= github.com/pion/webrtc/v4 v4.0.9 h1:PyOYMRKJgfy0dzPcYtFD/4oW9zaw3Ze3oZzzbj2LV9E= github.com/pion/webrtc/v4 v4.0.9/go.mod h1:ViHLVaNpiuvaH8pdiuQxuA9awuE6KVzAXx3vVWilOck= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -987,18 +927,13 @@ github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6R github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rollkit/go-sequencing v0.4.1 h1:P0x1wUFIAhdEeqUbrRAF343iExKhq9UkVOBbi45l750= github.com/rollkit/go-sequencing v0.4.1/go.mod h1:QnOk8mqyVgFWdMnjvZVBG4x8GC/TsRtoN5XdPZzfCSs= -github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= -github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -1012,8 +947,6 @@ github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgY github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= -github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= @@ -1105,11 +1038,7 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= -github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= @@ -1142,8 +1071,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= -go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1316,7 +1243,6 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1423,7 +1349,6 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1675,7 +1600,6 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= diff --git a/pkg/rpc/client/client.go b/pkg/rpc/client/client.go index 38145ea184..cfb3305d36 100644 --- a/pkg/rpc/client/client.go +++ b/pkg/rpc/client/client.go @@ -10,13 +10,13 @@ import ( rpc "github.com/rollkit/rollkit/types/pb/rollkit/v1/v1connect" ) -// StoreClient is the client for the StoreService -type StoreClient struct { +// Client is the client for the StoreService +type Client struct { client rpc.StoreServiceClient } // NewStoreClient creates a new StoreClient -func NewStoreClient(baseURL string) *StoreClient { +func NewClient(baseURL string) *Client { httpClient := http.DefaultClient client := rpc.NewStoreServiceClient( httpClient, @@ -24,13 +24,13 @@ func NewStoreClient(baseURL string) *StoreClient { connect.WithGRPC(), ) - return &StoreClient{ + return &Client{ client: client, } } // GetBlockByHeight returns a block by height -func (c *StoreClient) GetBlockByHeight(ctx context.Context, height uint64) (*pb.Block, error) { +func (c *Client) GetBlockByHeight(ctx context.Context, height uint64) (*pb.Block, error) { req := connect.NewRequest(&pb.GetBlockRequest{ Identifier: &pb.GetBlockRequest_Height{ Height: height, @@ -46,7 +46,7 @@ func (c *StoreClient) GetBlockByHeight(ctx context.Context, height uint64) (*pb. } // GetBlockByHash returns a block by hash -func (c *StoreClient) GetBlockByHash(ctx context.Context, hash []byte) (*pb.Block, error) { +func (c *Client) GetBlockByHash(ctx context.Context, hash []byte) (*pb.Block, error) { req := connect.NewRequest(&pb.GetBlockRequest{ Identifier: &pb.GetBlockRequest_Hash{ Hash: hash, @@ -62,7 +62,7 @@ func (c *StoreClient) GetBlockByHash(ctx context.Context, hash []byte) (*pb.Bloc } // GetState returns the current state -func (c *StoreClient) GetState(ctx context.Context) (*pb.State, error) { +func (c *Client) GetState(ctx context.Context) (*pb.State, error) { req := connect.NewRequest(&pb.GetStateRequest{}) resp, err := c.client.GetState(ctx, req) if err != nil { @@ -73,7 +73,7 @@ func (c *StoreClient) GetState(ctx context.Context) (*pb.State, error) { } // GetMetadata returns metadata for a specific key -func (c *StoreClient) GetMetadata(ctx context.Context, key string) ([]byte, error) { +func (c *Client) GetMetadata(ctx context.Context, key string) ([]byte, error) { req := connect.NewRequest(&pb.GetMetadataRequest{ Key: key, }) diff --git a/pkg/rpc/client/client_test.go b/pkg/rpc/client/client_test.go index fe1e3925b2..6f2e002a0a 100644 --- a/pkg/rpc/client/client_test.go +++ b/pkg/rpc/client/client_test.go @@ -19,7 +19,7 @@ import ( ) // setupTestServer creates a test server with a mock store -func setupTestServer(t *testing.T, mockStore *mocks.Store) (*httptest.Server, *StoreClient) { +func setupTestServer(t *testing.T, mockStore *mocks.Store) (*httptest.Server, *Client) { // Create a new HTTP test server mux := http.NewServeMux() @@ -34,7 +34,7 @@ func setupTestServer(t *testing.T, mockStore *mocks.Store) (*httptest.Server, *S testServer := httptest.NewServer(h2c.NewHandler(mux, &http2.Server{})) // Create a client that connects to the test server - client := NewStoreClient(testServer.URL) + client := NewClient(testServer.URL) return testServer, client } diff --git a/pkg/rpc/example/example.go b/pkg/rpc/example/example.go index 918ddeb3b2..97351f3673 100644 --- a/pkg/rpc/example/example.go +++ b/pkg/rpc/example/example.go @@ -41,7 +41,7 @@ func StartStoreServer(s store.Store, address string) { // ExampleClient demonstrates how to use the Store RPC client func ExampleClient() { // Create a new client - client := client.NewStoreClient("http://localhost:8080") + client := client.NewClient("http://localhost:8080") ctx := context.Background() // Get the current state diff --git a/sequencers/single/go.sum b/sequencers/single/go.sum index 89d14db2d1..1976192b64 100644 --- a/sequencers/single/go.sum +++ b/sequencers/single/go.sum @@ -40,8 +40,8 @@ github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= diff --git a/test/e2e/base_test.go b/test/e2e/base_test.go index d82287c0fa..6fb38d7d35 100644 --- a/test/e2e/base_test.go +++ b/test/e2e/base_test.go @@ -3,22 +3,16 @@ package e2e import ( - "context" "flag" - "fmt" "path/filepath" "testing" "time" - - "github.com/cometbft/cometbft/abci/example/kvstore" - rpchttp "github.com/cometbft/cometbft/rpc/client/http" - "github.com/stretchr/testify/require" ) var binaryPath string func init() { - flag.StringVar(&binaryPath, "binary", "rollkit", "rollkit binary") + flag.StringVar(&binaryPath, "binary", "testapp", "testapp binary") } func TestBasic(t *testing.T) { @@ -30,7 +24,7 @@ func TestBasic(t *testing.T) { var ( workDir = t.TempDir() node1Home = filepath.Join(workDir, "1") - node2Home = filepath.Join(workDir, "2") + // node2Home = filepath.Join(workDir, "2") ) // Define and parse the binary flag locally in the test function. @@ -39,78 +33,67 @@ func TestBasic(t *testing.T) { // start aggregator sut.StartNode(binaryPath, "start", - "--proxy_app=kvstore", "--home="+node1Home, - "--p2p.laddr=tcp://127.0.0.1:26656", - "--rpc.laddr=tcp://127.0.0.1:26657", - "--rollkit.sequencer_rollup_id=testing", - "--rollkit.aggregator", - "--rollkit.block_time=5ms", - "--rollkit.da_block_time=15ms", - "--rollkit.da_address=http://0.0.0.0:7980", - "--rollkit.sequencer_address=0.0.0.0:50051", + "--node.sequencer_rollup_id=testing", + "--node.aggregator", + "--node.block_time=5ms", + "--da.block_time=15ms", ) - sut.AwaitNodeUp(t, "tcp://127.0.0.1:26657", 2*time.Second) + sut.AwaitNodeUp(t, "tcp://127.0.0.1:7331", 2*time.Second) - // copy genesis to target home2 - MustCopyFile(t, filepath.Join(node1Home, "config", "genesis.json"), filepath.Join(node2Home, "config", "genesis.json")) - sut.StartNode( - binaryPath, - "start", - "--proxy_app=kvstore", - "--home="+node2Home, - "--p2p.laddr=tcp://127.0.0.1:16656", - "--rpc.laddr=tcp://127.0.0.1:16657", - "--rollkit.sequencer_rollup_id=testing", - fmt.Sprintf("--p2p.seeds=%s@127.0.0.1:26656", NodeID(t, node1Home)), - "--rollkit.aggregator=false", - "--rollkit.block_time=5ms", - "--rollkit.da_block_time=15ms", - "--rollkit.da_address=http://0.0.0.0:7980", - "--rollkit.sequencer_address=0.0.0.0:50051", - "--log_level=debug", - ) - sut.AwaitNodeUp(t, "tcp://127.0.0.1:16657", 2*time.Second) + // // copy genesis to target home2 + // MustCopyFile(t, filepath.Join(node1Home, "config", "genesis.json"), filepath.Join(node2Home, "config", "genesis.json")) + // sut.StartNode( + // binaryPath, + // "start", + // "--home="+node2Home, + // "--node.sequencer_rollup_id=testing", + // fmt.Sprintf("--p2p.seeds=%s@127.0.0.1:26656", NodeID(t, node1Home)), + // "--block_time=5ms", + // "--da_block_time=15ms", + // "--log_level=debug", + // ) + // sut.AwaitNodeUp(t, "tcp://127.0.0.1:16657", 2*time.Second) - asserNodeCaughtUp := func(c *rpchttp.HTTP) { - ctx, done := context.WithTimeout(context.Background(), time.Second) - defer done() - status, err := c.Status(ctx) - require.NoError(t, err) - require.False(t, status.SyncInfo.CatchingUp) - } - node1Client, err := rpchttp.New("tcp://localhost:26657", "tcp://localhost:26657"+"/websocket") - require.NoError(t, err) - asserNodeCaughtUp(node1Client) + // asserNodeCaughtUp := func(c *rpchttp.HTTP) { + // ctx, done := context.WithTimeout(context.Background(), time.Second) + // defer done() + // status, err := c.Status(ctx) + // require.NoError(t, err) + // require.False(t, status.SyncInfo.CatchingUp) + // } + // node1Client, err := rpchttp.New("tcp://localhost:26657", "tcp://localhost:26657"+"/websocket") + // require.NoError(t, err) + // asserNodeCaughtUp(node1Client) - node2Client, err := rpchttp.New("tcp://localhost:16657", "tcp://localhost:16657"+"/websocket") - require.NoError(t, err) - asserNodeCaughtUp(node2Client) + // node2Client, err := rpchttp.New("tcp://localhost:16657", "tcp://localhost:16657"+"/websocket") + // require.NoError(t, err) + // asserNodeCaughtUp(node2Client) // when a client TX for state update is executed - const myKey = "foo" - myValue := fmt.Sprintf("bar%d", time.Now().UnixNano()) - tx := kvstore.NewTx(myKey, myValue) + // const myKey = "foo" + // myValue := fmt.Sprintf("bar%d", time.Now().UnixNano()) + // tx := fmt.Sprintf("%s=%s", myKey, myValue) - ctx, done := context.WithTimeout(context.Background(), time.Second) - defer done() - result, err := node1Client.BroadcastTxCommit(ctx, tx) - require.NoError(t, err) - require.Equal(t, uint32(0), result.TxResult.Code, result.TxResult.Log) + // ctx, done := context.WithTimeout(context.Background(), time.Second) + // defer done() + // result, err := node1Client.BroadcastTxCommit(ctx, tx) + // require.NoError(t, err) + // require.Equal(t, uint32(0), result.TxResult.Code, result.TxResult.Log) // then state is persisted - ctx, done = context.WithTimeout(context.Background(), 150*time.Millisecond) - defer done() - resQuery, err := node1Client.ABCIQuery(ctx, "/store", []byte(myKey)) - require.NoError(t, err) - require.Equal(t, myValue, string(resQuery.Response.Value)) + // ctx, done = context.WithTimeout(context.Background(), 150*time.Millisecond) + // defer done() + // resQuery, err := node1Client.ABCIQuery(ctx, "/store", []byte(myKey)) + // require.NoError(t, err) + // require.Equal(t, myValue, string(resQuery.Response.Value)) // and state distributed to fullnode - require.Eventually(t, func() bool { - ctx, done := context.WithTimeout(context.Background(), 150*time.Millisecond) - defer done() - resQuery, err = node2Client.ABCIQuery(ctx, "/store", []byte(myKey)) - require.NoError(t, err) - return myValue == string(resQuery.Response.Value) - }, time.Second, 5*time.Millisecond) + // require.Eventually(t, func() bool { + // ctx, done := context.WithTimeout(context.Background(), 150*time.Millisecond) + // defer done() + // resQuery, err = node2Client.ABCIQuery(ctx, "/store", []byte(myKey)) + // require.NoError(t, err) + // return myValue == string(resQuery.Response.Value) + // }, time.Second, 5*time.Millisecond) } diff --git a/test/e2e/sut_helper.go b/test/e2e/sut_helper.go index 9760cea3d7..6542bb35ba 100644 --- a/test/e2e/sut_helper.go +++ b/test/e2e/sut_helper.go @@ -16,10 +16,9 @@ import ( "testing" "time" - "github.com/cometbft/cometbft/p2p" - rpchttp "github.com/cometbft/cometbft/rpc/client/http" - "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/peer" + "github.com/rollkit/rollkit/pkg/p2p/key" + "github.com/rollkit/rollkit/pkg/rpc/client" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -76,19 +75,17 @@ func (s *SystemUnderTest) AwaitNodeUp(t *testing.T, rpcAddr string, timeout time go func() { // query for a non empty block on status page t.Logf("Checking node status: %s\n", rpcAddr) for { - con, err := rpchttp.New(rpcAddr) - if err != nil || con.Start() != nil { + con := client.NewClient(rpcAddr) + if con == nil { time.Sleep(100 * time.Millisecond) continue } - result, err := con.Status(ctx) - if err != nil || result.SyncInfo.LatestBlockHeight < 1 { - _ = con.Stop() + result, err := con.GetState(ctx) + if err != nil || result.LastBlockHeight < 1 { time.Sleep(100 * time.Millisecond) continue } - t.Logf("Node started. Current block: %d\n", result.SyncInfo.LatestBlockHeight) - _ = con.Stop() + t.Logf("Node started. Current block: %d\n", result.LastBlockHeight) started <- struct{}{} return } @@ -256,11 +253,9 @@ func MustCopyFile(t *testing.T, src, dest string) *os.File { // NodeID generates and returns the peer ID from the node's private key. func NodeID(t *testing.T, nodeDir string) peer.ID { t.Helper() - node1Key, err := p2p.LoadOrGenNodeKey(filepath.Join(nodeDir, "config", "node_key.json")) + node1Key, err := key.LoadOrGenNodeKey(filepath.Join(nodeDir, "config", "node_key.json")) require.NoError(t, err) - p2pKey, err := crypto.UnmarshalEd25519PrivateKey(node1Key.PrivKey.Bytes()) - require.NoError(t, err) - node1ID, err := peer.IDFromPrivateKey(p2pKey) + node1ID, err := peer.IDFromPrivateKey(node1Key.PrivKey) require.NoError(t, err) return node1ID } From d4b16b652a68839ed4339ae08235d13328ca50d4 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 18:21:39 +0200 Subject: [PATCH 23/29] implement suggestiong from code rabbit --- pkg/signer/file/local.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/signer/file/local.go b/pkg/signer/file/local.go index 4a8049f42f..75bc6d874f 100644 --- a/pkg/signer/file/local.go +++ b/pkg/signer/file/local.go @@ -90,8 +90,8 @@ func generateAndSaveKeys(keyPath string, passphrase []byte) (*FileSystemSigner, // saveKeys encrypts and saves the private key to disk func (s *FileSystemSigner) saveKeys(passphrase []byte) error { - s.mu.RLock() - defer s.mu.RUnlock() + s.mu.Lock() + defer s.mu.Unlock() if s.privateKey == nil || s.publicKey == nil { return fmt.Errorf("keys not initialized") From 7de70c5aaf624b2e27891acbd127b00d3aae6333 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 18:25:14 +0200 Subject: [PATCH 24/29] add init --- test/e2e/base_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/e2e/base_test.go b/test/e2e/base_test.go index 6fb38d7d35..a666ee9fa4 100644 --- a/test/e2e/base_test.go +++ b/test/e2e/base_test.go @@ -30,12 +30,25 @@ func TestBasic(t *testing.T) { // Define and parse the binary flag locally in the test function. sut := NewSystemUnderTest(t) + aggregatorPass := "12345678" + // init aggregator + sut.StartNode(binaryPath, + "init", + "--home="+node1Home, + "--node.sequencer_rollup_id=testing", + "--node.aggregator", + "--node.block_time=5ms", + "--da.block_time=15ms", + "--node.aggrgator", + "--signer.passphrase="+aggregatorPass, + ) // start aggregator sut.StartNode(binaryPath, "start", "--home="+node1Home, "--node.sequencer_rollup_id=testing", "--node.aggregator", + "--signer.passphrase="+aggregatorPass, "--node.block_time=5ms", "--da.block_time=15ms", ) From 5fc1c070336b48fe865c67cc30aa0c32af70bda7 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 21:37:16 +0200 Subject: [PATCH 25/29] fix --- pkg/cmd/init.go | 173 +++++++++++++++------- pkg/config/config.go | 12 +- pkg/config/defaults.go | 6 +- pkg/genesis/genesis.go | 4 +- pkg/genesis/genesis_test.go | 6 - pkg/genesis/io_test.go | 6 - rollups/testapp/{commands => cmd}/root.go | 2 +- rollups/testapp/main.go | 2 +- test/e2e/base_test.go | 3 +- test/e2e/sut_helper.go | 10 ++ 10 files changed, 149 insertions(+), 75 deletions(-) rename rollups/testapp/{commands => cmd}/root.go (97%) diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go index 847c911501..7ba6224726 100644 --- a/pkg/cmd/init.go +++ b/pkg/cmd/init.go @@ -1,17 +1,101 @@ package cmd import ( + "encoding/json" "fmt" "os" "path/filepath" + "time" "github.com/spf13/cobra" rollconf "github.com/rollkit/rollkit/pkg/config" + genesispkg "github.com/rollkit/rollkit/pkg/genesis" "github.com/rollkit/rollkit/pkg/p2p/key" "github.com/rollkit/rollkit/pkg/signer/file" ) +// ValidateHomePath checks if the home path is valid and not already initialized +func ValidateHomePath(homePath string) error { + if homePath == "" { + return fmt.Errorf("home path is required") + } + + configFilePath := filepath.Join(homePath, rollconf.RollkitConfigYaml) + if _, err := os.Stat(configFilePath); err == nil { + return fmt.Errorf("%s file already exists in the specified directory", rollconf.RollkitConfigYaml) + } + + return nil +} + +// InitializeConfig creates and initializes the configuration with default values +func InitializeConfig(homePath string, aggregator bool) rollconf.Config { + config := rollconf.DefaultNodeConfig + config.ConfigDir = homePath + config.RootDir = homePath + config.Node.Aggregator = aggregator + return config +} + +// InitializeSigner sets up the signer configuration and creates necessary files +func InitializeSigner(config *rollconf.Config, homePath string, passphrase string) error { + if config.Signer.SignerType == "file" && config.Node.Aggregator { + if passphrase == "" { + return fmt.Errorf("passphrase is required when using local file signer") + } + + signerDir := filepath.Join(homePath, "config") + if err := os.MkdirAll(signerDir, rollconf.DefaultDirPerm); err != nil { + return fmt.Errorf("failed to create signer directory: %w", err) + } + + config.Signer.SignerPath = filepath.Join(signerDir, "priv_key.json") + + _, err := file.NewFileSystemSigner(config.Signer.SignerPath, []byte(passphrase)) + if err != nil { + return fmt.Errorf("failed to initialize signer: %w", err) + } + } + return nil +} + +// InitializeNodeKey creates the node key file +func InitializeNodeKey(homePath string) error { + nodeKeyFile := filepath.Join(homePath, "config", "node_key.json") + _, err := key.LoadOrGenNodeKey(nodeKeyFile) + if err != nil { + return fmt.Errorf("failed to create node key: %w", err) + } + return nil +} + +// InitializeGenesis creates and saves a genesis file with the given app state +func InitializeGenesis(homePath string, chainID string, initialHeight uint64, appState []byte) error { + // Create an empty genesis file + genesisData := genesispkg.NewGenesis( + chainID, + initialHeight, + time.Now(), // Current time as genesis DA start height + genesispkg.GenesisExtraData{}, + json.RawMessage(appState), // App state from parameters + ) + + // Create the config directory if it doesn't exist + configDir := filepath.Join(homePath, "config") + if err := os.MkdirAll(configDir, rollconf.DefaultDirPerm); err != nil { + return fmt.Errorf("error creating config directory: %w", err) + } + + // Save the genesis file + genesisPath := filepath.Join(configDir, "genesis.json") + if err := genesispkg.SaveGenesis(genesisData, genesisPath); err != nil { + return fmt.Errorf("error writing genesis file: %w", err) + } + + return nil +} + // InitCmd initializes a new rollkit.yaml file in the current directory var InitCmd = &cobra.Command{ Use: "init", @@ -23,77 +107,50 @@ var InitCmd = &cobra.Command{ return fmt.Errorf("error reading home flag: %w", err) } - if homePath == "" { - return fmt.Errorf("home path is required") - } - - configFilePath := filepath.Join(homePath, rollconf.RollkitConfigYaml) - if _, err := os.Stat(configFilePath); err == nil { - return fmt.Errorf("%s file already exists in the specified directory", rollconf.RollkitConfigYaml) + if err := ValidateHomePath(homePath); err != nil { + return err } - // Create a config with default values - config := rollconf.DefaultNodeConfig - - // Update with the values we found - config.ConfigDir = homePath - - // Set the root directory to the specified home path - config.RootDir = homePath - - // Make sure the home directory exists if err := os.MkdirAll(homePath, rollconf.DefaultDirPerm); err != nil { return fmt.Errorf("error creating directory %s: %w", homePath, err) } - // we check if the aggregator flag is set aggregator, err := cmd.Flags().GetBool(rollconf.FlagAggregator) if err != nil { return fmt.Errorf("error reading aggregator flag: %w", err) } - // if the aggregator flag is set, we set the aggregator to true - if aggregator { - config.Node.Aggregator = true + config := InitializeConfig(homePath, aggregator) + + passphrase, err := cmd.Flags().GetString(rollconf.FlagSignerPassphrase) + if err != nil { + return fmt.Errorf("error reading passphrase flag: %w", err) } - // If using local file signer and aggregator is enabled, initialize the key - if config.Signer.SignerType == "file" && aggregator { - // Get passphrase if local signing is enabled - passphrase, err := cmd.Flags().GetString(rollconf.FlagSignerPassphrase) - if err != nil { - return fmt.Errorf("error reading passphrase flag: %w", err) - } - - if passphrase == "" { - return fmt.Errorf("passphrase is required when using local file signer") - } - - // Create signer directory if it doesn't exist - signerDir := filepath.Join(homePath, "signer") - if err := os.MkdirAll(signerDir, rollconf.DefaultDirPerm); err != nil { - return fmt.Errorf("failed to create signer directory: %w", err) - } - - // Set signer path - config.Signer.SignerPath = filepath.Join(signerDir, "priv_key.json") - - // Initialize the signer - _, err = file.NewFileSystemSigner(config.Signer.SignerPath, []byte(passphrase)) - if err != nil { - return fmt.Errorf("failed to initialize signer: %w", err) - } + if err := InitializeSigner(&config, homePath, passphrase); err != nil { + return err } - // Use writeYamlConfig instead of manual marshaling and file writing if err := rollconf.WriteYamlConfig(config); err != nil { return fmt.Errorf("error writing rollkit.yaml file: %w", err) } - nodeKeyFile := filepath.Join(homePath, "config", "node_key.json") - _, err = key.LoadOrGenNodeKey(nodeKeyFile) + if err := InitializeNodeKey(homePath); err != nil { + return err + } + + // Get chain ID or use default + chainID, err := cmd.Flags().GetString(rollconf.FlagChainID) if err != nil { - return fmt.Errorf("failed to create node key: %w", err) + return fmt.Errorf("error reading chain ID flag: %w", err) + } + if chainID == "" { + chainID = "rollkit-test" + } + + // Initialize genesis with empty app state + if err := InitializeGenesis(homePath, chainID, 1, []byte("{}")); err != nil { + return fmt.Errorf("error initializing genesis file: %w", err) } fmt.Printf("Initialized %s file in %s\n", rollconf.RollkitConfigYaml, homePath) @@ -102,7 +159,17 @@ var InitCmd = &cobra.Command{ } func init() { + InitFlags(InitCmd) +} + +func SignerFlags(cmd *cobra.Command) { // Add passphrase flag - InitCmd.Flags().String(rollconf.FlagSignerPassphrase, "", "Passphrase for encrypting the local signer key (required when using local file signer)") - InitCmd.Flags().Bool(rollconf.FlagAggregator, false, "Run node in aggregator mode") + cmd.Flags().String(rollconf.FlagSignerPassphrase, "", "Passphrase for encrypting the local signer key (required when using local file signer)") + cmd.Flags().Bool(rollconf.FlagAggregator, false, "Run node in aggregator mode") +} + +// InitFlags adds init command flags +func InitFlags(cmd *cobra.Command) { + SignerFlags(cmd) + cmd.Flags().String(rollconf.FlagChainID, "rollkit-test", "Chain ID for the genesis file") } diff --git a/pkg/config/config.go b/pkg/config/config.go index d64b066358..ce2ac9f9e9 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -21,6 +21,8 @@ const ( FlagDBPath = "db_path" // FlagChainConfigDir is a flag for specifying the chain config directory FlagChainConfigDir = "config_dir" + // FlagChainID is a flag for specifying the chain ID + FlagChainID = "chain_id" // Node configuration flags @@ -142,7 +144,7 @@ type Config struct { RootDir string `mapstructure:"home" yaml:"home" comment:"Root directory where rollkit files are located"` DBPath string `mapstructure:"db_path" yaml:"db_path" comment:"Path inside the root directory where the database is located"` ConfigDir string `mapstructure:"config_dir" yaml:"config_dir" comment:"Directory containing the rollup chain configuration"` - + ChainID string `mapstructure:"chain_id" yaml:"chain_id" comment:"Chain ID for the rollup"` // P2P configuration P2P P2PConfig `mapstructure:"p2p" yaml:"p2p"` @@ -246,7 +248,7 @@ func AddFlags(cmd *cobra.Command) { cmd.Flags().String(FlagRootDir, DefaultNodeConfig.RootDir, "root directory for config and data") cmd.Flags().String(FlagDBPath, DefaultNodeConfig.DBPath, "path for the node database") cmd.Flags().String(FlagChainConfigDir, DefaultNodeConfig.ConfigDir, "directory containing chain configuration files") - + cmd.Flags().String(FlagChainID, DefaultNodeConfig.ChainID, "chain ID") // Node configuration flags cmd.Flags().BoolVar(&def.Node.Aggregator, FlagAggregator, def.Node.Aggregator, "run node in aggregator mode") cmd.Flags().Bool(FlagLight, def.Node.Light, "run light client") @@ -296,7 +298,7 @@ func AddFlags(cmd *cobra.Command) { // Signer configuration flags cmd.Flags().String(FlagSignerType, def.Signer.SignerType, "type of signer to use (file, grpc)") cmd.Flags().String(FlagSignerPath, def.Signer.SignerPath, "path to the signer file or address") - cmd.Flags().String(FlagSignerPassphrase, "", "passphrase for the signer") + cmd.Flags().String(FlagSignerPassphrase, "", "passphrase for the signer (required for file signer and if aggregator is enabled)") } // LoadNodeConfig loads the node configuration in the following order of precedence: @@ -422,4 +424,8 @@ func setDefaultsInViper(v *viper.Viper, config Config) { v.SetDefault(FlagLogLevel, "info") v.SetDefault(FlagLogFormat, "") v.SetDefault(FlagLogTrace, false) + + // Signer configuration defaults + v.SetDefault(FlagSignerType, config.Signer.SignerType) + v.SetDefault(FlagSignerPath, config.Signer.SignerPath) } diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index af2724e161..7f0be4d757 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -16,6 +16,9 @@ const ( // DefaultDataDir is the default directory for data files (e.g. database). DefaultDataDir = "data" + // DefaultSignerPath is the default path for the signer file + DefaultSignerPath = "signer" + // DefaultListenAddress is a default listen address for P2P client. DefaultListenAddress = "/ip4/0.0.0.0/tcp/7676" // Version is the current rollkit version @@ -53,6 +56,7 @@ var DefaultNodeConfig = Config{ RootDir: DefaultRootDir(), DBPath: DefaultDataDir, ConfigDir: DefaultConfigDir, + ChainID: "rollkit-test", P2P: P2PConfig{ ListenAddress: DefaultListenAddress, Seeds: "", @@ -82,7 +86,7 @@ var DefaultNodeConfig = Config{ }, Signer: SignerConfig{ SignerType: "file", - SignerPath: "", + SignerPath: DefaultSignerPath, }, RPC: RPCConfig{ Address: "127.0.0.1", diff --git a/pkg/genesis/genesis.go b/pkg/genesis/genesis.go index 55f163f59c..5028307fd0 100644 --- a/pkg/genesis/genesis.go +++ b/pkg/genesis/genesis.go @@ -8,9 +8,7 @@ import ( // GenesisExtraData represents the flexible configuration data in genesis type GenesisExtraData struct { - ProposerAddress []byte `json:"proposer_address,omitempty"` - Validators []ValidatorInfo `json:"validators,omitempty"` - ConsensusParams map[string]string `json:"consensus_params,omitempty"` + ProposerAddress []byte `json:"proposer_address,omitempty"` } // ValidatorInfo represents a validator's configuration in genesis diff --git a/pkg/genesis/genesis_test.go b/pkg/genesis/genesis_test.go index bd5b62b82d..d42e270656 100644 --- a/pkg/genesis/genesis_test.go +++ b/pkg/genesis/genesis_test.go @@ -21,12 +21,6 @@ func TestGenesis_Validate(t *testing.T) { InitialHeight: 1, ExtraData: GenesisExtraData{ ProposerAddress: []byte("proposer"), - Validators: []ValidatorInfo{ - { - Address: []byte("validator"), - PublicKey: []byte("pubkey"), - }, - }, }, AppState: json.RawMessage(`{}`), }, diff --git a/pkg/genesis/io_test.go b/pkg/genesis/io_test.go index 10b3e1f734..00efcfd991 100644 --- a/pkg/genesis/io_test.go +++ b/pkg/genesis/io_test.go @@ -35,12 +35,6 @@ func TestLoadAndSaveGenesis(t *testing.T) { GenesisDAStartHeight: validTime, ExtraData: GenesisExtraData{ ProposerAddress: []byte("proposer-address"), - Validators: []ValidatorInfo{ - { - Address: []byte("validator-1"), - PublicKey: []byte("pubkey-1"), - }, - }, }, AppState: json.RawMessage(`{"key": "value"}`), }, diff --git a/rollups/testapp/commands/root.go b/rollups/testapp/cmd/root.go similarity index 97% rename from rollups/testapp/commands/root.go rename to rollups/testapp/cmd/root.go index 598ccd1ae8..98f800fb2a 100644 --- a/rollups/testapp/commands/root.go +++ b/rollups/testapp/cmd/root.go @@ -1,4 +1,4 @@ -package commands +package cmd import ( "github.com/spf13/cobra" diff --git a/rollups/testapp/main.go b/rollups/testapp/main.go index d0eb0afb39..65bed51860 100644 --- a/rollups/testapp/main.go +++ b/rollups/testapp/main.go @@ -11,7 +11,7 @@ import ( coresequencer "github.com/rollkit/rollkit/core/sequencer" "github.com/rollkit/rollkit/da" rollcmd "github.com/rollkit/rollkit/pkg/cmd" - commands "github.com/rollkit/rollkit/rollups/testapp/commands" + commands "github.com/rollkit/rollkit/rollups/testapp/cmd" testExecutor "github.com/rollkit/rollkit/rollups/testapp/kv" ) diff --git a/test/e2e/base_test.go b/test/e2e/base_test.go index a666ee9fa4..57460a14c9 100644 --- a/test/e2e/base_test.go +++ b/test/e2e/base_test.go @@ -32,7 +32,7 @@ func TestBasic(t *testing.T) { sut := NewSystemUnderTest(t) aggregatorPass := "12345678" // init aggregator - sut.StartNode(binaryPath, + sut.RunCmd(binaryPath, "init", "--home="+node1Home, "--node.sequencer_rollup_id=testing", @@ -42,6 +42,7 @@ func TestBasic(t *testing.T) { "--node.aggrgator", "--signer.passphrase="+aggregatorPass, ) + // start aggregator sut.StartNode(binaryPath, "start", diff --git a/test/e2e/sut_helper.go b/test/e2e/sut_helper.go index 6542bb35ba..fe2a546d6a 100644 --- a/test/e2e/sut_helper.go +++ b/test/e2e/sut_helper.go @@ -49,6 +49,16 @@ func NewSystemUnderTest(t *testing.T) *SystemUnderTest { return r } +// RunCmd runs a command and returns the output +func (s *SystemUnderTest) RunCmd(cmd string, args ...string) (string, error) { + c := exec.Command( //nolint:gosec // used by tests only + locateExecutable(cmd), + args..., + ) + out, err := c.Output() + return string(out), err +} + // StartNode starts a process for the given command and manages it cleanup on test end. func (s *SystemUnderTest) StartNode(cmd string, args ...string) { c := exec.Command( //nolint:gosec // used by tests only From 495b8568bb3bbac345c3494de321bd661f4c2129 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 21:38:19 +0200 Subject: [PATCH 26/29] add todo --- rollups/testapp/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/rollups/testapp/main.go b/rollups/testapp/main.go index 65bed51860..adf33921d6 100644 --- a/rollups/testapp/main.go +++ b/rollups/testapp/main.go @@ -23,6 +23,7 @@ func main() { ctx := context.Background() // Create test implementations + // TODO: we need to start the executor http server executor := testExecutor.CreateDirectKVExecutor(ctx) sequencer := coresequencer.NewDummySequencer() From 4dd9b7a86cf44302821f5e2c4e2b00aee6d5fc3c Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 21:45:05 +0200 Subject: [PATCH 27/29] fix test --- pkg/config/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index d84547bcfa..82030aa1cf 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -97,7 +97,7 @@ func TestAddFlags(t *testing.T) { assertFlagValue(t, persistentFlags, FlagLogTrace, false) // Count the number of flags we're explicitly checking - expectedFlagCount := 44 // Update this number if you add more flag checks above + expectedFlagCount := 45 // Update this number if you add more flag checks above // Get the actual number of flags (both regular and persistent) actualFlagCount := 0 From 3b7ca479f81a5edf07e0a07e6b77b4906f988200 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 22:10:13 +0200 Subject: [PATCH 28/29] fix --- block/manager.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/block/manager.go b/block/manager.go index ebb162db80..a339c55ef1 100644 --- a/block/manager.go +++ b/block/manager.go @@ -1464,6 +1464,10 @@ func (m *Manager) execCommit(ctx context.Context, newState types.State, h *types func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignature *types.Signature, lastHeaderHash types.Hash, lastState types.State, batchData *BatchData) (*types.SignedHeader, *types.Data, error) { data := batchData.Data batchdata := convertBatchDataToBytes(data) + key, err := m.proposerKey.GetPublic() + if err != nil { + return nil, nil, err + } header := &types.SignedHeader{ Header: types.Header{ Version: types.Version{ @@ -1483,7 +1487,7 @@ func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignatur }, Signature: *lastSignature, Signer: types.Signer{ - PubKey: m.proposerKey.GetPublic(), + PubKey: key, Address: m.genesis.ProposerAddress(), }, } From 3507019fc94df7df8b51e7b1bc4a138b4bf433b6 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 31 Mar 2025 22:13:19 +0200 Subject: [PATCH 29/29] lint --- test/e2e/sut_helper.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/e2e/sut_helper.go b/test/e2e/sut_helper.go index fe2a546d6a..29bc836838 100644 --- a/test/e2e/sut_helper.go +++ b/test/e2e/sut_helper.go @@ -17,10 +17,11 @@ import ( "time" "github.com/libp2p/go-libp2p/core/peer" - "github.com/rollkit/rollkit/pkg/p2p/key" - "github.com/rollkit/rollkit/pkg/rpc/client" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/rollkit/rollkit/pkg/p2p/key" + "github.com/rollkit/rollkit/pkg/rpc/client" ) // WorkDir defines the default working directory for spawned processes.