package guts
import (
"math/bits"
"sync"
)
const (
FlagChunkStart = 1 << iota
FlagChunkEnd
FlagParent
FlagRoot
FlagKeyedHash
FlagDeriveKeyContext
FlagDeriveKeyMaterial
BlockSize = 64
ChunkSize = 1024
MaxSIMD = 16
)
var IV = [8 ]uint32 {
0x6A09E667 , 0xBB67AE85 , 0x3C6EF372 , 0xA54FF53A ,
0x510E527F , 0x9B05688C , 0x1F83D9AB , 0x5BE0CD19 ,
}
type Node struct {
CV [8 ]uint32
Block [16 ]uint32
Counter uint64
BlockLen uint32
Flags uint32
}
func ParentNode (left , right [8 ]uint32 , key *[8 ]uint32 , flags uint32 ) Node {
n := Node {
CV : *key ,
Counter : 0 ,
BlockLen : BlockSize ,
Flags : flags | FlagParent ,
}
copy (n .Block [:8 ], left [:])
copy (n .Block [8 :], right [:])
return n
}
func Eigentrees (counter uint64 , chunks uint64 ) (trees []int ) {
for i := counter ; i < counter +chunks ; {
bite := min (bits .TrailingZeros64 (i ), bits .Len64 (counter +chunks -i )-1 )
trees = append (trees , bite )
i += 1 << bite
}
return
}
func CompressEigentree (buf []byte , key *[8 ]uint32 , counter uint64 , flags uint32 ) Node {
if numChunks := uint64 (len (buf ) / ChunkSize ); bits .OnesCount64 (numChunks ) != 1 {
panic ("non-power-of-two eigentree size" )
} else if numChunks == 1 {
return CompressChunk (buf , key , counter , flags )
} else if numChunks <= MaxSIMD {
buflen := len (buf )
if cap (buf ) < MaxSIMD *ChunkSize {
buf = append (buf , make ([]byte , MaxSIMD *ChunkSize -len (buf ))...)
}
return CompressBuffer ((*[MaxSIMD * ChunkSize ]byte )(buf [:MaxSIMD *ChunkSize ]), buflen , key , counter , flags )
} else {
cvs := make ([][8 ]uint32 , numChunks /MaxSIMD )
var wg sync .WaitGroup
for i := range cvs {
wg .Add (1 )
go func (i uint64 ) {
defer wg .Done ()
cvs [i ] = ChainingValue (CompressBuffer ((*[MaxSIMD * ChunkSize ]byte )(buf [i *MaxSIMD *ChunkSize :]), MaxSIMD *ChunkSize , key , counter +(MaxSIMD *i ), flags ))
}(uint64 (i ))
}
wg .Wait ()
var rec func (cvs [][8 ]uint32 ) Node
rec = func (cvs [][8 ]uint32 ) Node {
if len (cvs ) == 2 {
return ParentNode (cvs [0 ], cvs [1 ], key , flags )
} else if len (cvs ) == MaxSIMD {
return mergeSubtrees ((*[MaxSIMD ][8 ]uint32 )(cvs ), MaxSIMD , key , flags )
}
return ParentNode (ChainingValue (rec (cvs [:len (cvs )/2 ])), ChainingValue (rec (cvs [len (cvs )/2 :])), key , flags )
}
return rec (cvs )
}
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .