diff --git a/Blockchain.go b/Blockchain.go index a2ea0cc..d9324a6 100644 --- a/Blockchain.go +++ b/Blockchain.go @@ -10,7 +10,6 @@ import ( "os" "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 @@ -22,9 +21,6 @@ const filenameUserBlockchain = "self.blockchain" // 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. func initUserBlockchain() { - blockchain.HashFunction = protocol.HashData - blockchain.PublicKey2NodeID = PublicKey2NodeID - var err error UserBlockchain, err = blockchain.Init(peerPrivateKey, filenameUserBlockchain) diff --git a/Command Traverse.go b/Command Traverse.go index cae129f..1fd9bd3 100644 --- a/Command Traverse.go +++ b/Command Traverse.go @@ -115,7 +115,7 @@ func (peer *PeerInfo) cmdTraverseReceive(msg *MessageTraverse) { // process the packet and create a virtual peer 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! switch decoded.Command { diff --git a/Message Encoding.go b/Message Encoding.go index ef3b9e5..e768bba 100644 --- a/Message Encoding.go +++ b/Message Encoding.go @@ -418,7 +418,7 @@ func decodePeerRecord(data []byte, count int) (hash2Peers []Hash2Peer, read int, 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 hash2Peer.Closest = append(hash2Peer.Closest, peer) diff --git a/Peer ID.go b/Peer ID.go index 7333fb7..765600e 100644 --- a/Peer ID.go +++ b/Peer ID.go @@ -32,7 +32,7 @@ func initPeerID() { configPK, err := hex.DecodeString(config.PrivateKey) if err == nil { peerPrivateKey, peerPublicKey = btcec.PrivKeyFromBytes(btcec.S256(), configPK) - nodeID = PublicKey2NodeID(peerPublicKey) + nodeID = protocol.PublicKey2NodeID(peerPublicKey) if config.AutoUpdateSeedList { configUpdateSeedList() @@ -51,7 +51,7 @@ func initPeerID() { Filters.LogError("initPeerID", "generating public-private key pairs: %s\n", err.Error()) os.Exit(1) } - nodeID = PublicKey2NodeID(peerPublicKey) + nodeID = protocol.PublicKey2NodeID(peerPublicKey) // save the newly generated private key into the config config.PrivateKey = hex.EncodeToString(peerPrivateKey.Serialize()) @@ -127,7 +127,7 @@ func PeerlistAdd(PublicKey *btcec.PublicKey, connections ...*Connection) (peer * 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] peerList[publicKeyCompressed] = peer @@ -197,11 +197,6 @@ func publicKey2Compressed(publicKey *btcec.PublicKey) [btcec.PubKeyBytesLenCompr 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. // LastContact is passed on in the Node.LastSeen field. func records2Nodes(records []PeerRecord, peerSource *PeerInfo) (nodes []*dht.Node) { @@ -222,7 +217,7 @@ func records2Nodes(records []PeerRecord, peerSource *PeerInfo) (nodes []*dht.Nod 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}) diff --git a/blockchain/Block Record File.go b/blockchain/Block Record File.go index dd0623b..4c7e400 100644 --- a/blockchain/Block Record File.go +++ b/blockchain/Block Record File.go @@ -31,6 +31,7 @@ import ( "errors" "math" + "github.com/PeernetOfficial/core/protocol" "github.com/google/uuid" ) @@ -64,8 +65,8 @@ func decodeBlockRecordFiles(recordsRaw []BlockRecordRaw, nodeID []byte) (files [ } file := BlockRecordFile{NodeID: nodeID} - file.Hash = make([]byte, hashSize) - copy(file.Hash, record.Data[0:0+hashSize]) + file.Hash = make([]byte, protocol.HashSize) + copy(file.Hash, record.Data[0:0+protocol.HashSize]) copy(file.ID[:], record.Data[32:32+16]) file.Type = record.Data[48] file.Format = binary.LittleEndian.Uint16(record.Data[49 : 49+2]) @@ -152,7 +153,7 @@ func encodeBlockRecordFiles(files []BlockRecordFile) (recordsRaw []BlockRecordRa for n := range files { 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") } diff --git a/blockchain/Block.go b/blockchain/Block.go index 600f5a3..959c4ea 100644 --- a/blockchain/Block.go +++ b/blockchain/Block.go @@ -22,6 +22,7 @@ import ( "errors" "time" + "github.com/PeernetOfficial/core/protocol" "github.com/btcsuite/btcd/btcec" ) @@ -56,15 +57,15 @@ func decodeBlock(raw []byte) (block *Block, err error) { 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 { return nil, err } - block.NodeID = PublicKey2NodeID(block.OwnerPublicKey) + block.NodeID = protocol.PublicKey2NodeID(block.OwnerPublicKey) - block.LastBlockHash = make([]byte, hashSize) - copy(block.LastBlockHash, raw[65:65+hashSize]) + block.LastBlockHash = make([]byte, protocol.HashSize) + copy(block.LastBlockHash, raw[65:65+protocol.HashSize]) 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 @@ -104,7 +105,7 @@ func encodeBlock(block *Block, ownerPrivateKey *btcec.PrivateKey) (raw []byte, e var buffer bytes.Buffer 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") } else if block.Number == 0 { // Block 0: Empty last hash 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 // 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 { return nil, err } diff --git a/blockchain/Blockchain.go b/blockchain/Blockchain.go index d11f882..b44a072 100644 --- a/blockchain/Blockchain.go +++ b/blockchain/Blockchain.go @@ -22,6 +22,7 @@ import ( "errors" "sync" + "github.com/PeernetOfficial/core/protocol" "github.com/PeernetOfficial/core/store" "github.com/btcsuite/btcd/btcec" ) @@ -41,15 +42,6 @@ type Blockchain struct { 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. func Init(privateKey *btcec.PrivateKey, path string) (blockchain *Blockchain, err error) { 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!") } - 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 } @@ -118,7 +110,7 @@ func (blockchain *Blockchain) headerWrite(height, version uint64) (err error) { binary.LittleEndian.PutUint64(buffer[8:16], version) 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 { return err @@ -250,7 +242,7 @@ func (blockchain *Blockchain) IterateDeleteRecord(callback func(record *BlockRec // store the block blockchain.database.Set(blockNumberToKey(block.Number), raw) - lastBlockHash = HashFunction(raw) + lastBlockHash = protocol.HashData(raw) } // update the blockchain header in the database @@ -293,7 +285,7 @@ func (blockchain *Blockchain) Append(RecordsRaw []BlockRecordRaw) (newHeight, ne return 0, 0, StatusBlockNotFound } - block.LastBlockHash = HashFunction(previousBlockRaw) + block.LastBlockHash = protocol.HashData(previousBlockRaw) } block.Number = blockchain.height diff --git a/blockchain/Test_test.go b/blockchain/Test_test.go index 1e1a17d..db9e66f 100644 --- a/blockchain/Test_test.go +++ b/blockchain/Test_test.go @@ -5,13 +5,12 @@ import ( "fmt" "testing" + "github.com/PeernetOfficial/core/protocol" "github.com/btcsuite/btcd/btcec" "github.com/google/uuid" - "lukechampine.com/blake3" ) func TestBlockEncoding(t *testing.T) { - initRequiredFunctions() privateKey, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { fmt.Printf("Error: %s\n", err.Error()) @@ -20,11 +19,11 @@ func TestBlockEncoding(t *testing.T) { 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(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(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) { // use static test key, otherwise tests will be inconsistent (would otherwise fail to open blockchain database) privateKeyTestA := "d65da474861d826edd29c1307f1250d79e9dbf84e3a2449022658445c8d8ed63" @@ -83,8 +75,6 @@ func initTestPrivateKey() (blockchain *Blockchain, err error) { fmt.Printf("Loaded public key: %s\n", hex.EncodeToString(peerPublicKey.SerializeCompressed())) - initRequiredFunctions() - return Init(peerPrivateKey, "test.blockchain") } @@ -94,7 +84,7 @@ func TestBlockchainAdd(t *testing.T) { 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(TagFolder, "documents\\sub folder")) @@ -177,7 +167,7 @@ func TestBlockchainDelete(t *testing.T) { } // 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(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 testFormatText = 10 diff --git a/protocol/Hash.go b/protocol/Hash.go index 83eb9dc..ae98ddd 100644 --- a/protocol/Hash.go +++ b/protocol/Hash.go @@ -6,7 +6,10 @@ Author: Peter Kleissner package protocol -import "lukechampine.com/blake3" +import ( + "github.com/btcsuite/btcd/btcec" + "lukechampine.com/blake3" +) // HashData abstracts the hash function. func HashData(data []byte) (hash []byte) { @@ -16,3 +19,9 @@ func HashData(data []byte) (hash []byte) { // HashSize is blake3 hash digest size = 256 bits 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()) +}