Refactoring code. Use protocol.HashData and HashSize. Move PublicKey2NodeID into protocol.

This commit is contained in:
Kleissner
2021-10-17 17:15:22 +02:00
parent 39217ab5ef
commit 7be31a9e34
9 changed files with 37 additions and 58 deletions

View File

@@ -10,7 +10,6 @@ import (
"os" "os"
"github.com/PeernetOfficial/core/blockchain" "github.com/PeernetOfficial/core/blockchain"
"github.com/PeernetOfficial/core/protocol"
) )
// UserBlockchain is the user's blockchain and exports functions to directly read and write it // UserBlockchain is the user's blockchain and exports functions to directly read and write it
@@ -22,9 +21,6 @@ const filenameUserBlockchain = "self.blockchain"
// initUserBlockchain initializes the users blockchain. It creates the blockchain file if it does not exist already. // initUserBlockchain initializes the users blockchain. It creates the blockchain file if it does not exist already.
// If it is corrupted, it will log the error and exit the process. // If it is corrupted, it will log the error and exit the process.
func initUserBlockchain() { func initUserBlockchain() {
blockchain.HashFunction = protocol.HashData
blockchain.PublicKey2NodeID = PublicKey2NodeID
var err error var err error
UserBlockchain, err = blockchain.Init(peerPrivateKey, filenameUserBlockchain) UserBlockchain, err = blockchain.Init(peerPrivateKey, filenameUserBlockchain)

View File

@@ -115,7 +115,7 @@ func (peer *PeerInfo) cmdTraverseReceive(msg *MessageTraverse) {
// process the packet and create a virtual peer // process the packet and create a virtual peer
raw := &MessageRaw{SenderPublicKey: senderPublicKey, PacketRaw: *decoded} raw := &MessageRaw{SenderPublicKey: senderPublicKey, PacketRaw: *decoded}
peerV := &PeerInfo{PublicKey: senderPublicKey, connectionActive: nil, connectionLatest: nil, NodeID: PublicKey2NodeID(senderPublicKey), messageSequence: rand.Uint32(), isVirtual: true, targetAddresses: addresses} peerV := &PeerInfo{PublicKey: senderPublicKey, connectionActive: nil, connectionLatest: nil, NodeID: protocol.PublicKey2NodeID(senderPublicKey), messageSequence: rand.Uint32(), isVirtual: true, targetAddresses: addresses}
// process it! // process it!
switch decoded.Command { switch decoded.Command {

View File

@@ -418,7 +418,7 @@ func decodePeerRecord(data []byte, count int) (hash2Peers []Hash2Peer, read int,
return nil, 0, false return nil, 0, false
} }
peer.NodeID = PublicKey2NodeID(peer.PublicKey) peer.NodeID = protocol.PublicKey2NodeID(peer.PublicKey)
if reason == 0 { // Peer was returned because it is close to the requested hash if reason == 0 { // Peer was returned because it is close to the requested hash
hash2Peer.Closest = append(hash2Peer.Closest, peer) hash2Peer.Closest = append(hash2Peer.Closest, peer)

View File

@@ -32,7 +32,7 @@ func initPeerID() {
configPK, err := hex.DecodeString(config.PrivateKey) configPK, err := hex.DecodeString(config.PrivateKey)
if err == nil { if err == nil {
peerPrivateKey, peerPublicKey = btcec.PrivKeyFromBytes(btcec.S256(), configPK) peerPrivateKey, peerPublicKey = btcec.PrivKeyFromBytes(btcec.S256(), configPK)
nodeID = PublicKey2NodeID(peerPublicKey) nodeID = protocol.PublicKey2NodeID(peerPublicKey)
if config.AutoUpdateSeedList { if config.AutoUpdateSeedList {
configUpdateSeedList() configUpdateSeedList()
@@ -51,7 +51,7 @@ func initPeerID() {
Filters.LogError("initPeerID", "generating public-private key pairs: %s\n", err.Error()) Filters.LogError("initPeerID", "generating public-private key pairs: %s\n", err.Error())
os.Exit(1) os.Exit(1)
} }
nodeID = PublicKey2NodeID(peerPublicKey) nodeID = protocol.PublicKey2NodeID(peerPublicKey)
// save the newly generated private key into the config // save the newly generated private key into the config
config.PrivateKey = hex.EncodeToString(peerPrivateKey.Serialize()) config.PrivateKey = hex.EncodeToString(peerPrivateKey.Serialize())
@@ -127,7 +127,7 @@ func PeerlistAdd(PublicKey *btcec.PublicKey, connections ...*Connection) (peer *
return peer, false return peer, false
} }
peer = &PeerInfo{PublicKey: PublicKey, connectionActive: connections, connectionLatest: connections[0], NodeID: PublicKey2NodeID(PublicKey), messageSequence: rand.Uint32()} peer = &PeerInfo{PublicKey: PublicKey, connectionActive: connections, connectionLatest: connections[0], NodeID: protocol.PublicKey2NodeID(PublicKey), messageSequence: rand.Uint32()}
_, peer.IsRootPeer = rootPeers[publicKeyCompressed] _, peer.IsRootPeer = rootPeers[publicKeyCompressed]
peerList[publicKeyCompressed] = peer peerList[publicKeyCompressed] = peer
@@ -197,11 +197,6 @@ func publicKey2Compressed(publicKey *btcec.PublicKey) [btcec.PubKeyBytesLenCompr
return key return key
} }
// PublicKey2NodeID translates the Public Key into the node ID used in the Kademlia network.
func PublicKey2NodeID(publicKey *btcec.PublicKey) (nodeID []byte) {
return protocol.HashData(publicKey.SerializeCompressed())
}
// records2Nodes translates infoPeer structures to nodes. If the reported nodes are not in the peer table, it will create temporary PeerInfo structures. // records2Nodes translates infoPeer structures to nodes. If the reported nodes are not in the peer table, it will create temporary PeerInfo structures.
// LastContact is passed on in the Node.LastSeen field. // LastContact is passed on in the Node.LastSeen field.
func records2Nodes(records []PeerRecord, peerSource *PeerInfo) (nodes []*dht.Node) { func records2Nodes(records []PeerRecord, peerSource *PeerInfo) (nodes []*dht.Node) {
@@ -222,7 +217,7 @@ func records2Nodes(records []PeerRecord, peerSource *PeerInfo) (nodes []*dht.Nod
continue continue
} }
peer = &PeerInfo{PublicKey: record.PublicKey, connectionActive: nil, connectionLatest: nil, NodeID: PublicKey2NodeID(record.PublicKey), messageSequence: rand.Uint32(), isVirtual: true, targetAddresses: addresses, traversePeer: peerSource} peer = &PeerInfo{PublicKey: record.PublicKey, connectionActive: nil, connectionLatest: nil, NodeID: protocol.PublicKey2NodeID(record.PublicKey), messageSequence: rand.Uint32(), isVirtual: true, targetAddresses: addresses, traversePeer: peerSource}
} }
nodes = append(nodes, &dht.Node{ID: peer.NodeID, LastSeen: record.LastContactT, Info: peer}) nodes = append(nodes, &dht.Node{ID: peer.NodeID, LastSeen: record.LastContactT, Info: peer})

View File

@@ -31,6 +31,7 @@ import (
"errors" "errors"
"math" "math"
"github.com/PeernetOfficial/core/protocol"
"github.com/google/uuid" "github.com/google/uuid"
) )
@@ -64,8 +65,8 @@ func decodeBlockRecordFiles(recordsRaw []BlockRecordRaw, nodeID []byte) (files [
} }
file := BlockRecordFile{NodeID: nodeID} file := BlockRecordFile{NodeID: nodeID}
file.Hash = make([]byte, hashSize) file.Hash = make([]byte, protocol.HashSize)
copy(file.Hash, record.Data[0:0+hashSize]) copy(file.Hash, record.Data[0:0+protocol.HashSize])
copy(file.ID[:], record.Data[32:32+16]) copy(file.ID[:], record.Data[32:32+16])
file.Type = record.Data[48] file.Type = record.Data[48]
file.Format = binary.LittleEndian.Uint16(record.Data[49 : 49+2]) file.Format = binary.LittleEndian.Uint16(record.Data[49 : 49+2])
@@ -152,7 +153,7 @@ func encodeBlockRecordFiles(files []BlockRecordFile) (recordsRaw []BlockRecordRa
for n := range files { for n := range files {
data := make([]byte, 61) data := make([]byte, 61)
if len(files[n].Hash) != hashSize { if len(files[n].Hash) != protocol.HashSize {
return nil, errors.New("encodeBlockRecords invalid file hash") return nil, errors.New("encodeBlockRecords invalid file hash")
} }

View File

@@ -22,6 +22,7 @@ import (
"errors" "errors"
"time" "time"
"github.com/PeernetOfficial/core/protocol"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
) )
@@ -56,15 +57,15 @@ func decodeBlock(raw []byte) (block *Block, err error) {
signature := raw[0 : 0+65] signature := raw[0 : 0+65]
block.OwnerPublicKey, _, err = btcec.RecoverCompact(btcec.S256(), signature, HashFunction(raw[65:])) block.OwnerPublicKey, _, err = btcec.RecoverCompact(btcec.S256(), signature, protocol.HashData(raw[65:]))
if err != nil { if err != nil {
return nil, err return nil, err
} }
block.NodeID = PublicKey2NodeID(block.OwnerPublicKey) block.NodeID = protocol.PublicKey2NodeID(block.OwnerPublicKey)
block.LastBlockHash = make([]byte, hashSize) block.LastBlockHash = make([]byte, protocol.HashSize)
copy(block.LastBlockHash, raw[65:65+hashSize]) copy(block.LastBlockHash, raw[65:65+protocol.HashSize])
block.BlockchainVersion = binary.LittleEndian.Uint64(raw[97 : 97+8]) block.BlockchainVersion = binary.LittleEndian.Uint64(raw[97 : 97+8])
block.Number = uint64(binary.LittleEndian.Uint32(raw[105 : 105+4])) // for now 32-bit in protocol block.Number = uint64(binary.LittleEndian.Uint32(raw[105 : 105+4])) // for now 32-bit in protocol
@@ -104,7 +105,7 @@ func encodeBlock(block *Block, ownerPrivateKey *btcec.PrivateKey) (raw []byte, e
var buffer bytes.Buffer var buffer bytes.Buffer
buffer.Write(make([]byte, 65)) // Signature, filled at the end buffer.Write(make([]byte, 65)) // Signature, filled at the end
if block.Number > 0 && len(block.LastBlockHash) != hashSize { if block.Number > 0 && len(block.LastBlockHash) != protocol.HashSize {
return nil, errors.New("encodeBlock invalid last block hash") return nil, errors.New("encodeBlock invalid last block hash")
} else if block.Number == 0 { // Block 0: Empty last hash } else if block.Number == 0 { // Block 0: Empty last hash
block.LastBlockHash = make([]byte, 32) block.LastBlockHash = make([]byte, 32)
@@ -151,7 +152,7 @@ func encodeBlock(block *Block, ownerPrivateKey *btcec.PrivateKey) (raw []byte, e
binary.LittleEndian.PutUint16(raw[113:113+2], countRecords) // Count of records binary.LittleEndian.PutUint16(raw[113:113+2], countRecords) // Count of records
// signature is last // signature is last
signature, err := btcec.SignCompact(btcec.S256(), ownerPrivateKey, HashFunction(raw[65:]), true) signature, err := btcec.SignCompact(btcec.S256(), ownerPrivateKey, protocol.HashData(raw[65:]), true)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -22,6 +22,7 @@ import (
"errors" "errors"
"sync" "sync"
"github.com/PeernetOfficial/core/protocol"
"github.com/PeernetOfficial/core/store" "github.com/PeernetOfficial/core/store"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
) )
@@ -41,15 +42,6 @@ type Blockchain struct {
sync.Mutex // synchronized access to the header sync.Mutex // synchronized access to the header
} }
// HashFunction must be set by the caller to the hash function (blake3) that shall be used.
var HashFunction func(data []byte) (hash []byte)
// hashSize is the blake3 digest size in bytes
const hashSize = 32
// PublicKey2NodeID must be set by the caller to the function generating the node ID from the public key. Typically it would use the HashFunction.
var PublicKey2NodeID func(publicKey *btcec.PublicKey) (nodeID []byte)
// Init initializes the given blockchain. It creates the blockchain file if it does not exist already. // Init initializes the given blockchain. It creates the blockchain file if it does not exist already.
func Init(privateKey *btcec.PrivateKey, path string) (blockchain *Blockchain, err error) { func Init(privateKey *btcec.PrivateKey, path string) (blockchain *Blockchain, err error) {
blockchain = &Blockchain{privateKey: privateKey, path: path} blockchain = &Blockchain{privateKey: privateKey, path: path}
@@ -103,7 +95,7 @@ func (blockchain *Blockchain) headerRead() (found bool, err error) {
return true, errors.New("future blockchain format not supported. You must go back to the future!") return true, errors.New("future blockchain format not supported. You must go back to the future!")
} }
blockchain.publicKey, _, err = btcec.RecoverCompact(btcec.S256(), signature, HashFunction(buffer[0:18])) blockchain.publicKey, _, err = btcec.RecoverCompact(btcec.S256(), signature, protocol.HashData(buffer[0:18]))
return return
} }
@@ -118,7 +110,7 @@ func (blockchain *Blockchain) headerWrite(height, version uint64) (err error) {
binary.LittleEndian.PutUint64(buffer[8:16], version) binary.LittleEndian.PutUint64(buffer[8:16], version)
binary.LittleEndian.PutUint16(buffer[16:18], 0) // Current format is 0 binary.LittleEndian.PutUint16(buffer[16:18], 0) // Current format is 0
signature, err := btcec.SignCompact(btcec.S256(), blockchain.privateKey, HashFunction(buffer[0:18]), true) signature, err := btcec.SignCompact(btcec.S256(), blockchain.privateKey, protocol.HashData(buffer[0:18]), true)
if err != nil { if err != nil {
return err return err
@@ -250,7 +242,7 @@ func (blockchain *Blockchain) IterateDeleteRecord(callback func(record *BlockRec
// store the block // store the block
blockchain.database.Set(blockNumberToKey(block.Number), raw) blockchain.database.Set(blockNumberToKey(block.Number), raw)
lastBlockHash = HashFunction(raw) lastBlockHash = protocol.HashData(raw)
} }
// update the blockchain header in the database // update the blockchain header in the database
@@ -293,7 +285,7 @@ func (blockchain *Blockchain) Append(RecordsRaw []BlockRecordRaw) (newHeight, ne
return 0, 0, StatusBlockNotFound return 0, 0, StatusBlockNotFound
} }
block.LastBlockHash = HashFunction(previousBlockRaw) block.LastBlockHash = protocol.HashData(previousBlockRaw)
} }
block.Number = blockchain.height block.Number = blockchain.height

View File

@@ -5,13 +5,12 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/PeernetOfficial/core/protocol"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
"github.com/google/uuid" "github.com/google/uuid"
"lukechampine.com/blake3"
) )
func TestBlockEncoding(t *testing.T) { func TestBlockEncoding(t *testing.T) {
initRequiredFunctions()
privateKey, err := btcec.NewPrivateKey(btcec.S256()) privateKey, err := btcec.NewPrivateKey(btcec.S256())
if err != nil { if err != nil {
fmt.Printf("Error: %s\n", err.Error()) fmt.Printf("Error: %s\n", err.Error())
@@ -20,11 +19,11 @@ func TestBlockEncoding(t *testing.T) {
encoded1, _ := encodeBlockRecordProfile([]BlockRecordProfile{ProfileFieldFromText(ProfileName, "Test User 1")}) encoded1, _ := encodeBlockRecordProfile([]BlockRecordProfile{ProfileFieldFromText(ProfileName, "Test User 1")})
file1 := BlockRecordFile{Hash: testHashData([]byte("Test data")), Type: testTypeText, Format: testFormatText, Size: 9, ID: uuid.New()} file1 := BlockRecordFile{Hash: protocol.HashData([]byte("Test data")), Type: testTypeText, Format: testFormatText, Size: 9, ID: uuid.New()}
file1.Tags = append(file1.Tags, TagFromText(TagName, "Filename 1.txt")) file1.Tags = append(file1.Tags, TagFromText(TagName, "Filename 1.txt"))
file1.Tags = append(file1.Tags, TagFromText(TagFolder, "documents\\sub folder")) file1.Tags = append(file1.Tags, TagFromText(TagFolder, "documents\\sub folder"))
file2 := BlockRecordFile{Hash: testHashData([]byte("Test data 2!")), Type: testTypeText, Format: testFormatText, Size: 10, ID: uuid.New()} file2 := BlockRecordFile{Hash: protocol.HashData([]byte("Test data 2!")), Type: testTypeText, Format: testFormatText, Size: 10, ID: uuid.New()}
file2.Tags = append(file2.Tags, TagFromText(TagName, "Filename 2.txt")) file2.Tags = append(file2.Tags, TagFromText(TagName, "Filename 2.txt"))
file2.Tags = append(file2.Tags, TagFromText(TagFolder, "documents\\sub folder")) file2.Tags = append(file2.Tags, TagFromText(TagFolder, "documents\\sub folder"))
@@ -68,13 +67,6 @@ func TestBlockEncoding(t *testing.T) {
} }
} }
func initRequiredFunctions() {
HashFunction = testHashData
PublicKey2NodeID = func(publicKey *btcec.PublicKey) (nodeID []byte) {
return testHashData(publicKey.SerializeCompressed())
}
}
func initTestPrivateKey() (blockchain *Blockchain, err error) { func initTestPrivateKey() (blockchain *Blockchain, err error) {
// use static test key, otherwise tests will be inconsistent (would otherwise fail to open blockchain database) // use static test key, otherwise tests will be inconsistent (would otherwise fail to open blockchain database)
privateKeyTestA := "d65da474861d826edd29c1307f1250d79e9dbf84e3a2449022658445c8d8ed63" privateKeyTestA := "d65da474861d826edd29c1307f1250d79e9dbf84e3a2449022658445c8d8ed63"
@@ -83,8 +75,6 @@ func initTestPrivateKey() (blockchain *Blockchain, err error) {
fmt.Printf("Loaded public key: %s\n", hex.EncodeToString(peerPublicKey.SerializeCompressed())) fmt.Printf("Loaded public key: %s\n", hex.EncodeToString(peerPublicKey.SerializeCompressed()))
initRequiredFunctions()
return Init(peerPrivateKey, "test.blockchain") return Init(peerPrivateKey, "test.blockchain")
} }
@@ -94,7 +84,7 @@ func TestBlockchainAdd(t *testing.T) {
return return
} }
file1 := BlockRecordFile{Hash: testHashData([]byte("Test data")), Type: testTypeText, Format: testFormatText, Size: 9, ID: uuid.New()} file1 := BlockRecordFile{Hash: protocol.HashData([]byte("Test data")), Type: testTypeText, Format: testFormatText, Size: 9, ID: uuid.New()}
file1.Tags = append(file1.Tags, TagFromText(TagName, "Filename 1.txt")) file1.Tags = append(file1.Tags, TagFromText(TagName, "Filename 1.txt"))
file1.Tags = append(file1.Tags, TagFromText(TagFolder, "documents\\sub folder")) file1.Tags = append(file1.Tags, TagFromText(TagFolder, "documents\\sub folder"))
@@ -177,7 +167,7 @@ func TestBlockchainDelete(t *testing.T) {
} }
// test add file // test add file
file1 := BlockRecordFile{Hash: testHashData([]byte("Test data")), Type: testTypeText, Format: testFormatText, Size: 9, ID: uuid.New()} file1 := BlockRecordFile{Hash: protocol.HashData([]byte("Test data")), Type: testTypeText, Format: testFormatText, Size: 9, ID: uuid.New()}
file1.Tags = append(file1.Tags, TagFromText(TagName, "Test file to be deleted.txt")) file1.Tags = append(file1.Tags, TagFromText(TagName, "Test file to be deleted.txt"))
file1.Tags = append(file1.Tags, TagFromText(TagFolder, "documents\\sub folder")) file1.Tags = append(file1.Tags, TagFromText(TagFolder, "documents\\sub folder"))
@@ -256,10 +246,5 @@ func printProfileField(field BlockRecordProfile) {
} }
} }
func testHashData(data []byte) (hash []byte) {
hash32 := blake3.Sum256(data)
return hash32[:]
}
const testTypeText = 1 const testTypeText = 1
const testFormatText = 10 const testFormatText = 10

View File

@@ -6,7 +6,10 @@ Author: Peter Kleissner
package protocol package protocol
import "lukechampine.com/blake3" import (
"github.com/btcsuite/btcd/btcec"
"lukechampine.com/blake3"
)
// HashData abstracts the hash function. // HashData abstracts the hash function.
func HashData(data []byte) (hash []byte) { func HashData(data []byte) (hash []byte) {
@@ -16,3 +19,9 @@ func HashData(data []byte) (hash []byte) {
// HashSize is blake3 hash digest size = 256 bits // HashSize is blake3 hash digest size = 256 bits
const HashSize = 32 const HashSize = 32
// PublicKey2NodeID translates the Public Key into the node ID used in the Kademlia network.
// It is also referenced in various other places including blockchain data at runtime. The node ID identifies the owner.
func PublicKey2NodeID(publicKey *btcec.PublicKey) (nodeID []byte) {
return HashData(publicKey.SerializeCompressed())
}