6 "github.com/anacrolix/torrent/merkle"
9 func ValidatePieceLayers(
10 pieceLayers map[string]string,
14 fileTree.Walk(nil, func(path []string, ft *FileTree) {
21 piecesRoot := ft.PiecesRootAsByteArray()
25 filePieceLayers, ok := pieceLayers[string(piecesRoot.Value[:])]
27 // BEP 52: "For each file in the file tree that is larger than the piece size it
28 // contains one string value.". The reference torrent creator in
29 // https://blog.libtorrent.org/2020/09/bittorrent-v2/ also has this. If a file is equal
30 // to or smaller than the piece length, we can just use the pieces root instead of the
32 if ft.File.Length > pieceLength {
33 err = fmt.Errorf("no piece layers for file %q", path)
37 var layerHashes [][32]byte
38 layerHashes, err = merkle.CompactLayerToSliceHashes(filePieceLayers)
39 root := merkle.RootWithPadHash(layerHashes, HashForPiecePad(pieceLength))
40 if root != piecesRoot.Value {
41 err = fmt.Errorf("file %q: expected hash %x got %x", path, piecesRoot.Value, root)
48 // Returns the padding hash for the hash layer corresponding to a piece. It can't be zero because
49 // that's the bottom-most layer (the hashes for the smallest blocks).
50 func HashForPiecePad(pieceLength int64) (hash [32]byte) {
51 // This should be a power of two, and probably checked elsewhere.
52 blocksPerPiece := pieceLength / (1 << 14)
53 blockHashes := make([][32]byte, blocksPerPiece)
54 return merkle.Root(blockHashes)