From a34509c0bf9f321804e37f5b0c731805ece46e63 Mon Sep 17 00:00:00 2001 From: Kleissner Date: Tue, 7 Dec 2021 21:43:47 +0100 Subject: [PATCH] New command: get block --- Block Transfer.go | 119 ++++++++++++++++++++++++++++++++++++++++++++++ Command Line.go | 40 ++++++++++++++++ go.mod | 2 +- go.sum | 4 +- 4 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 Block Transfer.go diff --git a/Block Transfer.go b/Block Transfer.go new file mode 100644 index 0000000..2aa11b7 --- /dev/null +++ b/Block Transfer.go @@ -0,0 +1,119 @@ +/* +File Name: Block Transfer.go +Copyright: 2021 Peernet Foundation s.r.o. +Author: Peter Kleissner +*/ + +package main + +import ( + "encoding/hex" + "fmt" + + "github.com/PeernetOfficial/core" + "github.com/PeernetOfficial/core/blockchain" + "github.com/PeernetOfficial/core/protocol" +) + +const maxBlockSize = 1 * 1024 * 1024 + +func blockTransfer(peer *core.PeerInfo, blockNumber uint64) { + conn, _, err := peer.BlockTransferRequest(peer.PublicKey, 1, maxBlockSize, []protocol.BlockRange{{Offset: uint64(blockNumber), Limit: 1}}) + if err != nil { + fmt.Printf("Error starting block transfer: %s\n", err.Error()) + return + } + + data, targetBlock, blockSize, availability, err := protocol.BlockTransferReadBlock(conn, maxBlockSize) + conn.Close() + + if err != nil { + fmt.Printf("Error reading block (indicated block size %d) from remote: %s\n", blockSize, err.Error()) + return + } else if targetBlock.Limit != 1 || targetBlock.Offset != blockNumber { + fmt.Printf("Error mismatch requested block %d with returned block %d (count %d)\n", blockNumber, targetBlock.Offset, targetBlock.Limit) + return + } else if availability == protocol.GetBlockStatusNotAvailable { // Block range not available + fmt.Printf("Error requested block %d not available\n", blockNumber) + return + } else if availability == protocol.GetBlockStatusSizeExceed { // Block range exceeds size limit + fmt.Printf("Error block %d reported by remote as exceeding size %d (limit %d)\n", blockNumber, blockSize, maxBlockSize) + return + } else if availability != protocol.GetBlockStatusAvailable { + fmt.Printf("Error requested block %d unknown availability indicator %d\n", blockNumber, availability) + return + } + + decoded, status, err := blockchain.DecodeBlockRaw(data) + + if err != nil { + fmt.Printf("Error decoding block: %s\n", err.Error()) + return + } else if status != blockchain.StatusOK { + fmt.Printf("Error decoding block status is %d\n", status) + return + } + + fmt.Printf("Block %d from %s: version %d, number %d, block size %d, decoded %d records\n", blockNumber, hex.EncodeToString(peer.PublicKey.SerializeCompressed()), decoded.BlockchainVersion, decoded.Number, len(data), len(decoded.RecordsDecoded)) + + for _, decodedR := range decoded.RecordsDecoded { + if file, ok := decodedR.(blockchain.BlockRecordFile); ok { + blockPrintFile(file) + } else if recordsProfile, ok := decodedR.([]blockchain.BlockRecordProfile); ok { + for _, recordP := range recordsProfile { + blockPrintProfileField(recordP) + } + } else { + fmt.Printf("* Unknown record.\n") + } + } +} + +func blockPrintFile(file blockchain.BlockRecordFile) { + fmt.Printf("* File %s\n", file.ID.String()) + fmt.Printf(" Size %d\n", file.Size) + fmt.Printf(" Type %d\n", file.Type) + fmt.Printf(" Format %d\n", file.Format) + fmt.Printf(" Hash %s\n", hex.EncodeToString(file.Hash)) + fmt.Printf(" Merkle Root Hash %s\n", hex.EncodeToString(file.MerkleRootHash)) + fmt.Printf(" Fragment Size %d\n", file.FragmentSize) + + for _, tag := range file.Tags { + switch tag.Type { + case blockchain.TagName: + fmt.Printf(" Name %s\n", tag.Text()) + case blockchain.TagFolder: + fmt.Printf(" Folder %s\n", tag.Text()) + case blockchain.TagDescription: + fmt.Printf(" Description %s\n", tag.Text()) + } + } +} + +func blockPrintProfileField(field blockchain.BlockRecordProfile) { + switch field.Type { + case blockchain.ProfileName: + fmt.Printf("* Profile Name = %s\n", string(field.Data)) + + case blockchain.ProfileEmail: + fmt.Printf("* Profile Email = %s\n", string(field.Data)) + + case blockchain.ProfileWebsite: + fmt.Printf("* Profile Website = %s\n", string(field.Data)) + + case blockchain.ProfileTwitter: + fmt.Printf("* Profile Twitter = %s\n", string(field.Data)) + + case blockchain.ProfileYouTube: + fmt.Printf("* Profile YouTube = %s\n", string(field.Data)) + + case blockchain.ProfileAddress: + fmt.Printf("* Profile Address = %s\n", string(field.Data)) + + case blockchain.ProfilePicture: + fmt.Printf("* Profile Picture. Size %d\n", len(field.Data)) + + default: + fmt.Printf("* Field %d = %s\n", field.Type, hex.EncodeToString(field.Data)) + } +} diff --git a/Command Line.go b/Command Line.go index 646e111..626af1c 100644 --- a/Command Line.go +++ b/Command Line.go @@ -44,6 +44,7 @@ func showHelp(output io.Writer) { "warehouse store Store data into local warehouse\n"+ "dht get Get data via DHT by hash\n"+ "dht store Store data into DHT\n"+ + "get block Get block from remote peer\n"+ "log error Set error log output\n"+ "\n") } @@ -400,6 +401,45 @@ func userCommands(input io.Reader, output io.Writer, terminateSignal chan struct } go transferCompareFile(peer, fileHash) + + case "get block": + fmt.Fprintf(output, "Enter peer ID or node ID:\n") + nodeIDA, _, terminate := getUserOptionString(reader, terminateSignal) + if terminate { + return + } + fmt.Fprintf(output, "Enter block number:\n") + blockNumber, _, terminate := getUserOptionInt(reader, terminateSignal) + if terminate { + return + } + + nodeID, valid2 := webapi.DecodeBlake3Hash(nodeIDA) + publicKey, err3 := core.PublicKeyFromPeerID(nodeIDA) + + if !valid2 && err3 != nil { + fmt.Fprintf(output, "Invalid peer ID or node ID.\n") + break + } else if blockNumber < 0 { + fmt.Fprintf(output, "Invalid block number.\n") + } + + var peer *core.PeerInfo + var err error + timeout := time.Second * 10 + + if valid2 { + peer, err = webapi.PeerConnectNode(nodeID, timeout) + } else if err3 == nil { + peer, err = webapi.PeerConnectPublicKey(publicKey, timeout) + } + if err != nil { + fmt.Fprintf(output, "Could not connect to peer: %s\n", err.Error()) + break + } + + go blockTransfer(peer, uint64(blockNumber)) + } } } diff --git a/go.mod b/go.mod index 2cea459..1376737 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/PeernetOfficial/Cmd go 1.16 require ( - github.com/PeernetOfficial/core v0.0.0-20211130025319-68d8c1187273 + github.com/PeernetOfficial/core v0.0.0-20211204025234-34e48c09df12 github.com/google/uuid v1.3.0 github.com/gorilla/websocket v1.4.3-0.20210424162022-e8629af678b7 ) diff --git a/go.sum b/go.sum index ef0dce3..242be8a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/PeernetOfficial/core v0.0.0-20211130025319-68d8c1187273 h1:WZKBtdXfNBxy06Dyf+aPXsA+0fIBwNNGD7O5FnmiIVo= -github.com/PeernetOfficial/core v0.0.0-20211130025319-68d8c1187273/go.mod h1:0D/jIDYdV0WXg5WACS+fR5keafLhYB89WUs6ZEE8t4Y= +github.com/PeernetOfficial/core v0.0.0-20211204025234-34e48c09df12 h1:mOz4+1+2P5cJoRYUDesXnNvKX3qp0TUeX81oYjn3alQ= +github.com/PeernetOfficial/core v0.0.0-20211204025234-34e48c09df12/go.mod h1:0D/jIDYdV0WXg5WACS+fR5keafLhYB89WUs6ZEE8t4Y= github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w= github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=