mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-29 14:45:07 +03:00
1. moved address to core
This commit is contained in:
parent
b5f79eadcb
commit
6319d6231b
15 changed files with 61 additions and 60 deletions
150
src/core/address.go
Normal file
150
src/core/address.go
Normal file
|
@ -0,0 +1,150 @@
|
|||
// Package address contains the types used by mesh to represent IPv6 addresses or prefixes, as well as functions for working with these types.
|
||||
// Of particular importance are the functions used to derive addresses or subnets from a NodeID, or to get the NodeID and bitmask of the bits visible from an address, which is needed for DHT searches.
|
||||
package core
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
)
|
||||
|
||||
// Address represents an IPv6 address in the mesh address range.
|
||||
type Address [16]byte
|
||||
|
||||
// Subnet represents an IPv6 /64 subnet in the mesh subnet range.
|
||||
type Subnet [8]byte
|
||||
|
||||
// GetPrefix returns the address prefix used by mesh.
|
||||
// The current implementation requires this to be a multiple of 8 bits + 7 bits.
|
||||
// The 8th bit of the last byte is used to signal nodes (0) or /64 prefixes (1).
|
||||
// Nodes that configure this differently will be unable to communicate with each other using IP packets, though routing and the DHT machinery *should* still work.
|
||||
func GetPrefix() [1]byte {
|
||||
return [...]byte{0xfc}
|
||||
}
|
||||
|
||||
// IsValid returns true if an address falls within the range used by nodes in the network.
|
||||
func (a *Address) IsValid() bool {
|
||||
prefix := GetPrefix()
|
||||
for idx := range prefix {
|
||||
if (*a)[idx] != prefix[idx] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsValid returns true if a prefix falls within the range usable by the network.
|
||||
func (s *Subnet) IsValid() bool {
|
||||
prefix := GetPrefix()
|
||||
l := len(prefix)
|
||||
for idx := range prefix[:l-1] {
|
||||
if (*s)[idx] != prefix[idx] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return (*s)[l-1] == prefix[l-1]|0x01
|
||||
}
|
||||
|
||||
// AddrForKey takes an ed25519.PublicKey as an argument and returns an *Address.
|
||||
// This function returns nil if the key length is not ed25519.PublicKeySize.
|
||||
// This address begins with the contents of GetPrefix(), with the last bit set to 0 to indicate an address.
|
||||
// The following 8 bits are set to the number of leading 1 bits in the bitwise inverse of the public key.
|
||||
// The bitwise inverse of the key, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the address.
|
||||
func (c *Core) AddrForKey(publicKey ed25519.PublicKey) *Address {
|
||||
// 128 bit address
|
||||
// Begins with prefix
|
||||
// Next bit is a 0
|
||||
// Next 7 bits, interpreted as a uint, are # of leading 1s in the NodeID
|
||||
// Leading 1s and first leading 0 of the NodeID are truncated off
|
||||
// The rest is appended to the IPv6 address (truncated to 128 bits total)
|
||||
if len(publicKey) != ed25519.PublicKeySize {
|
||||
return nil
|
||||
}
|
||||
var buf [ed25519.PublicKeySize]byte
|
||||
copy(buf[:], publicKey)
|
||||
for idx := range buf {
|
||||
buf[idx] = ^buf[idx]
|
||||
}
|
||||
var addr Address
|
||||
var temp = make([]byte, 0, 32)
|
||||
done := false
|
||||
ones := byte(0)
|
||||
bits := byte(0)
|
||||
nBits := 0
|
||||
for idx := 0; idx < 8*len(buf); idx++ {
|
||||
bit := (buf[idx/8] & (0x80 >> byte(idx%8))) >> byte(7-(idx%8))
|
||||
if !done && bit != 0 {
|
||||
ones++
|
||||
continue
|
||||
}
|
||||
if !done && bit == 0 {
|
||||
done = true
|
||||
continue // FIXME? this assumes that ones <= 127, probably only worth changing by using a variable length uint64, but that would require changes to the addressing scheme, and I'm not sure ones > 127 is realistic
|
||||
}
|
||||
bits = (bits << 1) | bit
|
||||
nBits++
|
||||
if nBits == 8 {
|
||||
nBits = 0
|
||||
temp = append(temp, bits)
|
||||
}
|
||||
}
|
||||
prefix := GetPrefix()
|
||||
copy(addr[:], prefix[:])
|
||||
addr[len(prefix)] = ones
|
||||
copy(addr[len(prefix)+1:], temp)
|
||||
return &addr
|
||||
}
|
||||
|
||||
// SubnetForKey takes an ed25519.PublicKey as an argument and returns a *Subnet.
|
||||
// This function returns nil if the key length is not ed25519.PublicKeySize.
|
||||
// The subnet begins with the address prefix, with the last bit set to 1 to indicate a prefix.
|
||||
// The following 8 bits are set to the number of leading 1 bits in the bitwise inverse of the key.
|
||||
// The bitwise inverse of the key, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the subnet.
|
||||
func (c *Core) SubnetForKey(publicKey ed25519.PublicKey) *Subnet {
|
||||
// Exactly as the address version, with two exceptions:
|
||||
// 1) The first bit after the fixed prefix is a 1 instead of a 0
|
||||
// 2) It's truncated to a subnet prefix length instead of 128 bits
|
||||
addr := c.AddrForKey(publicKey)
|
||||
if addr == nil {
|
||||
return nil
|
||||
}
|
||||
var snet Subnet
|
||||
copy(snet[:], addr[:])
|
||||
prefix := GetPrefix() // nolint:staticcheck
|
||||
snet[len(prefix)-1] |= 0x01
|
||||
return &snet
|
||||
}
|
||||
|
||||
// GetKet returns the partial ed25519.PublicKey for the Address.
|
||||
// This is used for key lookup.
|
||||
func (a *Address) GetKey() ed25519.PublicKey {
|
||||
var key [ed25519.PublicKeySize]byte
|
||||
prefix := GetPrefix() // nolint:staticcheck
|
||||
ones := int(a[len(prefix)])
|
||||
for idx := 0; idx < ones; idx++ {
|
||||
key[idx/8] |= 0x80 >> byte(idx%8)
|
||||
}
|
||||
keyOffset := ones + 1
|
||||
addrOffset := 8*len(prefix) + 8
|
||||
for idx := addrOffset; idx < 8*len(a); idx++ {
|
||||
bits := a[idx/8] & (0x80 >> byte(idx%8))
|
||||
bits <<= byte(idx % 8)
|
||||
keyIdx := keyOffset + (idx - addrOffset)
|
||||
bits >>= byte(keyIdx % 8)
|
||||
idx := keyIdx / 8
|
||||
if idx >= len(key) {
|
||||
break
|
||||
}
|
||||
key[idx] |= bits
|
||||
}
|
||||
for idx := range key {
|
||||
key[idx] = ^key[idx]
|
||||
}
|
||||
return ed25519.PublicKey(key[:])
|
||||
}
|
||||
|
||||
// GetKet returns the partial ed25519.PublicKey for the Subnet.
|
||||
// This is used for key lookup.
|
||||
func (s *Subnet) GetKey() ed25519.PublicKey {
|
||||
var addr Address
|
||||
copy(addr[:], s[:])
|
||||
return addr.GetKey()
|
||||
}
|
114
src/core/address_test.go
Normal file
114
src/core/address_test.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAddress_Address_IsValid(t *testing.T) {
|
||||
var address Address
|
||||
rand.Read(address[:])
|
||||
|
||||
address[0] = 0
|
||||
|
||||
if address.IsValid() {
|
||||
t.Fatal("invalid address marked as valid")
|
||||
}
|
||||
|
||||
address[0] = 0xfd
|
||||
|
||||
if address.IsValid() {
|
||||
t.Fatal("invalid address marked as valid")
|
||||
}
|
||||
|
||||
address[0] = 0xfc
|
||||
|
||||
if !address.IsValid() {
|
||||
t.Fatal("valid address marked as invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_Subnet_IsValid(t *testing.T) {
|
||||
var subnet Subnet
|
||||
rand.Read(subnet[:])
|
||||
|
||||
subnet[0] = 0
|
||||
|
||||
if subnet.IsValid() {
|
||||
t.Fatal("invalid subnet marked as valid")
|
||||
}
|
||||
|
||||
subnet[0] = 0xfc
|
||||
|
||||
if subnet.IsValid() {
|
||||
t.Fatal("invalid subnet marked as valid")
|
||||
}
|
||||
|
||||
subnet[0] = 0xfd
|
||||
|
||||
if !subnet.IsValid() {
|
||||
t.Fatal("valid subnet marked as invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_AddrForKey(t *testing.T) {
|
||||
publicKey := ed25519.PublicKey{
|
||||
189, 186, 207, 216, 34, 64, 222, 61, 205, 18, 57, 36, 203, 181, 82, 86,
|
||||
251, 141, 171, 8, 170, 152, 227, 5, 82, 138, 184, 79, 65, 158, 110, 251,
|
||||
}
|
||||
|
||||
expectedAddress := Address{
|
||||
f, c, 0, 132, 138, 96, 79, 187, 126, 67, 132, 101, 219, 141, 182, 104, 149,
|
||||
}
|
||||
|
||||
if *AddrForKey(publicKey) != expectedAddress {
|
||||
t.Fatal("invalid address returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_SubnetForKey(t *testing.T) {
|
||||
publicKey := ed25519.PublicKey{
|
||||
189, 186, 207, 216, 34, 64, 222, 61, 205, 18, 57, 36, 203, 181, 82, 86,
|
||||
251, 141, 171, 8, 170, 152, 227, 5, 82, 138, 184, 79, 65, 158, 110, 251,
|
||||
}
|
||||
|
||||
expectedSubnet := Subnet{f, d, 0, 132, 138, 96, 79, 187, 126}
|
||||
|
||||
if *SubnetForKey(publicKey) != expectedSubnet {
|
||||
t.Fatal("invalid subnet returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_Address_GetKey(t *testing.T) {
|
||||
address := Address{
|
||||
f, c, 0, 132, 138, 96, 79, 187, 126, 67, 132, 101, 219, 141, 182, 104, 149,
|
||||
}
|
||||
|
||||
expectedPublicKey := ed25519.PublicKey{
|
||||
189, 186, 207, 216, 34, 64, 222, 61,
|
||||
205, 18, 57, 36, 203, 181, 127, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
}
|
||||
|
||||
if !bytes.Equal(address.GetKey(), expectedPublicKey) {
|
||||
t.Fatal("invalid public key returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_Subnet_GetKey(t *testing.T) {
|
||||
subnet := Subnet{f, d, 0, 132, 138, 96, 79, 187, 126}
|
||||
|
||||
expectedPublicKey := ed25519.PublicKey{
|
||||
189, 186, 207, 216, 34, 64, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
}
|
||||
|
||||
if !bytes.Equal(subnet.GetKey(), expectedPublicKey) {
|
||||
t.Fatal("invalid public key returned")
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ import (
|
|||
//"time"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"github.com/RiV-chain/RiV-mesh/src/address"
|
||||
//"github.com/RiV-chain/RiV-mesh/src/address"
|
||||
)
|
||||
|
||||
type SelfInfo struct {
|
||||
|
@ -159,7 +159,7 @@ func (c *Core) Listen(u *url.URL, sintf string) (*Listener, error) {
|
|||
// that application also implements either VPN functionality or deals with IP
|
||||
// packets specifically.
|
||||
func (c *Core) Address() net.IP {
|
||||
addr := net.IP(address.AddrForKey(c.public)[:])
|
||||
addr := net.IP(c.AddrForKey(c.public)[:])
|
||||
return addr
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ func (c *Core) Address() net.IP {
|
|||
// that application also implements either VPN functionality or deals with IP
|
||||
// packets specifically.
|
||||
func (c *Core) Subnet() net.IPNet {
|
||||
subnet := address.SubnetForKey(c.public)[:]
|
||||
subnet := c.SubnetForKey(c.public)[:]
|
||||
subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
return net.IPNet{IP: subnet, Mask: net.CIDRMask(64, 128)}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
// The Core object represents the Mesh node. You should create a Core
|
||||
// object for each Mesh node you plan to run.
|
||||
type Core struct {
|
||||
address Address
|
||||
// This is the main data structure that holds everything else for a node
|
||||
// We're going to keep our own copy of the provided config - that way we can
|
||||
// guarantee that it will be covered by the mutex
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
"sync/atomic"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"github.com/RiV-chain/RiV-mesh/src/address"
|
||||
//"github.com/RiV-chain/RiV-mesh/src/address"
|
||||
//"github.com/Arceliar/phony" // TODO? use instead of mutexes
|
||||
)
|
||||
|
||||
|
@ -188,7 +188,7 @@ func (intf *link) handler() error {
|
|||
if intf.incoming {
|
||||
dir = "inbound"
|
||||
}
|
||||
remoteAddr := net.IP(address.AddrForKey(meta.key)[:]).String()
|
||||
remoteAddr := net.IP(intf.links.core.AddrForKey(meta.key)[:]).String()
|
||||
remoteStr := fmt.Sprintf("%s@%s", remoteAddr, intf.info.remote)
|
||||
localStr := intf.conn.LocalAddr()
|
||||
intf.links.core.log.Infof("Connected %s %s: %s, source %s",
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
iwt "github.com/Arceliar/ironwood/types"
|
||||
"github.com/Arceliar/phony"
|
||||
|
||||
"github.com/RiV-chain/RiV-mesh/src/address"
|
||||
//"github.com/RiV-chain/RiV-mesh/src/address"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -266,7 +266,7 @@ func (p *protoHandler) getSelfHandler(in json.RawMessage) (interface{}, error) {
|
|||
if err := msg.UnmarshalJSON(info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ip := net.IP(address.AddrForKey(kbs)[:])
|
||||
ip := net.IP(p.core.AddrForKey(kbs)[:])
|
||||
res := DebugGetSelfResponse{ip.String(): msg}
|
||||
return res, nil
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ func (p *protoHandler) getPeersHandler(in json.RawMessage) (interface{}, error)
|
|||
if err := msg.UnmarshalJSON(js); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ip := net.IP(address.AddrForKey(kbs)[:])
|
||||
ip := net.IP(p.core.AddrForKey(kbs)[:])
|
||||
res := DebugGetPeersResponse{ip.String(): msg}
|
||||
return res, nil
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ func (p *protoHandler) getDHTHandler(in json.RawMessage) (interface{}, error) {
|
|||
if err := msg.UnmarshalJSON(js); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ip := net.IP(address.AddrForKey(kbs)[:])
|
||||
ip := net.IP(p.core.AddrForKey(kbs)[:])
|
||||
res := DebugGetDHTResponse{ip.String(): msg}
|
||||
return res, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue