Skip to content

Commit 4a71069

Browse files
committed
Merge branch 'master' into multiple-underlay-addresses
2 parents 3fc84b4 + ec5ff0d commit 4a71069

File tree

13 files changed

+183
-45
lines changed

13 files changed

+183
-45
lines changed

Dockerfile.dev

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,19 @@ FROM debian:12.12-slim
1818
ENV DEBIAN_FRONTEND=noninteractive
1919

2020
RUN apt-get update && apt-get install -y --no-install-recommends \
21-
ca-certificates; \
21+
ca-certificates \
22+
iputils-ping \
23+
netcat-openbsd \
24+
telnet \
25+
curl \
26+
wget \
27+
jq \
28+
net-tools; \
2229
apt-get clean; \
2330
rm -rf /var/lib/apt/lists/*; \
2431
groupadd -r bee --gid 999; \
2532
useradd -r -g bee --uid 999 --no-log-init -m bee;
2633

27-
# make sure mounted volumes have correct permissions
2834
RUN mkdir -p /home/bee/.bee && chown 999:999 /home/bee/.bee
2935

3036
COPY --from=build /src/dist/bee /usr/local/bin/bee

openapi/Swarm.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -565,12 +565,6 @@ paths:
565565
tags:
566566
- Tag
567567
description: Tags can be thought of as upload sessions which can be tracked using the tags endpoint. It will keep track of the chunks that are uploaded as part of the tag and will push them out to the network once a done split is called on the Tag. This happens internally if you use the `Swarm-Deferred-Upload` header.
568-
requestBody:
569-
required: true
570-
content:
571-
application/json:
572-
schema:
573-
$ref: "SwarmCommon.yaml#/components/schemas/NewTagRequest"
574568
responses:
575569
"201":
576570
description: New Tag Info

openapi/SwarmCommon.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,6 @@ components:
295295
MultiAddress:
296296
type: string
297297

298-
NewTagRequest:
299-
type: object
300-
properties:
301-
address:
302-
$ref: "#/components/schemas/SwarmAddress"
303-
304298
NewTagResponse:
305299
type: object
306300
properties:

pkg/node/chain.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,8 @@ func (m noOpChainBackend) SuggestGasTipCap(context.Context) (*big.Int, error) {
372372
panic("chain no op: SuggestGasTipCap")
373373
}
374374

375-
func (m noOpChainBackend) EstimateGas(context.Context, ethereum.CallMsg) (uint64, error) {
376-
panic("chain no op: EstimateGas")
375+
func (m noOpChainBackend) EstimateGasAtBlock(context.Context, ethereum.CallMsg, *big.Int) (uint64, error) {
376+
panic("chain no op: EstimateGasAtBlock")
377377
}
378378

379379
func (m noOpChainBackend) SendTransaction(context.Context, *types.Transaction) error {

pkg/node/export_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2025 The Swarm Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package node
6+
7+
var ValidatePublicAddress = validatePublicAddress

pkg/node/node.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"net/http"
2121
"path/filepath"
2222
"runtime"
23+
"strconv"
2324
"sync"
2425
"sync/atomic"
2526
"time"
@@ -222,6 +223,10 @@ func NewBee(
222223
return nil, fmt.Errorf("tracer: %w", err)
223224
}
224225

226+
if err := validatePublicAddress(o.NATAddr); err != nil {
227+
return nil, fmt.Errorf("invalid NAT address %s: %w", o.NATAddr, err)
228+
}
229+
225230
ctx, ctxCancel := context.WithCancel(ctx)
226231
defer func() {
227232
// if there's been an error on this function
@@ -1463,3 +1468,38 @@ func isChainEnabled(o *Options, swapEndpoint string, logger log.Logger) bool {
14631468
logger.Info("starting with an enabled chain backend")
14641469
return true // all other modes operate require chain enabled
14651470
}
1471+
1472+
func validatePublicAddress(addr string) error {
1473+
if addr == "" {
1474+
return nil
1475+
}
1476+
1477+
host, port, err := net.SplitHostPort(addr)
1478+
if err != nil {
1479+
return fmt.Errorf("%w", err)
1480+
}
1481+
if host == "" {
1482+
return errors.New("host is empty")
1483+
}
1484+
if port == "" {
1485+
return errors.New("port is empty")
1486+
}
1487+
if _, err := strconv.ParseUint(port, 10, 16); err != nil {
1488+
return fmt.Errorf("port is not a valid number: %w", err)
1489+
}
1490+
if host == "localhost" {
1491+
return errors.New("localhost is not a valid address")
1492+
}
1493+
ip := net.ParseIP(host)
1494+
if ip == nil {
1495+
return errors.New("not a valid IP address")
1496+
}
1497+
if ip.IsLoopback() {
1498+
return errors.New("loopback address is not a valid address")
1499+
}
1500+
if ip.IsPrivate() {
1501+
return errors.New("private address is not a valid address")
1502+
}
1503+
1504+
return nil
1505+
}

pkg/node/node_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2025 The Swarm Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package node_test
6+
7+
import (
8+
"testing"
9+
10+
"github.com/ethersphere/bee/v2/pkg/node"
11+
)
12+
13+
func TestValidatePublicAddress(t *testing.T) {
14+
t.Parallel()
15+
16+
testCases := []struct {
17+
name string
18+
addr string
19+
expErr bool
20+
}{
21+
{
22+
name: "empty host",
23+
addr: ":1635",
24+
expErr: true,
25+
},
26+
{
27+
name: "localhost",
28+
addr: "localhost:1635",
29+
expErr: true,
30+
},
31+
{
32+
name: "loopback",
33+
addr: "127.0.0.1:1635",
34+
expErr: true,
35+
},
36+
{
37+
name: "loopback ipv6",
38+
addr: "[::1]:1635",
39+
expErr: true,
40+
},
41+
{
42+
name: "missing port",
43+
addr: "1.2.3.4",
44+
expErr: true,
45+
},
46+
{
47+
name: "empty port",
48+
addr: "1.2.3.4:",
49+
expErr: true,
50+
},
51+
{
52+
name: "invalid port number",
53+
addr: "1.2.3.4:abc",
54+
expErr: true,
55+
},
56+
{
57+
name: "valid",
58+
addr: "1.2.3.4:1635",
59+
expErr: false,
60+
},
61+
{
62+
name: "valid ipv6",
63+
addr: "[2001:db8::1]:1635",
64+
expErr: false,
65+
},
66+
{
67+
name: "empty",
68+
addr: "",
69+
expErr: false,
70+
},
71+
{
72+
name: "invalid IP",
73+
addr: "not-an-ip:8080",
74+
expErr: true,
75+
},
76+
{
77+
name: "private IP",
78+
addr: "192.168.1.1:8080",
79+
expErr: true,
80+
},
81+
{
82+
name: "hostname",
83+
addr: "example.com:8080",
84+
expErr: true,
85+
},
86+
}
87+
88+
for _, tc := range testCases {
89+
t.Run(tc.name, func(t *testing.T) {
90+
err := node.ValidatePublicAddress(tc.addr)
91+
if tc.expErr && err == nil {
92+
t.Fatal("expected error, but got none")
93+
}
94+
if !tc.expErr && err != nil {
95+
t.Fatalf("expected no error, but got: %v", err)
96+
}
97+
})
98+
}
99+
}

pkg/transaction/backend/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type Geth interface {
2020
CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
2121
ChainID(ctx context.Context) (*big.Int, error)
2222
Close()
23-
EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error)
23+
EstimateGasAtBlock(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) (uint64, error)
2424
FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
2525
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
2626
NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)

pkg/transaction/backendmock/backend.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type backendMock struct {
2020
sendTransaction func(ctx context.Context, tx *types.Transaction) error
2121
suggestedFeeAndTip func(ctx context.Context, gasPrice *big.Int, boostPercent int) (*big.Int, *big.Int, error)
2222
suggestGasTipCap func(ctx context.Context) (*big.Int, error)
23-
estimateGas func(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)
23+
estimateGasAtBlock func(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) (gas uint64, err error)
2424
transactionReceipt func(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
2525
pendingNonceAt func(ctx context.Context, account common.Address) (uint64, error)
2626
transactionByHash func(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error)
@@ -51,9 +51,9 @@ func (m *backendMock) SuggestedFeeAndTip(ctx context.Context, gasPrice *big.Int,
5151
return nil, nil, errors.New("not implemented")
5252
}
5353

54-
func (m *backendMock) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) {
55-
if m.estimateGas != nil {
56-
return m.estimateGas(ctx, call)
54+
func (m *backendMock) EstimateGasAtBlock(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) (uint64, error) {
55+
if m.estimateGasAtBlock != nil {
56+
return m.estimateGasAtBlock(ctx, msg, blockNumber)
5757
}
5858
return 0, errors.New("not implemented")
5959
}
@@ -171,9 +171,9 @@ func WithSuggestGasTipCapFunc(f func(ctx context.Context) (*big.Int, error)) Opt
171171
})
172172
}
173173

174-
func WithEstimateGasFunc(f func(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)) Option {
174+
func WithEstimateGasAtBlockFunc(f func(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) (gas uint64, err error)) Option {
175175
return optionFunc(func(s *backendMock) {
176-
s.estimateGas = f
176+
s.estimateGasAtBlock = f
177177
})
178178
}
179179

pkg/transaction/backendsimulation/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func (m *simulatedBackend) SuggestedFeeAndTip(ctx context.Context, gasPrice *big
9595
return nil, nil, errors.New("not implemented")
9696
}
9797

98-
func (m *simulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) {
98+
func (m *simulatedBackend) EstimateGasAtBlock(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) (uint64, error) {
9999
return 0, errors.New("not implemented")
100100
}
101101

0 commit comments

Comments
 (0)