92 lines
2.4 KiB
Go
92 lines
2.4 KiB
Go
package wallet
|
|
|
|
import (
|
|
"math/bits"
|
|
|
|
"github.com/phamminh0811/private-grpc/crypto"
|
|
"github.com/phamminh0811/private-grpc/nockchain"
|
|
)
|
|
|
|
var InitialBits = []bool{true, false, false, true, true, false, true, false, false, false, false, false, false, false, true, true, true, true, false, false, false, false, false, true, true, true, false, true, true, false, true, false, true, true, false, false, false, false, true, false, true, true, true, false}
|
|
|
|
func NumBitsUint64(v uint64) int {
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return 64 - bits.LeadingZeros64(v)
|
|
}
|
|
|
|
func Uint64ToBitsLSB0(x uint64) []bool {
|
|
bits := make([]bool, 64)
|
|
for i := 0; i < 64; i++ {
|
|
bits[i] = ((x >> i) & 1) == 1
|
|
}
|
|
return bits
|
|
}
|
|
|
|
func BoolsToBytesLSB0(bits []bool) []byte {
|
|
if len(bits) == 0 {
|
|
return nil
|
|
}
|
|
n := (len(bits) + 7) / 8 // ceil division
|
|
bytes := make([]byte, n)
|
|
for i, bit := range bits {
|
|
if bit {
|
|
byteIdx := i / 8
|
|
bitIdx := i % 8
|
|
bytes[byteIdx] |= 1 << bitIdx // LSB0: least-significant bit first
|
|
}
|
|
}
|
|
return bytes
|
|
}
|
|
|
|
func EncodeNoteData(noteData *nockchain.NockchainLock) []byte {
|
|
bits := InitialBits
|
|
|
|
numPubkeys := noteData.KeysRequired
|
|
numPubkeysSz := NumBitsUint64(uint64(numPubkeys))
|
|
numPubkeysSzSz := NumBitsUint64(uint64(numPubkeysSz))
|
|
|
|
bits = append(bits, false)
|
|
for i := 0; i < numPubkeysSzSz; i++ {
|
|
bits = append(bits, false)
|
|
}
|
|
bits = append(bits, true)
|
|
|
|
if numPubkeysSzSz > 1 {
|
|
numPubkeysSzBits := Uint64ToBitsLSB0(uint64(numPubkeysSz))
|
|
bits = append(bits, numPubkeysSzBits[0:numPubkeysSzSz-1]...)
|
|
}
|
|
|
|
numPubkeysBits := Uint64ToBitsLSB0(uint64(numPubkeys))
|
|
bits = append(bits, numPubkeysBits[0:numPubkeysSz]...)
|
|
bits = append(bits, []bool{true, false}...)
|
|
for _, pkStr := range noteData.Pubkeys {
|
|
pkHash := crypto.Base58ToTip5Hash(pkStr)
|
|
for i, hash := range pkHash {
|
|
if i != 4 {
|
|
bits = append(bits, []bool{true, false}...)
|
|
}
|
|
hashSz := NumBitsUint64(hash)
|
|
hashSzSz := NumBitsUint64(uint64(hashSz))
|
|
|
|
bits = append(bits, false)
|
|
for i := 0; i < hashSzSz; i++ {
|
|
bits = append(bits, false)
|
|
}
|
|
bits = append(bits, true)
|
|
|
|
if hashSzSz > 1 {
|
|
hashSzBits := Uint64ToBitsLSB0(uint64(hashSz))
|
|
bits = append(bits, hashSzBits[0:hashSzSz-1]...)
|
|
}
|
|
|
|
hashBits := Uint64ToBitsLSB0(hash)
|
|
bits = append(bits, hashBits[0:hashSz]...)
|
|
}
|
|
}
|
|
|
|
bits = append(bits, []bool{true, false, false, true, false, true, false, true}...)
|
|
return BoolsToBytesLSB0(bits)
|
|
}
|