Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
72ab6d32
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
72ab6d32
编写于
4月 23, 2015
作者:
F
Felix Lange
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
p2p/discover: track sha3(ID) in Node
上级
b34a8ef6
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
166 addition
and
99 deletion
+166
-99
p2p/discover/database.go
p2p/discover/database.go
+2
-0
p2p/discover/database_test.go
p2p/discover/database_test.go
+41
-31
p2p/discover/node.go
p2p/discover/node.go
+35
-20
p2p/discover/node_test.go
p2p/discover/node_test.go
+43
-28
p2p/discover/table.go
p2p/discover/table.go
+6
-5
p2p/discover/table_test.go
p2p/discover/table_test.go
+1
-1
p2p/discover/udp.go
p2p/discover/udp.go
+26
-6
p2p/discover/udp_test.go
p2p/discover/udp_test.go
+12
-8
未找到文件。
p2p/discover/database.go
浏览文件 @
72ab6d32
...
...
@@ -10,6 +10,7 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rlp"
...
...
@@ -167,6 +168,7 @@ func (db *nodeDB) node(id NodeID) *Node {
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"failed to decode node RLP: %v"
,
err
)
return
nil
}
node
.
sha
=
crypto
.
Sha3Hash
(
node
.
ID
[
:
])
return
node
}
...
...
p2p/discover/database_test.go
浏览文件 @
72ab6d32
...
...
@@ -86,12 +86,12 @@ func TestNodeDBInt64(t *testing.T) {
}
func
TestNodeDBFetchStore
(
t
*
testing
.
T
)
{
node
:=
&
Node
{
ID
:
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
net
.
IP
([]
byte
{
192
,
168
,
0
,
1
})
,
UDP
:
30303
,
TCP
:
30303
,
}
node
:=
newNode
(
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
IP
{
192
,
168
,
0
,
1
}
,
30303
,
30303
,
)
inst
:=
time
.
Now
()
db
,
_
:=
newNodeDB
(
""
,
Version
)
...
...
@@ -132,28 +132,34 @@ func TestNodeDBFetchStore(t *testing.T) {
}
var
nodeDBSeedQueryNodes
=
[]
struct
{
node
Node
node
*
Node
pong
time
.
Time
}{
{
node
:
Node
{
ID
:
MustHexID
(
"0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
[]
byte
{
127
,
0
,
0
,
1
},
},
node
:
newNode
(
MustHexID
(
"0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
IP
{
127
,
0
,
0
,
1
},
30303
,
30303
,
),
pong
:
time
.
Now
()
.
Add
(
-
2
*
time
.
Second
),
},
{
node
:
Node
{
ID
:
MustHexID
(
"0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
[]
byte
{
127
,
0
,
0
,
2
},
},
node
:
newNode
(
MustHexID
(
"0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
IP
{
127
,
0
,
0
,
2
},
30303
,
30303
,
),
pong
:
time
.
Now
()
.
Add
(
-
3
*
time
.
Second
),
},
{
node
:
Node
{
ID
:
MustHexID
(
"0x03d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
[]
byte
{
127
,
0
,
0
,
3
},
},
node
:
newNode
(
MustHexID
(
"0x03d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
IP
{
127
,
0
,
0
,
3
},
30303
,
30303
,
),
pong
:
time
.
Now
()
.
Add
(
-
1
*
time
.
Second
),
},
}
...
...
@@ -164,7 +170,7 @@ func TestNodeDBSeedQuery(t *testing.T) {
// Insert a batch of nodes for querying
for
i
,
seed
:=
range
nodeDBSeedQueryNodes
{
if
err
:=
db
.
updateNode
(
&
seed
.
node
);
err
!=
nil
{
if
err
:=
db
.
updateNode
(
seed
.
node
);
err
!=
nil
{
t
.
Fatalf
(
"node %d: failed to insert: %v"
,
i
,
err
)
}
}
...
...
@@ -204,7 +210,7 @@ func TestNodeDBSeedQueryContinuation(t *testing.T) {
// Insert a batch of nodes for querying
for
i
,
seed
:=
range
nodeDBSeedQueryNodes
{
if
err
:=
db
.
updateNode
(
&
seed
.
node
);
err
!=
nil
{
if
err
:=
db
.
updateNode
(
seed
.
node
);
err
!=
nil
{
t
.
Fatalf
(
"node %d: failed to insert: %v"
,
i
,
err
)
}
}
...
...
@@ -268,22 +274,26 @@ func TestNodeDBPersistency(t *testing.T) {
}
var
nodeDBExpirationNodes
=
[]
struct
{
node
Node
node
*
Node
pong
time
.
Time
exp
bool
}{
{
node
:
Node
{
ID
:
MustHexID
(
"0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
[]
byte
{
127
,
0
,
0
,
1
},
},
node
:
newNode
(
MustHexID
(
"0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
IP
{
127
,
0
,
0
,
1
},
30303
,
30303
,
),
pong
:
time
.
Now
()
.
Add
(
-
nodeDBNodeExpiration
+
time
.
Minute
),
exp
:
false
,
},
{
node
:
Node
{
ID
:
MustHexID
(
"0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
[]
byte
{
127
,
0
,
0
,
2
},
},
node
:
newNode
(
MustHexID
(
"0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
IP
{
127
,
0
,
0
,
2
},
30303
,
30303
,
),
pong
:
time
.
Now
()
.
Add
(
-
nodeDBNodeExpiration
-
time
.
Minute
),
exp
:
true
,
},
...
...
@@ -295,7 +305,7 @@ func TestNodeDBExpiration(t *testing.T) {
// Add all the test nodes and set their last pong time
for
i
,
seed
:=
range
nodeDBExpirationNodes
{
if
err
:=
db
.
updateNode
(
&
seed
.
node
);
err
!=
nil
{
if
err
:=
db
.
updateNode
(
seed
.
node
);
err
!=
nil
{
t
.
Fatalf
(
"node %d: failed to insert: %v"
,
i
,
err
)
}
if
err
:=
db
.
updateLastPong
(
seed
.
node
.
ID
,
seed
.
pong
);
err
!=
nil
{
...
...
p2p/discover/node.go
浏览文件 @
72ab6d32
...
...
@@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
)
...
...
@@ -23,19 +24,26 @@ const nodeIDBits = 512
type
Node
struct
{
IP
net
.
IP
// len 4 for IPv4 or 16 for IPv6
UDP
,
TCP
uint16
// port numbers
ID
NodeID
ID
NodeID
// the node's public key
// This is a cached copy of sha3(ID) which is used for node
// distance calculations. This is part of Node in order to make it
// possible to write tests that need a node at a certain distance.
// In those tests, the content of sha will not actually correspond
// with ID.
sha
common
.
Hash
}
func
newNode
(
id
NodeID
,
addr
*
net
.
UDPAddr
)
*
Node
{
ip
:=
addr
.
IP
.
To4
()
if
ip
==
nil
{
ip
=
addr
.
IP
.
To16
()
func
newNode
(
id
NodeID
,
ip
net
.
IP
,
udpPort
,
tcpPort
uint16
)
*
Node
{
if
ipv4
:=
ip
.
To4
();
ipv4
!=
nil
{
ip
=
ipv4
}
return
&
Node
{
IP
:
ip
,
UDP
:
u
int16
(
addr
.
Port
)
,
TCP
:
uint16
(
addr
.
Port
)
,
UDP
:
u
dpPort
,
TCP
:
tcpPort
,
ID
:
id
,
sha
:
crypto
.
Sha3Hash
(
id
[
:
]),
}
}
...
...
@@ -75,40 +83,47 @@ func (n *Node) String() string {
//
// enode://<hex node id>@10.3.58.6:30303?discport=30301
func
ParseNode
(
rawurl
string
)
(
*
Node
,
error
)
{
var
n
Node
var
(
id
NodeID
ip
net
.
IP
tcpPort
,
udpPort
uint64
)
u
,
err
:=
url
.
Parse
(
rawurl
)
if
u
.
Scheme
!=
"enode"
{
return
nil
,
errors
.
New
(
"invalid URL scheme, want
\"
enode
\"
"
)
}
// Parse the Node ID from the user portion.
if
u
.
User
==
nil
{
return
nil
,
errors
.
New
(
"does not contain node ID"
)
}
if
n
.
ID
,
err
=
HexID
(
u
.
User
.
String
());
err
!=
nil
{
if
id
,
err
=
HexID
(
u
.
User
.
String
());
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid node ID (%v)"
,
err
)
}
ip
,
port
,
err
:=
net
.
SplitHostPort
(
u
.
Host
)
// Parse the IP address.
host
,
port
,
err
:=
net
.
SplitHostPort
(
u
.
Host
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid host: %v"
,
err
)
}
if
n
.
IP
=
net
.
ParseIP
(
ip
);
n
.
IP
==
nil
{
if
ip
=
net
.
ParseIP
(
host
);
ip
==
nil
{
return
nil
,
errors
.
New
(
"invalid IP address"
)
}
tcp
,
err
:=
strconv
.
ParseUint
(
port
,
10
,
16
)
if
err
!=
nil
{
// Ensure the IP is 4 bytes long for IPv4 addresses.
if
ipv4
:=
ip
.
To4
();
ipv4
!=
nil
{
ip
=
ipv4
}
// Parse the port numbers.
if
tcpPort
,
err
=
strconv
.
ParseUint
(
port
,
10
,
16
);
err
!=
nil
{
return
nil
,
errors
.
New
(
"invalid port"
)
}
n
.
TCP
=
uint16
(
tcp
)
udpPort
=
tcpPort
qv
:=
u
.
Query
()
if
qv
.
Get
(
"discport"
)
==
""
{
n
.
UDP
=
n
.
TCP
}
else
{
udp
,
err
:=
strconv
.
ParseUint
(
qv
.
Get
(
"discport"
),
10
,
16
)
if
qv
.
Get
(
"discport"
)
!=
""
{
udpPort
,
err
=
strconv
.
ParseUint
(
qv
.
Get
(
"discport"
),
10
,
16
)
if
err
!=
nil
{
return
nil
,
errors
.
New
(
"invalid discport in query"
)
}
n
.
UDP
=
uint16
(
udp
)
}
return
&
n
,
nil
return
newNode
(
id
,
ip
,
uint16
(
udpPort
),
uint16
(
tcpPort
))
,
nil
}
// MustParseNode parses a node URL. It panics if the URL is not valid.
...
...
p2p/discover/node_test.go
浏览文件 @
72ab6d32
...
...
@@ -48,46 +48,61 @@ var parseNodeTests = []struct {
},
{
rawurl
:
"enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150"
,
wantResult
:
&
Node
{
ID
:
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
net
.
ParseIP
(
"127.0.0.1"
)
,
UDP
:
52150
,
TCP
:
52150
,
}
,
wantResult
:
newNode
(
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
IP
{
0x7f
,
0x0
,
0x0
,
0x1
}
,
52150
,
52150
,
)
,
},
{
rawurl
:
"enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150"
,
wantResult
:
&
Node
{
ID
:
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
net
.
ParseIP
(
"::"
),
UDP
:
52150
,
TCP
:
52150
,
},
wantResult
:
newNode
(
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
ParseIP
(
"::"
),
52150
,
52150
,
),
},
{
rawurl
:
"enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150"
,
wantResult
:
newNode
(
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
ParseIP
(
"2001:db8:3c4d:15::abcd:ef12"
),
52150
,
52150
,
),
},
{
rawurl
:
"enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334"
,
wantResult
:
&
Node
{
ID
:
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
IP
:
net
.
ParseIP
(
"127.0.0.1"
)
,
UDP
:
22334
,
TCP
:
52150
,
}
,
wantResult
:
newNode
(
MustHexID
(
"0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"
),
net
.
IP
{
0x7f
,
0x0
,
0x0
,
0x1
}
,
22334
,
52150
,
)
,
},
}
func
TestParseNode
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
parseNodeTests
{
n
,
err
:=
ParseNode
(
test
.
rawurl
)
if
err
==
nil
&&
test
.
wantError
!=
""
{
t
.
Errorf
(
"test %d: got nil error, expected %#q"
,
i
,
test
.
wantError
)
continue
}
if
err
!=
nil
&&
err
.
Error
()
!=
test
.
wantError
{
t
.
Errorf
(
"test %d: got error %#q, expected %#q"
,
i
,
err
.
Error
(),
test
.
wantError
)
continue
}
if
!
reflect
.
DeepEqual
(
n
,
test
.
wantResult
)
{
t
.
Errorf
(
"test %d: result mismatch:
\n
got: %#v, want: %#v"
,
i
,
n
,
test
.
wantResult
)
if
test
.
wantError
!=
""
{
if
err
==
nil
{
t
.
Errorf
(
"test %d: got nil error, expected %#q"
,
i
,
test
.
wantError
)
continue
}
else
if
err
.
Error
()
!=
test
.
wantError
{
t
.
Errorf
(
"test %d: got error %#q, expected %#q"
,
i
,
err
.
Error
(),
test
.
wantError
)
continue
}
}
else
{
if
err
!=
nil
{
t
.
Errorf
(
"test %d: unexpected error: %v"
,
i
,
err
)
continue
}
if
!
reflect
.
DeepEqual
(
n
,
test
.
wantResult
)
{
t
.
Errorf
(
"test %d: result mismatch:
\n
got: %#v, want: %#v"
,
i
,
n
,
test
.
wantResult
)
}
}
}
}
...
...
p2p/discover/table.go
浏览文件 @
72ab6d32
...
...
@@ -12,6 +12,7 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
)
...
...
@@ -71,7 +72,7 @@ func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string
tab
:=
&
Table
{
net
:
t
,
db
:
db
,
self
:
newNode
(
ourID
,
ourAddr
),
self
:
newNode
(
ourID
,
ourAddr
.
IP
,
uint16
(
ourAddr
.
Port
),
uint16
(
ourAddr
.
Port
)
),
bonding
:
make
(
map
[
NodeID
]
*
bondproc
),
bondslots
:
make
(
chan
struct
{},
maxBondingPingPongs
),
}
...
...
@@ -105,6 +106,7 @@ func (tab *Table) Bootstrap(nodes []*Node) {
tab
.
nursery
=
make
([]
*
Node
,
0
,
len
(
nodes
))
for
_
,
n
:=
range
nodes
{
cpy
:=
*
n
cpy
.
sha
=
crypto
.
Sha3Hash
(
n
.
ID
[
:
])
tab
.
nursery
=
append
(
tab
.
nursery
,
&
cpy
)
}
tab
.
mutex
.
Unlock
()
...
...
@@ -299,7 +301,7 @@ func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAdd
tab
.
net
.
waitping
(
id
)
}
// Bonding succeeded, update the node database
w
.
n
=
&
Node
{
ID
:
id
,
IP
:
addr
.
IP
,
UDP
:
uint16
(
addr
.
Port
),
TCP
:
tcpPort
}
w
.
n
=
newNode
(
id
,
addr
.
IP
,
uint16
(
addr
.
Port
),
tcpPort
)
tab
.
db
.
updateNode
(
w
.
n
)
close
(
w
.
done
)
}
...
...
@@ -340,9 +342,8 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
func
(
tab
*
Table
)
add
(
entries
[]
*
Node
)
{
outer
:
for
_
,
n
:=
range
entries
{
if
n
==
nil
||
n
.
ID
==
tab
.
self
.
ID
{
// skip bad entries. The RLP decoder returns nil for empty
// input lists.
if
n
.
ID
==
tab
.
self
.
ID
{
// don't add self.
continue
}
bucket
:=
tab
.
buckets
[
logdist
(
tab
.
self
.
ID
,
n
.
ID
)]
...
...
p2p/discover/table_test.go
浏览文件 @
72ab6d32
...
...
@@ -224,7 +224,7 @@ func TestTable_Lookup(t *testing.T) {
t
.
Fatalf
(
"lookup on empty table returned %d results: %#v"
,
len
(
results
),
results
)
}
// seed table with initial node (otherwise lookup will terminate immediately)
tab
.
add
([]
*
Node
{
newNode
(
randomID
(
target
,
200
),
&
net
.
UDPAddr
{
Port
:
200
}
)})
tab
.
add
([]
*
Node
{
newNode
(
randomID
(
target
,
200
),
net
.
ParseIP
(
"127.0.0.1"
),
200
,
200
)})
results
:=
tab
.
Lookup
(
target
)
t
.
Logf
(
"results:"
)
...
...
p2p/discover/udp.go
浏览文件 @
72ab6d32
...
...
@@ -74,10 +74,17 @@ type (
// reply to findnode
neighbors
struct
{
Nodes
[]
*
Node
Nodes
[]
rpc
Node
Expiration
uint64
}
rpcNode
struct
{
IP
net
.
IP
// len 4 for IPv4 or 16 for IPv6
UDP
uint16
// for discovery protocol
TCP
uint16
// for RLPx protocol
ID
NodeID
}
rpcEndpoint
struct
{
IP
net
.
IP
// len 4 for IPv4 or 16 for IPv6
UDP
uint16
// for discovery protocol
...
...
@@ -93,9 +100,17 @@ func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint {
return
rpcEndpoint
{
IP
:
ip
,
UDP
:
uint16
(
addr
.
Port
),
TCP
:
tcpPort
}
}
func
validNode
(
n
*
Node
)
bool
{
func
nodeFromRPC
(
rn
rpcNode
)
(
n
*
Node
,
valid
bool
)
{
// TODO: don't accept localhost, LAN addresses from internet hosts
return
!
n
.
IP
.
IsMulticast
()
&&
!
n
.
IP
.
IsUnspecified
()
&&
n
.
UDP
!=
0
// TODO: check public key is on secp256k1 curve
if
rn
.
IP
.
IsMulticast
()
||
rn
.
IP
.
IsUnspecified
()
||
rn
.
UDP
==
0
{
return
nil
,
false
}
return
newNode
(
rn
.
ID
,
rn
.
IP
,
rn
.
UDP
,
rn
.
TCP
),
true
}
func
nodeToRPC
(
n
*
Node
)
rpcNode
{
return
rpcNode
{
ID
:
n
.
ID
,
IP
:
n
.
IP
,
UDP
:
n
.
UDP
,
TCP
:
n
.
TCP
}
}
type
packet
interface
{
...
...
@@ -232,9 +247,9 @@ func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node
nreceived
:=
0
errc
:=
t
.
pending
(
toid
,
neighborsPacket
,
func
(
r
interface
{})
bool
{
reply
:=
r
.
(
*
neighbors
)
for
_
,
n
:=
range
reply
.
Nodes
{
for
_
,
r
n
:=
range
reply
.
Nodes
{
nreceived
++
if
validNode
(
n
)
{
if
n
,
valid
:=
nodeFromRPC
(
rn
);
valid
{
nodes
=
append
(
nodes
,
n
)
}
}
...
...
@@ -489,8 +504,13 @@ func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte
closest
:=
t
.
closest
(
req
.
Target
,
bucketSize
)
.
entries
t
.
mutex
.
Unlock
()
// TODO: this conversion could use a cached version of the slice
closestrpc
:=
make
([]
rpcNode
,
len
(
closest
))
for
i
,
n
:=
range
closest
{
closestrpc
[
i
]
=
nodeToRPC
(
n
)
}
t
.
send
(
from
,
neighborsPacket
,
neighbors
{
Nodes
:
closest
,
Nodes
:
closest
rpc
,
Expiration
:
uint64
(
time
.
Now
()
.
Add
(
expiration
)
.
Unix
()),
})
return
nil
...
...
p2p/discover/udp_test.go
浏览文件 @
72ab6d32
...
...
@@ -159,12 +159,12 @@ func TestUDP_findnode(t *testing.T) {
// ensure there's a bond with the test node,
// findnode won't be accepted otherwise.
test
.
table
.
db
.
updateNode
(
&
Node
{
ID
:
PubkeyID
(
&
test
.
remotekey
.
PublicKey
),
IP
:
test
.
remoteaddr
.
IP
,
UDP
:
uint16
(
test
.
remoteaddr
.
Port
),
TCP
:
99
,
}
)
test
.
table
.
db
.
updateNode
(
newNode
(
PubkeyID
(
&
test
.
remotekey
.
PublicKey
),
test
.
remoteaddr
.
IP
,
uint16
(
test
.
remoteaddr
.
Port
),
99
,
)
)
// check that closest neighbors are returned.
test
.
packetIn
(
nil
,
findnodePacket
,
&
findnode
{
Target
:
testTarget
,
Expiration
:
futureExp
})
test
.
waitPacketOut
(
func
(
p
*
neighbors
)
{
...
...
@@ -211,8 +211,12 @@ func TestUDP_findnodeMultiReply(t *testing.T) {
MustParseNode
(
"enode://9bffefd833d53fac8e652415f4973bee289e8b1a5c6c4cbe70abf817ce8a64cee11b823b66a987f51aaa9fba0d6a91b3e6bf0d5a5d1042de8e9eeea057b217f8@10.0.1.36:30301?discport=17"
),
MustParseNode
(
"enode://1b5b4aa662d7cb44a7221bfba67302590b643028197a7d5214790f3bac7aaa4a3241be9e83c09cf1f6c69d007c634faae3dc1b1221793e8446c0b3a09de65960@10.0.1.16:30303"
),
}
test
.
packetIn
(
nil
,
neighborsPacket
,
&
neighbors
{
Expiration
:
futureExp
,
Nodes
:
list
[
:
2
]})
test
.
packetIn
(
nil
,
neighborsPacket
,
&
neighbors
{
Expiration
:
futureExp
,
Nodes
:
list
[
2
:
]})
rpclist
:=
make
([]
rpcNode
,
len
(
list
))
for
i
:=
range
list
{
rpclist
[
i
]
=
nodeToRPC
(
list
[
i
])
}
test
.
packetIn
(
nil
,
neighborsPacket
,
&
neighbors
{
Expiration
:
futureExp
,
Nodes
:
rpclist
[
:
2
]})
test
.
packetIn
(
nil
,
neighborsPacket
,
&
neighbors
{
Expiration
:
futureExp
,
Nodes
:
rpclist
[
2
:
]})
// check that the sent neighbors are all returned by findnode
select
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录