mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	(broken state) WIP address migration
This commit is contained in:
		
							parent
							
								
									ae96148008
								
							
						
					
					
						commit
						ace7b43b6d
					
				
					 9 changed files with 73 additions and 120 deletions
				
			
		| 
						 | 
				
			
			@ -3,9 +3,7 @@
 | 
			
		|||
package address
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
			
		||||
	"crypto/ed25519"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Address represents an IPv6 address in the yggdrasil address range.
 | 
			
		||||
| 
						 | 
				
			
			@ -45,25 +43,34 @@ func (s *Subnet) IsValid() bool {
 | 
			
		|||
	return (*s)[l-1] == prefix[l-1]|0x01
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddrForNodeID takes a *NodeID as an argument and returns an *Address.
 | 
			
		||||
// 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 NodeID.
 | 
			
		||||
// The NodeID, 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 AddrForNodeID(nid *crypto.NodeID) *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 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 []byte
 | 
			
		||||
	done := false
 | 
			
		||||
	ones := byte(0)
 | 
			
		||||
	bits := byte(0)
 | 
			
		||||
	nBits := 0
 | 
			
		||||
	for idx := 0; idx < 8*len(nid); idx++ {
 | 
			
		||||
		bit := (nid[idx/8] & (0x80 >> byte(idx%8))) >> byte(7-(idx%8))
 | 
			
		||||
	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
 | 
			
		||||
| 
						 | 
				
			
			@ -86,91 +93,22 @@ func AddrForNodeID(nid *crypto.NodeID) *Address {
 | 
			
		|||
	return &addr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SubnetForNodeID takes a *NodeID as an argument and returns an *Address.
 | 
			
		||||
// This 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 NodeID.
 | 
			
		||||
// The NodeID, 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 SubnetForNodeID(nid *crypto.NodeID) *Subnet {
 | 
			
		||||
// 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 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 := *AddrForNodeID(nid)
 | 
			
		||||
	addr := AddrForKey(publicKey)
 | 
			
		||||
	if addr == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	var snet Subnet
 | 
			
		||||
	copy(snet[:], addr[:])
 | 
			
		||||
	prefix := GetPrefix()
 | 
			
		||||
	snet[len(prefix)-1] |= 0x01
 | 
			
		||||
	return &snet
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetNodeIDandMask returns two *NodeID.
 | 
			
		||||
// The first is a NodeID with all the bits known from the Address set to their correct values.
 | 
			
		||||
// The second is a bitmask with 1 bit set for each bit that was known from the Address.
 | 
			
		||||
// This is used to look up NodeIDs in the DHT and tell if they match an Address.
 | 
			
		||||
func (a *Address) GetNodeIDandMask() (*crypto.NodeID, *crypto.NodeID) {
 | 
			
		||||
	// Mask is a bitmask to mark the bits visible from the address
 | 
			
		||||
	// This means truncated leading 1s, first leading 0, and visible part of addr
 | 
			
		||||
	var nid crypto.NodeID
 | 
			
		||||
	var mask crypto.NodeID
 | 
			
		||||
	prefix := GetPrefix()
 | 
			
		||||
	ones := int(a[len(prefix)])
 | 
			
		||||
	for idx := 0; idx < ones; idx++ {
 | 
			
		||||
		nid[idx/8] |= 0x80 >> byte(idx%8)
 | 
			
		||||
	}
 | 
			
		||||
	nidOffset := 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)
 | 
			
		||||
		nidIdx := nidOffset + (idx - addrOffset)
 | 
			
		||||
		bits >>= byte(nidIdx % 8)
 | 
			
		||||
		nid[nidIdx/8] |= bits
 | 
			
		||||
	}
 | 
			
		||||
	maxMask := 8*(len(a)-len(prefix)-1) + ones + 1
 | 
			
		||||
	for idx := 0; idx < maxMask; idx++ {
 | 
			
		||||
		mask[idx/8] |= 0x80 >> byte(idx%8)
 | 
			
		||||
	}
 | 
			
		||||
	return &nid, &mask
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetNodeIDLengthString returns a string representation of the known bits of the NodeID, along with the number of known bits, for use with yggdrasil.Dialer's Dial and DialContext functions.
 | 
			
		||||
func (a *Address) GetNodeIDLengthString() string {
 | 
			
		||||
	nid, mask := a.GetNodeIDandMask()
 | 
			
		||||
	l := mask.PrefixLength()
 | 
			
		||||
	return fmt.Sprintf("%s/%d", nid.String(), l)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetNodeIDandMask returns two *NodeID.
 | 
			
		||||
// The first is a NodeID with all the bits known from the Subnet set to their correct values.
 | 
			
		||||
// The second is a bitmask with 1 bit set for each bit that was known from the Subnet.
 | 
			
		||||
// This is used to look up NodeIDs in the DHT and tell if they match a Subnet.
 | 
			
		||||
func (s *Subnet) GetNodeIDandMask() (*crypto.NodeID, *crypto.NodeID) {
 | 
			
		||||
	// As with the address version, but visible parts of the subnet prefix instead
 | 
			
		||||
	var nid crypto.NodeID
 | 
			
		||||
	var mask crypto.NodeID
 | 
			
		||||
	prefix := GetPrefix()
 | 
			
		||||
	ones := int(s[len(prefix)])
 | 
			
		||||
	for idx := 0; idx < ones; idx++ {
 | 
			
		||||
		nid[idx/8] |= 0x80 >> byte(idx%8)
 | 
			
		||||
	}
 | 
			
		||||
	nidOffset := ones + 1
 | 
			
		||||
	addrOffset := 8*len(prefix) + 8
 | 
			
		||||
	for idx := addrOffset; idx < 8*len(s); idx++ {
 | 
			
		||||
		bits := s[idx/8] & (0x80 >> byte(idx%8))
 | 
			
		||||
		bits <<= byte(idx % 8)
 | 
			
		||||
		nidIdx := nidOffset + (idx - addrOffset)
 | 
			
		||||
		bits >>= byte(nidIdx % 8)
 | 
			
		||||
		nid[nidIdx/8] |= bits
 | 
			
		||||
	}
 | 
			
		||||
	maxMask := 8*(len(s)-len(prefix)-1) + ones + 1
 | 
			
		||||
	for idx := 0; idx < maxMask; idx++ {
 | 
			
		||||
		mask[idx/8] |= 0x80 >> byte(idx%8)
 | 
			
		||||
	}
 | 
			
		||||
	return &nid, &mask
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetNodeIDLengthString returns a string representation of the known bits of the NodeID, along with the number of known bits, for use with yggdrasil.Dialer's Dial and DialContext functions.
 | 
			
		||||
func (s *Subnet) GetNodeIDLengthString() string {
 | 
			
		||||
	nid, mask := s.GetNodeIDandMask()
 | 
			
		||||
	l := mask.PrefixLength()
 | 
			
		||||
	return fmt.Sprintf("%s/%d", nid.String(), l)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue