Skip to content

Commit

Permalink
Add quic transport layer
Browse files Browse the repository at this point in the history
  • Loading branch information
bamzedev committed Dec 30, 2024
1 parent ac572e4 commit 2a5a7e2
Show file tree
Hide file tree
Showing 17 changed files with 1,463 additions and 153 deletions.
143 changes: 105 additions & 38 deletions cmd/strawberry/main.go
Original file line number Diff line number Diff line change
@@ -1,54 +1,121 @@
package main

import (
"encoding/json"
"context"
"crypto/ed25519"
"flag"
"fmt"
"log"
"net/http"
"sync"
"time"

"github.com/eigerco/strawberry/internal/block"
"github.com/eigerco/strawberry/internal/state"
"github.com/eigerco/strawberry/internal/statetransition"
"github.com/eigerco/strawberry/pkg/network/cert"
"github.com/eigerco/strawberry/pkg/network/handlers"
"github.com/eigerco/strawberry/pkg/network/peer"
"github.com/eigerco/strawberry/pkg/network/protocol"
"github.com/eigerco/strawberry/pkg/network/transport"
)

// main starts a blockchain node.
//
// To run the first node (listener):
//
// go run main.go -addr localhost:9000
//
// To run a second node that connects to the first node:
//
// go run main.go -addr localhost:9001 -connect localhost:9000
//
// - The first node listens on port 9000.
// - The second node listens on port 9001 and connects to the first node's address (localhost:9000).
func main() {
globalState := &state.State{}
mu := &sync.RWMutex{}

// a simple http server that demonstrates the block import capabilities
// this will be replaced with proper p2p network communication in milestone 2
mux := http.NewServeMux()
mux.HandleFunc("/block/import", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
newBlock := block.Block{}
if err := json.NewDecoder(r.Body).Decode(&newBlock); err != nil {
jsonError(w, err.Error(), http.StatusBadRequest)
return
}
listenAddr := flag.String("addr", "", "Listen address (e.g., 0.0.0.0:9000)")
connectTo := flag.String("connect", "", "Address to connect to (optional)")
flag.Parse()

if *listenAddr == "" {
log.Fatal("listen address is required")
}

// Generate node keys
pub, priv, err := ed25519.GenerateKey(nil)
if err != nil {
log.Fatalf("Failed to generate keys: %v", err)
}

// Create certificate
certGen := cert.NewGenerator(cert.Config{
PublicKey: pub,
PrivateKey: priv,
CertValidityPeriod: 24 * time.Hour,
})
tlsCert, err := certGen.GenerateCertificate()
if err != nil {
log.Fatalf("Failed to generate certificate: %v", err)
}

// Create protocol manager
protoConfig := protocol.Config{
ChainHash: "12345678", // Example chain hash
IsBuilder: false,
MaxBuilderSlots: 20,
}
protoManager, err := protocol.NewManager(protoConfig)
if err != nil {
log.Fatalf("Failed to create protocol manager: %v", err)
}

mu.Lock()
defer mu.Unlock()
// Register protocol handlers
protoManager.Registry.RegisterHandler(protocol.StreamKindBlockRequest, handlers.NewBlockRequestHandler())

if err := statetransition.UpdateState(globalState, newBlock); err != nil {
jsonError(w, err.Error(), http.StatusBadRequest)
return
// Create transport with minimal config
transportConfig := transport.Config{
PublicKey: pub,
PrivateKey: priv,
TLSCert: tlsCert,
ListenAddr: *listenAddr,
CertValidator: cert.NewValidator(),
Handler: protoManager, // Protocol manager implements ConnectionHandler
}

tr, err := transport.NewTransport(transportConfig)
if err != nil {
log.Fatalf("Failed to create transport: %v", err)
}

if err := tr.Start(); err != nil {
log.Fatalf("Failed to start transport: %v", err)
}
defer func() {
if err := tr.Stop(); err != nil {
fmt.Printf("Failed to stop transport: %v\n", err)
}
}()

log.Printf("Node listening on %s", *listenAddr)

// If we have an address to connect to, make a request
if *connectTo != "" {
log.Printf("Connecting to peer at %s", *connectTo)

if err := json.NewEncoder(w).Encode(map[string]string{"status": "success"}); err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
conn, err := tr.Connect(*connectTo)
if err != nil {
log.Fatalf("Failed to connect to peer: %v", err)
}
})
log.Println("demo server running on port :8080")
log.Fatal(http.ListenAndServe(":8080", mux))
}

func jsonError(w http.ResponseWriter, message string, statusCode int) {
w.WriteHeader(statusCode)
if err := json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"message": message,
}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
// Create a dummy block hash for the request
hash := [32]byte{1, 2, 3, 4} // Example hash

// Create peer with protocol connection
p := peer.NewPeer(conn, conn.PeerKey(), protoManager)
ctx := context.Background()
blocks, err := p.RequestBlocks(ctx, hash, true)
if err != nil {
log.Fatalf("Failed to request blocks: %v", err)
}
fmt.Printf("blocks: %v\n", blocks)
log.Printf("Block request completed")
}

// Keep the node running
select {}
}
47 changes: 28 additions & 19 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,49 @@ module github.com/eigerco/strawberry
go 1.22.5

require (
github.com/cockroachdb/pebble v1.1.0
github.com/cockroachdb/pebble v1.1.2
github.com/ebitengine/purego v0.8.1
github.com/golang/mock v1.6.0
github.com/quic-go/quic-go v0.48.2
github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.27.0
golang.org/x/crypto v0.31.0
)

require (
github.com/DataDog/zstd v1.5.2 // indirect
github.com/DataDog/zstd v1.5.6 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/errors v1.11.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cespare/xxhash/v2 v2.3.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-20241215232642-bb51bb14a506 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/getsentry/sentry-go v0.30.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo/v2 v2.22.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.18.0 // indirect
github.com/prometheus/client_model v0.6.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.61.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
go.uber.org/mock v0.5.0 // indirect
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.32.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/tools v0.28.0 // indirect
google.golang.org/protobuf v1.36.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit 2a5a7e2

Please sign in to comment.