Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: ID or NodeID #20104

Closed
trung opened this issue Sep 20, 2019 · 2 comments
Closed

Question: ID or NodeID #20104

trung opened this issue Sep 20, 2019 · 2 comments

Comments

@trung
Copy link
Contributor

trung commented Sep 20, 2019

Node identifier is mentioned in 2 places:

  1. As 32-byte ID type which is returned via admin.nodeInfo

    // ID is a unique identifier for each node.
    type ID [32]byte

  2. As 64-byte NodeID type which is used in p2p

    const nodeIDBits = 512
    // NodeID is a unique identifier for each node.
    // The node identifier is a marshaled elliptic curve public key.
    type NodeID [nodeIDBits / 8]byte

Which one is the real node identifier? I would say NodeID. But not sure why there are two.

@dherbst
Copy link
Contributor

dherbst commented Sep 21, 2019

From https://github.com/ethereum/devp2p/wiki/Discovery-Overview#discovery-v4

All nodes are identified by their 64-byte elliptic curve public key. However, the Kademlia table identifies nodes as the 32-byte SHA256 hash of the node id.

And then https://github.com/ethereum/devp2p/wiki/Discovery-Overview#discovery-v5-aka-discv5

'discv5' as a software package will be deprecated in geth.

Further down the page:

Discovery v5 wire protocol will attempt to offer a backwards compatible method of relaying ENRs in FindNode responses. The Kademlia tables should maintain ENR s, not discovery v4 tuples.

and

Discovery v4 accepts the 64-byte public key, the node id, as the target to search for in a FindNode call. It is converted to a SHA256(node id) 32-byte Kademlia id. This means it is practically impossible to implement the Kademlia bucket-refresh scheme by selecting a random id in the bucket range.

If you look at the ENR https://eips.ethereum.org/EIPS/eip-778 which references ethereum/devp2p#43 there is good information on the discussion about the EIP.

@trung
Copy link
Contributor Author

trung commented Sep 25, 2019

Thanks for the detail response. I guess the answer is "both are ok".
However, NodeId in discv5 package is going to be moved/deprecated, despite the fact that its intention is still correct. It represents the node public key and also known as hex node id portion in the enode URL.

ID is used in Kademlia table

// getNode returns the node with the given ID or nil if it isn't in the table.
func (tab *Table) getNode(id enode.ID) *enode.Node {
tab.mutex.Lock()
defer tab.mutex.Unlock()
b := tab.bucket(id)
for _, e := range b.entries {
if e.ID() == id {
return unwrapNode(e)
}
}
return nil
}

Few things I noticed:

  1. NodeId in discv5 can be obtained via:
    // PubkeyID returns a marshaled representation of the given public key.
    func PubkeyID(pub *ecdsa.PublicKey) NodeID {
    var id NodeID
    pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
    if len(pbytes)-1 != len(id) {
    panic(fmt.Errorf("need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes)))
    }
    copy(id[:], pbytes[1:])
    return id
    }

    However, there's another calculation using similar logic but with explicit curve S256()
    func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
    if pub == nil || pub.X == nil || pub.Y == nil {
    return nil
    }
    return elliptic.Marshal(S256(), pub.X, pub.Y)
    }
  2. ID is indeed keccak256() and not SHA256()
    func (V4ID) NodeAddr(r *enr.Record) []byte {
    var pubkey Secp256k1
    err := r.Load(&pubkey)
    if err != nil {
    return nil
    }
    buf := make([]byte, 64)
    math.ReadBits(pubkey.X, buf[:32])
    math.ReadBits(pubkey.Y, buf[32:])
    return crypto.Keccak256(buf)
    }

@trung trung closed this as completed Sep 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants