From 15fa89a8c19aede9e3dd90d313df581ff62d4049 Mon Sep 17 00:00:00 2001 From: Emanuel Pargov Date: Tue, 7 Jan 2025 13:04:58 +0200 Subject: [PATCH] Address PR review comments --- cmd/strawberry/main.go | 2 +- go.mod | 22 +++--- go.sum | 46 ++++++------ pkg/network/network_test.go | 69 ++++++++++++++++-- pkg/network/peer/peer.go | 6 +- pkg/network/transport/transport.go | 109 +++++++++++++++-------------- 6 files changed, 158 insertions(+), 96 deletions(-) diff --git a/cmd/strawberry/main.go b/cmd/strawberry/main.go index 49eebb0e..1143c136 100644 --- a/cmd/strawberry/main.go +++ b/cmd/strawberry/main.go @@ -106,7 +106,7 @@ func main() { hash := [32]byte{1, 2, 3, 4} // Example hash // Create peer with protocol connection - p := peer.NewPeer(conn, conn.PeerKey(), protoManager) + p := peer.NewPeer(conn, protoManager) ctx := context.Background() blocks, err := p.RequestBlocks(ctx, hash, true) if err != nil { diff --git a/go.mod b/go.mod index b487dfed..25a5bdaa 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,14 @@ module github.com/eigerco/strawberry go 1.22.5 require ( - github.com/cockroachdb/pebble v1.1.2 + github.com/cockroachdb/pebble v1.1.3 github.com/ebitengine/purego v0.8.1 github.com/golang/mock v1.6.0 + github.com/pkg/errors v0.9.1 github.com/quic-go/quic-go v0.48.2 github.com/stretchr/testify v1.10.0 - golang.org/x/crypto v0.31.0 + golang.org/x/crypto v0.32.0 + golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 ) require ( @@ -16,12 +18,12 @@ require ( github.com/beorn7/perks v1.0.1 // 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/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // 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.30.0 // indirect + github.com/getsentry/sentry-go v0.31.1 // 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 @@ -30,8 +32,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.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/onsi/ginkgo/v2 v2.22.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect @@ -39,13 +40,12 @@ require ( 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/net v0.34.0 // indirect golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect + golang.org/x/sys v0.29.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 + golang.org/x/tools v0.29.0 // indirect + google.golang.org/protobuf v1.36.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e1cbeb8e..e0c2d099 100644 --- a/go.sum +++ b/go.sum @@ -8,12 +8,12 @@ github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaY 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/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 h1:ASDL+UJcILMqgNeV5jiqR4j+sTuvQNHdf2chuKj1M5k= github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506/go.mod h1:Mw7HqKr2kdtu6aYGn3tPmAftiP3QPX63LdK/zcariIo= -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/pebble v1.1.3 h1:GM5YY3Yb09KCGUQoyWdi3vsLErXHsmc3qRRWsX+tBqw= +github.com/cockroachdb/pebble v1.1.3/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= @@ -23,8 +23,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE= github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/getsentry/sentry-go v0.30.0 h1:lWUwDnY7sKHaVIoZ9wYqRHJ5iEmoc0pqcRqFkosKzBo= -github.com/getsentry/sentry-go v0.30.0/go.mod h1:WU9B9/1/sHDqeV8T+3VwwbjeR5MSXs/6aqG3mqZrezA= +github.com/getsentry/sentry-go v0.31.1 h1:ELVc0h7gwyhnXHDouXkhqTFSO5oslsRDk0++eyE0KJ4= +github.com/getsentry/sentry-go v0.31.1/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= 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-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= @@ -51,10 +51,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= -github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= -github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +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= +github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -80,15 +80,17 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= 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/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4= -golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= +golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= 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/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -99,8 +101,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL 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/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= 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= @@ -113,8 +115,8 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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= @@ -127,14 +129,14 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn 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/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= -golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= 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.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ= -google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU= +google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/pkg/network/network_test.go b/pkg/network/network_test.go index 59f9a99e..75fbb7d8 100644 --- a/pkg/network/network_test.go +++ b/pkg/network/network_test.go @@ -92,7 +92,7 @@ func setupTestPair(t *testing.T) (*testNode, *testNode, *peer.Peer) { conn, err := node2.transport.Connect(node1.addr) require.NoError(t, err) - p := peer.NewPeer(conn, conn.PeerKey(), node2.protoManager) + p := peer.NewPeer(conn, node2.protoManager) return node1, node2, p } @@ -177,13 +177,14 @@ func TestConnectionClosure(t *testing.T) { // Close node1's transport require.NoError(t, node1.transport.Stop()) + // Wait a bit to ensure connection is fully closed + time.Sleep(1 * time.Second) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() response, err := p.RequestBlocks(ctx, [32]byte{}, true) assert.Error(t, err) - assert.Contains(t, err.Error(), context.DeadlineExceeded.Error()) assert.Nil(t, response) } @@ -225,7 +226,7 @@ func TestServerNodeRestart(t *testing.T) { require.NoError(t, err) // Create new peer with new connection - p = peer.NewPeer(conn, conn.PeerKey(), node2.protoManager) + p = peer.NewPeer(conn, node2.protoManager) // Try request with longer timeout ctx, cancel = context.WithTimeout(context.Background(), time.Second) @@ -258,7 +259,7 @@ func TestClientNodeRestart(t *testing.T) { require.NoError(t, err) // Create new peer with new connection - newPeer := peer.NewPeer(conn, conn.PeerKey(), node2.protoManager) + newPeer := peer.NewPeer(conn, node2.protoManager) // Try request with new peer ctx, cancel = context.WithTimeout(context.Background(), time.Second) @@ -267,3 +268,63 @@ func TestClientNodeRestart(t *testing.T) { require.NoError(t, err) assert.Equal(t, "test block response", string(response2)) } + +func TestConnectWithWrongChainHash(t *testing.T) { + // Setup node1 + node1 := setupTestNode(t) + defer cleanupNodes(t, node1) + + // Generate a unique address for node2 + listener, err := net.Listen("tcp", "localhost:0") + require.NoError(t, err) + node2Addr := listener.Addr().String() + listener.Close() + + // Generate keys for node2 + pub, priv, err := ed25519.GenerateKey(nil) + require.NoError(t, err) + + // Create certificate for node2 + certGen := cert.NewGenerator(cert.Config{ + PublicKey: pub, + PrivateKey: priv, + CertValidityPeriod: 24 * time.Hour, + }) + tlsCert, err := certGen.GenerateCertificate() + require.NoError(t, err) + + // Create a protocol manager with a wrong chain hash for node2 + protoConfig := protocol.Config{ + ChainHash: "12345679", // Mismatched chain hash + IsBuilder: false, + } + protoManager, err := protocol.NewManager(protoConfig) + require.NoError(t, err) + + // Create transport for node2 + transportConfig := transport.Config{ + PublicKey: pub, + PrivateKey: priv, + TLSCert: tlsCert, + ListenAddr: node2Addr, // Use the new address for node2 + CertValidator: cert.NewValidator(), + Handler: protoManager, + } + + node2Transport, err := transport.NewTransport(transportConfig) + require.NoError(t, err) + + // Start node1 and node2 + require.NoError(t, node1.transport.Start()) + require.NoError(t, node2Transport.Start()) + defer func() { + if err := node2Transport.Stop(); err != nil { + t.Errorf("failed to stop node2 transport: %v", err) + } + }() + + // Attempt to connect node2 to node1 + _, err = node2Transport.Connect(node1.addr) + assert.Error(t, err, "connection should fail due to ALPN mismatch") + assert.Contains(t, err.Error(), "no application protocol", "error should indicate ALPN failure") +} diff --git a/pkg/network/peer/peer.go b/pkg/network/peer/peer.go index b3a96637..558c7b7a 100644 --- a/pkg/network/peer/peer.go +++ b/pkg/network/peer/peer.go @@ -2,7 +2,6 @@ package peer import ( "context" - "crypto/ed25519" "fmt" "github.com/eigerco/strawberry/pkg/network/handlers" @@ -17,8 +16,6 @@ type Peer struct { conn *transport.Conn // protoConn handles protocol-specific operations protoConn *protocol.ProtocolConn - // pubKey uniquely identifies the remote peer - pubKey ed25519.PublicKey } // NewPeer creates a new peer instance from an established transport connection. @@ -27,11 +24,10 @@ type Peer struct { // - conn: The underlying transport connection // - pubKey: The peer's Ed25519 public key // - protoManager: The protocol manager for handling streams -func NewPeer(conn *transport.Conn, pubKey ed25519.PublicKey, protoManager *protocol.Manager) *Peer { +func NewPeer(conn *transport.Conn, protoManager *protocol.Manager) *Peer { return &Peer{ conn: conn, protoConn: protoManager.WrapConnection(conn), - pubKey: pubKey, } } diff --git a/pkg/network/transport/transport.go b/pkg/network/transport/transport.go index 24fe5092..c9a88289 100644 --- a/pkg/network/transport/transport.go +++ b/pkg/network/transport/transport.go @@ -68,13 +68,13 @@ type Config struct { // Transport manages QUIC connections and their lifecycles type Transport struct { - config Config - listener *quic.Listener - mu sync.RWMutex - conns map[string]*Conn // Active connections mapped by peer key - ctx context.Context - cancel context.CancelFunc - acceptLoopWg sync.WaitGroup // For clean shutdown of accept loop + config Config + listener *quic.Listener + mu sync.RWMutex + conns map[string]*Conn // Active connections mapped by peer key + ctx context.Context + cancel context.CancelFunc + done chan struct{} // For clean shutdown of accept loop } // NewTransport creates and configures a new transport instance. @@ -110,12 +110,19 @@ func (t *Transport) Start() error { ClientAuth: tls.RequireAnyClientCert, MinVersion: tls.VersionTLS13, InsecureSkipVerify: true, - VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { - c, err := x509.ParseCertificate(rawCerts[0]) - if err != nil { + VerifyConnection: func(cs tls.ConnectionState) error { + fmt.Printf("Negotiated Protocol: %s\n", cs.NegotiatedProtocol) + if len(cs.PeerCertificates) == 0 { + return fmt.Errorf("%w: no peer certificate provided", ErrInvalidCertificate) + } + cert := cs.PeerCertificates[0] + if err := t.config.CertValidator.ValidateCertificate(cert); err != nil { return fmt.Errorf("%w: %v", ErrInvalidCertificate, err) } - return t.config.CertValidator.ValidateCertificate(c) + if err := t.config.Handler.ValidateConnection(cs); err != nil { + return fmt.Errorf("connection validation failed: %v", err) + } + return nil }, } @@ -129,10 +136,10 @@ func (t *Transport) Start() error { t.ctx, t.cancel = context.WithCancel(context.Background()) t.listener = listener - t.acceptLoopWg.Add(1) + t.done = make(chan struct{}) go func() { - defer t.acceptLoopWg.Done() t.acceptLoop() + close(t.done) }() return nil } @@ -140,11 +147,29 @@ func (t *Transport) Start() error { // Stop gracefully shuts down the transport and all active connections. // Waits for the accept loop to finish before returning. func (t *Transport) Stop() error { + // Cancel the accept loop t.cancel() + + // Close all active connections + t.mu.Lock() + for _, conn := range t.conns { + if err := conn.Close(); err != nil { + fmt.Printf("Failed to close connection: %v\n", err) + } + } + // Clear the connection map + t.conns = make(map[string]*Conn) + t.mu.Unlock() + + // Close the listener if t.listener != nil { - t.listener.Close() + if err := t.listener.Close(); err != nil { + return fmt.Errorf("failed to close listener: %w", err) + } } - t.acceptLoopWg.Wait() // Wait for acceptLoop to finish + + // Wait for the accept loop to finish + <-t.done return nil } @@ -232,56 +257,46 @@ func (t *Transport) acceptLoop() { // handleConnection processes a new QUIC connection func (t *Transport) handleConnection(qConn quic.Connection) *Conn { - tlsState := qConn.ConnectionState().TLS - - if err := t.verifyPeerCert(tlsState.PeerCertificates); err != nil { - if cerr := qConn.CloseWithError(0, ErrInvalidCertificate.Error()); cerr != nil { + peerKey, err := t.config.CertValidator.ExtractPublicKey(qConn.ConnectionState().TLS.PeerCertificates[0]) + if err != nil { + fmt.Printf("Failed to extract peer key: %v\n", err) + if cerr := qConn.CloseWithError(0, fmt.Sprintf("%s: %v", ErrInvalidCertificate.Error(), err)); cerr != nil { fmt.Printf("Failed to close connection: %v\n", cerr) } return nil } - if err := t.config.Handler.ValidateConnection(tlsState); err != nil { - fmt.Printf("Failed to validate connection: %v\n", err) + conn := t.manageConnection(peerKey, qConn) + + if err := t.config.Handler.OnConnection(conn); err != nil { + t.cleanup(peerKey) if cerr := qConn.CloseWithError(0, err.Error()); cerr != nil { fmt.Printf("Failed to close connection: %v\n", cerr) } return nil } - peerKey, err := t.config.CertValidator.ExtractPublicKey(tlsState.PeerCertificates[0]) - if err != nil { - fmt.Printf("Failed to extract peer key: %v\n", err) - if cerr := qConn.CloseWithError(0, fmt.Sprintf("%s: %v", ErrInvalidCertificate.Error(), err)); cerr != nil { - fmt.Printf("Failed to close connection: %v\n", cerr) - } - return nil - } + return conn +} +// manageConnection handles connection storage and replacement +func (t *Transport) manageConnection(peerKey ed25519.PublicKey, qConn quic.Connection) *Conn { t.mu.Lock() + defer t.mu.Unlock() + + // Close existing connection if any if existingConn, exists := t.conns[string(peerKey)]; exists { fmt.Println("Found existing connection, closing it") - // Close existing connection before replacing it if err := existingConn.Close(); err != nil { fmt.Printf("Failed to close existing connection: %v\n", err) } delete(t.conns, string(peerKey)) } + // Create and store new connection conn := newConn(qConn, t) conn.peerKey = peerKey - - // Store connection t.conns[string(peerKey)] = conn - t.mu.Unlock() - - if err := t.config.Handler.OnConnection(conn); err != nil { - t.cleanup(peerKey) - if cerr := qConn.CloseWithError(0, err.Error()); cerr != nil { - fmt.Printf("Failed to close connection: %v\n", cerr) - } - return nil - } return conn } @@ -292,15 +307,3 @@ func (t *Transport) cleanup(peerKey ed25519.PublicKey) { delete(t.conns, string(peerKey)) t.mu.Unlock() } - -// verifyPeerCert verifies the peer's certificate chain -func (t *Transport) verifyPeerCert(certs []*x509.Certificate) error { - if len(certs) == 0 { - return fmt.Errorf("%w: no certificates provided", ErrInvalidCertificate) - } - if err := t.config.CertValidator.ValidateCertificate(certs[0]); err != nil { - return fmt.Errorf("%w: %v", ErrInvalidCertificate, err) - } - - return nil -}