first draft for nockchain-grpc

This commit is contained in:
Trinity 2025-10-06 13:38:53 +07:00
commit 65ccf9157c
28 changed files with 9284 additions and 0 deletions

283
crypto/argon2.go Normal file
View File

@ -0,0 +1,283 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package argon2 implements the key derivation function Argon2.
// Argon2 was selected as the winner of the Password Hashing Competition and can
// be used to derive cryptographic keys from passwords.
//
// For a detailed specification of Argon2 see [1].
//
// If you aren't sure which function you need, use Argon2id (IDKey) and
// the parameter recommendations for your scenario.
//
// # Argon2i
//
// Argon2i (implemented by Key) is the side-channel resistant version of Argon2.
// It uses data-independent memory access, which is preferred for password
// hashing and password-based key derivation. Argon2i requires more passes over
// memory than Argon2id to protect from trade-off attacks. The recommended
// parameters (taken from [2]) for non-interactive operations are time=3 and to
// use the maximum available memory.
//
// # Argon2id
//
// Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining
// Argon2i and Argon2d. It uses data-independent memory access for the first
// half of the first iteration over the memory and data-dependent memory access
// for the rest. Argon2id is side-channel resistant and provides better brute-
// force cost savings due to time-memory tradeoffs than Argon2i. The recommended
// parameters for non-interactive operations (taken from [2]) are time=1 and to
// use the maximum available memory.
//
// [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
// [2] https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.3
package crypto
import (
"encoding/binary"
"sync"
"golang.org/x/crypto/blake2b"
)
// The Argon2 version implemented by this package.
const Version = 0x13
const (
argon2d = iota
argon2i
argon2id
)
// Key derives a key from the password, salt, and cost parameters using Argon2i
// returning a byte slice of length keyLen that can be used as cryptographic
// key. The CPU cost and parallelism degree must be greater than zero.
//
// For example, you can get a derived key for e.g. AES-256 (which needs a
// 32-byte key) by doing:
//
// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32)
//
// The draft RFC recommends[2] time=3, and memory=32*1024 is a sensible number.
// If using that amount of memory (32 MB) is not possible in some contexts then
// the time parameter can be increased to compensate.
//
// The time parameter specifies the number of passes over the memory and the
// memory parameter specifies the size of the memory in KiB. For example
// memory=32*1024 sets the memory cost to ~32 MB. The number of threads can be
// adjusted to the number of available CPUs. The cost parameters should be
// increased as memory latency and CPU parallelism increases. Remember to get a
// good random salt.
func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
return DeriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen)
}
// IDKey derives a key from the password, salt, and cost parameters using
// Argon2id returning a byte slice of length keyLen that can be used as
// cryptographic key. The CPU cost and parallelism degree must be greater than
// zero.
//
// For example, you can get a derived key for e.g. AES-256 (which needs a
// 32-byte key) by doing:
//
// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32)
//
// The draft RFC recommends[2] time=1, and memory=64*1024 is a sensible number.
// If using that amount of memory (64 MB) is not possible in some contexts then
// the time parameter can be increased to compensate.
//
// The time parameter specifies the number of passes over the memory and the
// memory parameter specifies the size of the memory in KiB. For example
// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be
// adjusted to the numbers of available CPUs. The cost parameters should be
// increased as memory latency and CPU parallelism increases. Remember to get a
// good random salt.
func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
return DeriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen)
}
func DeriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
if time < 1 {
panic("argon2: number of rounds too small")
}
if threads < 1 {
panic("argon2: parallelism degree too low")
}
h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode)
memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads))
if memory < 2*syncPoints*uint32(threads) {
memory = 2 * syncPoints * uint32(threads)
}
B := initBlocks(&h0, memory, uint32(threads))
processBlocks(B, time, memory, uint32(threads), mode)
return extractKey(B, memory, uint32(threads), keyLen)
}
const (
blockLength = 128
syncPoints = 4
)
type block [blockLength]uint64
func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte {
var (
h0 [blake2b.Size + 8]byte
params [24]byte
tmp [4]byte
)
b2, _ := blake2b.New512(nil)
binary.LittleEndian.PutUint32(params[0:4], threads)
binary.LittleEndian.PutUint32(params[4:8], keyLen)
binary.LittleEndian.PutUint32(params[8:12], memory)
binary.LittleEndian.PutUint32(params[12:16], time)
binary.LittleEndian.PutUint32(params[16:20], uint32(Version))
binary.LittleEndian.PutUint32(params[20:24], uint32(mode))
b2.Write(params[:])
binary.LittleEndian.PutUint32(tmp[:], uint32(len(password)))
b2.Write(tmp[:])
b2.Write(password)
binary.LittleEndian.PutUint32(tmp[:], uint32(len(salt)))
b2.Write(tmp[:])
b2.Write(salt)
binary.LittleEndian.PutUint32(tmp[:], uint32(len(key)))
b2.Write(tmp[:])
b2.Write(key)
binary.LittleEndian.PutUint32(tmp[:], uint32(len(data)))
b2.Write(tmp[:])
b2.Write(data)
b2.Sum(h0[:0])
return h0
}
func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block {
var block0 [1024]byte
B := make([]block, memory)
for lane := uint32(0); lane < threads; lane++ {
j := lane * (memory / threads)
binary.LittleEndian.PutUint32(h0[blake2b.Size+4:], lane)
binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0)
blake2bHash(block0[:], h0[:])
for i := range B[j+0] {
B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:])
}
binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1)
blake2bHash(block0[:], h0[:])
for i := range B[j+1] {
B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:])
}
}
return B
}
func processBlocks(B []block, time, memory, threads uint32, mode int) {
lanes := memory / threads
segments := lanes / syncPoints
processSegment := func(n, slice, lane uint32, wg *sync.WaitGroup) {
var addresses, in, zero block
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
in[0] = uint64(n)
in[1] = uint64(lane)
in[2] = uint64(slice)
in[3] = uint64(memory)
in[4] = uint64(time)
in[5] = uint64(mode)
}
index := uint32(0)
if n == 0 && slice == 0 {
index = 2 // we have already generated the first two blocks
if mode == argon2i || mode == argon2id {
in[6]++
processBlock(&addresses, &in, &zero)
processBlock(&addresses, &addresses, &zero)
}
}
offset := lane*lanes + slice*segments + index
var random uint64
for index < segments {
prev := offset - 1
if index == 0 && slice == 0 {
prev += lanes // last block in lane
}
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
if index%blockLength == 0 {
in[6]++
processBlock(&addresses, &in, &zero)
processBlock(&addresses, &addresses, &zero)
}
random = addresses[index%blockLength]
} else {
random = B[prev][0]
}
newOffset := indexAlpha(random, lanes, segments, threads, n, slice, lane, index)
processBlockXOR(&B[offset], &B[prev], &B[newOffset])
index, offset = index+1, offset+1
}
wg.Done()
}
for n := uint32(0); n < time; n++ {
for slice := uint32(0); slice < syncPoints; slice++ {
var wg sync.WaitGroup
for lane := uint32(0); lane < threads; lane++ {
wg.Add(1)
go processSegment(n, slice, lane, &wg)
}
wg.Wait()
}
}
}
func extractKey(B []block, memory, threads, keyLen uint32) []byte {
lanes := memory / threads
for lane := uint32(0); lane < threads-1; lane++ {
for i, v := range B[(lane*lanes)+lanes-1] {
B[memory-1][i] ^= v
}
}
var block [1024]byte
for i, v := range B[memory-1] {
binary.LittleEndian.PutUint64(block[i*8:], v)
}
key := make([]byte, keyLen)
blake2bHash(key, block[:])
return key
}
func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 {
refLane := uint32(rand>>32) % threads
if n == 0 && slice == 0 {
refLane = lane
}
m, s := 3*segments, ((slice+1)%syncPoints)*segments
if lane == refLane {
m += index
}
if n == 0 {
m, s = slice*segments, 0
if slice == 0 || lane == refLane {
m += index
}
}
if index == 0 || lane == refLane {
m--
}
return phi(rand, uint64(m), uint64(s), refLane, lanes)
}
func phi(rand, m, s uint64, lane, lanes uint32) uint32 {
p := rand & 0xFFFFFFFF
p = (p * p) >> 32
p = (p * m) >> 32
return lane*lanes + uint32((s+m-(p+1))%uint64(lanes))
}

302
crypto/belt.go Normal file
View File

@ -0,0 +1,302 @@
package crypto
import (
"fmt"
"math/big"
"math/bits"
)
const (
// Base field arithmetic functions.
PRIME uint64 = 18446744069414584321
PRIME_PRIME uint64 = PRIME - 2
// R_MOD_P uint64 = 0xFFFF_FFFF;
H uint64 = 20033703337
ORDER uint64 = 1 << 32
)
var ROOTS = []uint64{
0x0000000000000001, 0xffffffff00000000, 0x0001000000000000, 0xfffffffeff000001,
0xefffffff00000001, 0x00003fffffffc000, 0x0000008000000000, 0xf80007ff08000001,
0xbf79143ce60ca966, 0x1905d02a5c411f4e, 0x9d8f2ad78bfed972, 0x0653b4801da1c8cf,
0xf2c35199959dfcb6, 0x1544ef2335d17997, 0xe0ee099310bba1e2, 0xf6b2cffe2306baac,
0x54df9630bf79450e, 0xabd0a6e8aa3d8a0e, 0x81281a7b05f9beac, 0xfbd41c6b8caa3302,
0x30ba2ecd5e93e76d, 0xf502aef532322654, 0x4b2a18ade67246b5, 0xea9d5a1336fbc98b,
0x86cdcc31c307e171, 0x4bbaf5976ecfefd8, 0xed41d05b78d6e286, 0x10d78dd8915a171d,
0x59049500004a4485, 0xdfa8c93ba46d2666, 0x7e9bd009b86a0845, 0x400a7f755588e659,
0x185629dcda58878c,
}
var (
PRIME_128, _ = new(big.Int).SetString("18446744069414584321", 10)
RP, _ = new(big.Int).SetString("340282366841710300967557013911933812736", 10)
R2, _ = new(big.Int).SetString("18446744065119617025", 10)
)
type Belt struct {
Value uint64
}
func BaseCheck(x uint64) bool {
return x < PRIME
}
func ZeroBelt() Belt {
return Belt{Value: 0}
}
func OneBelt() Belt {
return Belt{Value: 1}
}
func (belt *Belt) IsZero() bool {
return belt.Value == 0
}
func (belt *Belt) IsOne() bool {
return belt.Value == 1
}
func (belt *Belt) OrderedRoot() (Belt, error) {
// Belt(bpow(H, ORDER / self.0))
log2 := bits.Len(uint(belt.Value)) - 1
if log2 > len(ROOTS) {
return Belt{}, fmt.Errorf("ordered_root: out of bounds")
}
// assert that it was an even power of two
if (1 << log2) != belt.Value {
return Belt{}, fmt.Errorf("ordered_root: not a power of two")
}
return Belt{Value: ROOTS[log2]}, nil
}
func (belt *Belt) Inv() Belt {
return Belt{Value: binv(belt.Value)}
}
func (belt *Belt) Add(other Belt) Belt {
a := belt.Value
b := other.Value
return Belt{Value: badd(a, b)}
}
func (belt *Belt) Sub(other Belt) Belt {
a := belt.Value
b := other.Value
return Belt{Value: bsub(a, b)}
}
func (belt *Belt) Neg() Belt {
return Belt{Value: bneg(belt.Value)}
}
func (belt *Belt) Mul(other Belt) Belt {
a := belt.Value
b := other.Value
return Belt{Value: bmul(a, b)}
}
func (belt *Belt) Eq(other Belt) bool {
return belt.Value == other.Value
}
func (belt *Belt) Pow(exp uint64) Belt {
return Belt{Value: bpow(belt.Value, exp)}
}
func (belt *Belt) Div(other Belt) Belt {
return belt.Mul(other.Inv())
}
func binv(a uint64) uint64 {
if !BaseCheck(a) {
fmt.Println("element must be inside the field")
}
y := montify(a)
y2 := montiply(y, montiply(y, y))
y3 := montiply(y, montiply(y2, y2))
y5 := montiply(y2, montwopow(y3, 2))
y10 := montiply(y5, montwopow(y5, 5))
y20 := montiply(y10, montwopow(y10, 10))
y30 := montiply(y10, montwopow(y20, 10))
y31 := montiply(y, montiply(y30, y30))
dup := montiply(montwopow(y31, 32), y31)
res := new(big.Int)
res.SetUint64(montiply(y, montiply(dup, dup)))
return montReduction(res)
}
func badd(a, b uint64) uint64 {
if !BaseCheck(a) || !BaseCheck(b) {
fmt.Println("element must be inside the field")
}
b = PRIME - b
r, c := overflowingSub(a, b)
adj := uint32(0)
if c {
adj = adj - 1
}
return r - uint64(adj)
}
func bsub(a, b uint64) uint64 {
if !BaseCheck(a) || !BaseCheck(b) {
fmt.Println("element must be inside the field")
}
r, c := overflowingSub(a, b)
adj := uint32(0)
if c {
adj = adj - 1
}
return r - uint64(adj)
}
func bneg(a uint64) uint64 {
if !BaseCheck(a) {
fmt.Println("element must be inside the field")
}
if a != 0 {
return PRIME - a
} else {
return 0
}
}
func bmul(a, b uint64) uint64 {
if !BaseCheck(a) || !BaseCheck(b) {
fmt.Println("element must be inside the field")
}
aBig := new(big.Int).SetUint64(a)
bBig := new(big.Int).SetUint64(b)
return reduce(aBig.Mul(aBig, bBig))
}
func bpow(a, b uint64) uint64 {
if !BaseCheck(a) || !BaseCheck(b) {
fmt.Println("element must be inside the field")
}
c := uint64(1)
if b == 0 {
return c
}
for b > 1 {
if b&1 == 0 {
a = bmul(a, a)
b >>= 1
} else {
c = bmul(c, a)
a = bmul(a, a)
b = (b - 1) >> 1
}
}
return bmul(a, c)
}
func overflowingSub(a, b uint64) (uint64, bool) {
res := a - b
overflow := a < b
return res, overflow
}
func overflowingAdd(a, b uint64) (uint64, bool) {
res := a + b
overflow := res < a || res < b
return res, overflow
}
func montify(a uint64) uint64 {
if !BaseCheck(a) {
fmt.Println("element must be inside the field")
}
aBig := new(big.Int).SetUint64(a)
return montReduction(aBig.Mul(aBig, R2))
}
func montiply(a, b uint64) uint64 {
if !BaseCheck(a) || !BaseCheck(b) {
fmt.Println("element must be inside the field")
}
aBig := new(big.Int).SetUint64(a)
bBig := new(big.Int).SetUint64(b)
return montReduction(aBig.Mul(aBig, bBig))
}
func montwopow(a uint64, exp int) uint64 {
if !BaseCheck(a) {
fmt.Println("element must be inside the field")
}
res := a
for i := 0; i < exp; i++ {
res = montiply(res, res)
}
return res
}
func montReduction(a *big.Int) uint64 {
if a.Cmp(RP) >= 0 {
fmt.Println("element must be inside the field")
}
x1 := new(big.Int)
x1.And(x1.Rsh(a, 32), new(big.Int).SetUint64(0xFFFFFFFF))
x2 := new(big.Int)
x2.Rsh(a, 64)
x0 := new(big.Int)
x0.And(a, new(big.Int).SetUint64(0xFFFFFFFF))
c := new(big.Int)
c.Lsh(x0.Add(x0, x1), 32)
f := new(big.Int)
f.Rsh(c, 64)
d := new(big.Int)
d.Sub(c, d.Add(x1, d.Mul(f, PRIME_128)))
if x2.Cmp(d) >= 0 {
ret := new(big.Int)
ret.Sub(x2, d)
return ret.Uint64()
} else {
ret := new(big.Int)
ret.Sub(ret.Add(x2, PRIME_128), d)
return ret.Uint64()
}
}
func reduce(a *big.Int) uint64 {
low := new(big.Int).And(a, new(big.Int).SetUint64(0xFFFFFFFFFFFFFFFF))
mid := new(big.Int)
mid.And(mid.Rsh(a, 64), big.NewInt(0xFFFFFFFF))
high := new(big.Int)
high.Rsh(a, 96)
low2, carry := overflowingSub(low.Uint64(), high.Uint64())
if carry {
low2 = low2 + PRIME
}
product := mid.Uint64() << 32
product -= product >> 32
result, carry := overflowingAdd(low2, product)
if carry {
result = result - PRIME
}
if result >= PRIME {
result -= PRIME
}
return result
}

49
crypto/blake2b.go Normal file
View File

@ -0,0 +1,49 @@
package crypto
import (
"encoding/binary"
"hash"
"golang.org/x/crypto/blake2b"
)
// blake2bHash computes an arbitrary long hash value of in
// and writes the hash to out.
func blake2bHash(out []byte, in []byte) {
var b2 hash.Hash
if n := len(out); n < blake2b.Size {
b2, _ = blake2b.New(n, nil)
} else {
b2, _ = blake2b.New512(nil)
}
var buffer [blake2b.Size]byte
binary.LittleEndian.PutUint32(buffer[:4], uint32(len(out)))
b2.Write(buffer[:4])
b2.Write(in)
if len(out) <= blake2b.Size {
b2.Sum(out[:0])
return
}
outLen := len(out)
b2.Sum(buffer[:0])
b2.Reset()
copy(out, buffer[:32])
out = out[32:]
for len(out) > blake2b.Size {
b2.Write(buffer[:])
b2.Sum(buffer[:0])
copy(out, buffer[:32])
out = out[32:]
b2.Reset()
}
if outLen%blake2b.Size > 0 { // outLen > 64
r := ((outLen + 31) / 32) - 2 // ⌈τ /32⌉-2
b2, _ = blake2b.New(outLen-32*r, nil)
}
b2.Write(buffer[:])
b2.Sum(out[:0])
}

165
crypto/blamka_generic.go Normal file
View File

@ -0,0 +1,165 @@
package crypto
func processBlock(out, in1, in2 *block) {
processBlockGeneric(out, in1, in2, false)
}
func processBlockXOR(out, in1, in2 *block) {
processBlockGeneric(out, in1, in2, true)
}
func processBlockGeneric(out, in1, in2 *block, xor bool) {
var t block
for i := range t {
t[i] = in1[i] ^ in2[i]
}
for i := 0; i < blockLength; i += 16 {
blamkaGeneric(
&t[i+0], &t[i+1], &t[i+2], &t[i+3],
&t[i+4], &t[i+5], &t[i+6], &t[i+7],
&t[i+8], &t[i+9], &t[i+10], &t[i+11],
&t[i+12], &t[i+13], &t[i+14], &t[i+15],
)
}
for i := 0; i < blockLength/8; i += 2 {
blamkaGeneric(
&t[i], &t[i+1], &t[16+i], &t[16+i+1],
&t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1],
&t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1],
&t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1],
)
}
if xor {
for i := range t {
out[i] ^= in1[i] ^ in2[i] ^ t[i]
}
} else {
for i := range t {
out[i] = in1[i] ^ in2[i] ^ t[i]
}
}
}
func blamkaGeneric(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15 *uint64) {
v00, v01, v02, v03 := *t00, *t01, *t02, *t03
v04, v05, v06, v07 := *t04, *t05, *t06, *t07
v08, v09, v10, v11 := *t08, *t09, *t10, *t11
v12, v13, v14, v15 := *t12, *t13, *t14, *t15
v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04))
v12 ^= v00
v12 = v12>>32 | v12<<32
v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12))
v04 ^= v08
v04 = v04>>24 | v04<<40
v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04))
v12 ^= v00
v12 = v12>>16 | v12<<48
v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12))
v04 ^= v08
v04 = v04>>63 | v04<<1
v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05))
v13 ^= v01
v13 = v13>>32 | v13<<32
v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13))
v05 ^= v09
v05 = v05>>24 | v05<<40
v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05))
v13 ^= v01
v13 = v13>>16 | v13<<48
v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13))
v05 ^= v09
v05 = v05>>63 | v05<<1
v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06))
v14 ^= v02
v14 = v14>>32 | v14<<32
v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14))
v06 ^= v10
v06 = v06>>24 | v06<<40
v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06))
v14 ^= v02
v14 = v14>>16 | v14<<48
v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14))
v06 ^= v10
v06 = v06>>63 | v06<<1
v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07))
v15 ^= v03
v15 = v15>>32 | v15<<32
v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15))
v07 ^= v11
v07 = v07>>24 | v07<<40
v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07))
v15 ^= v03
v15 = v15>>16 | v15<<48
v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15))
v07 ^= v11
v07 = v07>>63 | v07<<1
v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05))
v15 ^= v00
v15 = v15>>32 | v15<<32
v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15))
v05 ^= v10
v05 = v05>>24 | v05<<40
v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05))
v15 ^= v00
v15 = v15>>16 | v15<<48
v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15))
v05 ^= v10
v05 = v05>>63 | v05<<1
v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06))
v12 ^= v01
v12 = v12>>32 | v12<<32
v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12))
v06 ^= v11
v06 = v06>>24 | v06<<40
v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06))
v12 ^= v01
v12 = v12>>16 | v12<<48
v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12))
v06 ^= v11
v06 = v06>>63 | v06<<1
v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07))
v13 ^= v02
v13 = v13>>32 | v13<<32
v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13))
v07 ^= v08
v07 = v07>>24 | v07<<40
v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07))
v13 ^= v02
v13 = v13>>16 | v13<<48
v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13))
v07 ^= v08
v07 = v07>>63 | v07<<1
v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04))
v14 ^= v03
v14 = v14>>32 | v14<<32
v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14))
v04 ^= v09
v04 = v04>>24 | v04<<40
v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04))
v14 ^= v03
v14 = v14>>16 | v14<<48
v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14))
v04 ^= v09
v04 = v04>>63 | v04<<1
*t00, *t01, *t02, *t03 = v00, v01, v02, v03
*t04, *t05, *t06, *t07 = v04, v05, v06, v07
*t08, *t09, *t10, *t11 = v08, v09, v10, v11
*t12, *t13, *t14, *t15 = v12, v13, v14, v15
}

229
crypto/bpoly.go Normal file
View File

@ -0,0 +1,229 @@
package crypto
type Bpoly struct {
Value []Belt
}
func (p *Bpoly) IsZero() bool {
length := len(p.Value)
if length == 0 {
return true
}
if length == 1 && p.Value[0].IsZero() {
return true
}
for _, i := range p.Value {
if !i.IsZero() {
return false
}
}
return true
}
func (p *Bpoly) Degree() uint32 {
for i := len(p.Value) - 1; i >= 0; i-- {
if !p.Value[i].IsZero() {
return uint32(i)
}
}
return 0
}
func (p *Bpoly) Add(other Bpoly) Bpoly {
min := Bpoly{}
max := Bpoly{}
if len(p.Value) <= len(other.Value) {
min = *p
max = other
} else {
min = other
max = *p
}
res := Bpoly{Value: make([]Belt, len(max.Value))}
for i := range max.Value {
if i < len(min.Value) {
res.Value[i] = min.Value[i].Add(max.Value[i])
} else {
res.Value[i] = max.Value[i]
}
}
return res
}
func (p *Bpoly) Sub(other Bpoly) Bpoly {
resLen := len(p.Value)
if len(other.Value) > resLen {
resLen = len(other.Value)
}
res := Bpoly{Value: make([]Belt, resLen)}
for i := 0; i < resLen; i++ {
if i < len(p.Value) && i < len(other.Value) {
res.Value[i] = p.Value[i].Sub(other.Value[i])
} else if i < len(p.Value) {
res.Value[i] = p.Value[i]
} else {
res.Value[i] = other.Value[i].Neg()
}
}
return res
}
func (p *Bpoly) Mul(other Bpoly) Bpoly {
resLen := len(p.Value) + len(other.Value) - 1
res := Bpoly{Value: make([]Belt, resLen)}
for i := range res.Value {
res.Value[i] = BELT_ZERO
}
if p.IsZero() || other.IsZero() {
return res
}
for i := 0; i < len(p.Value); i++ {
if p.Value[i].IsZero() {
continue
}
for j := 0; j < len(other.Value); j++ {
res.Value[i+j] = res.Value[i+j].Add(p.Value[i].Mul(other.Value[j]))
}
}
return res
}
func (p *Bpoly) ScalarMul(scalar Belt, resLen int) Bpoly {
res := Bpoly{Value: make([]Belt, resLen)}
for i := range res.Value {
res.Value[i] = p.Value[i].Mul(scalar)
}
return res
}
func Dvr(a Bpoly, b Bpoly) (Bpoly, Bpoly) {
degA := a.Degree()
degB := b.Degree()
degQ := uint32(0)
if degA >= degB {
degQ = degA - degB
}
lenQ := degQ + 1
lenR := degB + 1
q := Bpoly{Value: make([]Belt, lenQ)}
res := Bpoly{Value: make([]Belt, lenR)}
for i := range q.Value {
q.Value[i] = BELT_ZERO
}
for i := range res.Value {
res.Value[i] = BELT_ZERO
}
if a.IsZero() {
return q, res
} else if b.IsZero() {
panic("division by zero")
}
r := a
i := degA
degR := degA
qIdx := degQ
for degR >= degB {
coeff := r.Value[i].Div(b.Value[degB])
q.Value[qIdx] = coeff
for k := 0; k <= int(degB); k++ {
if k <= int(degA) && k < len(b.Value) && k <= int(i) {
r.Value[i-uint32(k)] = r.Value[i-uint32(k)].Sub(coeff.Mul(b.Value[degB-uint32(k)]))
}
}
if degR >= 1 {
degR--
}
if qIdx >= 1 {
qIdx--
}
if degR == 0 && r.Value[0].IsZero() {
break
}
i--
}
rLen := int(degR) + 1
for i := 0; i < rLen; i++ {
res.Value[i] = r.Value[i]
}
return q, res
}
func Egcd(a Bpoly, b Bpoly) (Bpoly, Bpoly, Bpoly) {
m1u := Bpoly{Value: []Belt{BELT_ZERO}}
m2u := Bpoly{Value: []Belt{BELT_ONE}}
m1v := Bpoly{Value: []Belt{BELT_ONE}}
m2v := Bpoly{Value: []Belt{BELT_ZERO}}
// length of d is at most min(len a, len b) + 1
dLen := min(len(a.Value), len(b.Value)) + 1
// length of u is at most deg(b)
uLen := b.Degree()
// length of u is at most deg(a)
vLen := a.Degree()
d := Bpoly{Value: make([]Belt, dLen)}
u := Bpoly{Value: make([]Belt, uLen)}
v := Bpoly{Value: make([]Belt, vLen)}
for i := range d.Value {
d.Value[i] = BELT_ZERO
}
for i := range u.Value {
u.Value[i] = BELT_ZERO
}
for i := range v.Value {
v.Value[i] = BELT_ZERO
}
aCopy := a
bCopy := b
for !bCopy.IsZero() {
degQ := uint32(0)
if aCopy.Degree() >= bCopy.Degree() {
degQ = aCopy.Degree() - bCopy.Degree()
}
qLen := degQ + 1
rLen := bCopy.Degree() + 1
q := Bpoly{Value: make([]Belt, qLen)}
r := Bpoly{Value: make([]Belt, rLen)}
for i := range q.Value {
q.Value[i] = BELT_ZERO
}
for i := range r.Value {
r.Value[i] = BELT_ZERO
}
q, r = Dvr(aCopy, bCopy)
aCopy = bCopy
bCopy = r
res1 := q.Mul(m1u)
res2 := m2u.Sub(res1)
m2u = m1u
m1u = res2
res1 = q.Mul(m1v)
res3 := m2v.Sub(res1)
m2v = m1v
m1v = res3
}
d.Value = aCopy.Value
u.Value = m2u.Value
v.Value = m2v.Value
return d, u, v
}

308
crypto/cheetah.go Normal file
View File

@ -0,0 +1,308 @@
package crypto
import (
"encoding/binary"
"fmt"
"math/big"
"slices"
)
var (
BELT_ZERO = Belt{Value: 0}
BELT_ONE = Belt{Value: 1}
F6_ZERO = [6]Belt{BELT_ZERO, BELT_ZERO, BELT_ZERO, BELT_ZERO, BELT_ZERO, BELT_ZERO}
F6_ONE = [6]Belt{BELT_ONE, BELT_ZERO, BELT_ZERO, BELT_ZERO, BELT_ZERO, BELT_ZERO}
A_ID = CheetahPoint{
X: F6_ZERO,
Y: F6_ONE,
Inf: true,
}
A_GEN = CheetahPoint{
X: [6]Belt{
{Value: 2754611494552410273},
{Value: 8599518745794843693},
{Value: 10526511002404673680},
{Value: 4830863958577994148},
{Value: 375185138577093320},
{Value: 12938930721685970739},
},
Y: [6]Belt{
{Value: 15384029202802550068},
{Value: 2774812795997841935},
{Value: 14375303400746062753},
{Value: 10708493419890101954},
{Value: 13187678623570541764},
{Value: 9990732138772505951},
},
Inf: false,
}
P_BIG = new(big.Int).SetUint64(PRIME)
P_BIG_2 = new(big.Int).Mul(P_BIG, P_BIG)
P_BIG_3 = new(big.Int).Mul(P_BIG_2, P_BIG)
G_ORDER, _ = new(big.Int).SetString("55610362957290864006699123731285679659474893560816383126640993521607086746831", 10)
)
type CheetahPoint struct {
X, Y [6]Belt
Inf bool
}
func (p *CheetahPoint) Bytes() []byte {
bytes := []byte{0x1}
for i := 5; i >= 0; i-- {
belt := p.Y[i].Value
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, belt)
bytes = append(bytes, buf...)
}
for i := 5; i >= 0; i-- {
belt := p.X[i].Value
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, belt)
bytes = append(bytes, buf...)
}
return bytes
}
func CheetaPointFromBytes(bytes []byte) (CheetahPoint, error) {
if len(bytes) != 97 {
return CheetahPoint{}, fmt.Errorf("invalid point length %d, length must be 97", len(bytes))
}
bytes = bytes[1:]
if len(bytes)%8 != 0 {
return CheetahPoint{}, fmt.Errorf("input length not multiple of 8")
}
n := len(bytes) / 8
belts := []Belt{}
for i := 0; i < n; i++ {
chunk := bytes[i*8 : (i+1)*8]
belt := binary.BigEndian.Uint64(chunk)
belts = append(belts, Belt{Value: belt})
}
slices.Reverse(belts)
point := CheetahPoint{
X: [6]Belt(belts[0:6]),
Y: [6]Belt(belts[6:]),
Inf: false,
}
if point.InCurve() {
return point, nil
}
return CheetahPoint{}, fmt.Errorf("point not in curve")
}
func (p *CheetahPoint) InCurve() bool {
if *p == A_ID {
return true
}
scaled := CheetahScaleBig(*p, *G_ORDER)
return scaled == A_ID
}
func CheetahScaleBig(p CheetahPoint, n big.Int) CheetahPoint {
zero := big.NewInt(0)
nCopy := new(big.Int).Set(&n)
acc := A_ID
for nCopy.Cmp(zero) > 0 {
if nCopy.Bit(0) == 1 {
acc = CheetahAdd(acc, p)
}
p = CheetahDouble(p)
nCopy.Rsh(nCopy, 1)
}
return acc
}
func CheetahAdd(p, q CheetahPoint) CheetahPoint {
if p.Inf {
return q
}
if q.Inf {
return p
}
if p == CheetahNeg(q) {
return A_ID
}
if p == q {
return CheetahDouble(p)
}
return cheetahAddUnsafe(&p, &q)
}
func CheetahNeg(p CheetahPoint) CheetahPoint {
negP := p
for i := 0; i < 6; i++ {
negP.Y[i] = p.Y[i].Neg()
}
return negP
}
func CheetahDouble(p CheetahPoint) CheetahPoint {
if p.Inf {
return A_ID
}
if p.Y == F6_ZERO {
return A_ID
}
return cheetahDoubleUnsafe(&p)
}
func cheetahAddUnsafe(p, q *CheetahPoint) CheetahPoint {
slope := f6Mul(f6Sub(p.Y, q.Y), f6Inv(f6Sub(p.X, q.X)))
xOut := f6Sub(f6Square(slope), f6Add(p.X, q.X))
yOut := f6Sub(f6Mul(slope, f6Sub(p.X, xOut)), p.Y)
return CheetahPoint{
X: xOut,
Y: yOut,
Inf: false,
}
}
func cheetahDoubleUnsafe(p *CheetahPoint) CheetahPoint {
slope := f6Mul(
f6Add(f6ScalarMul(f6Square(p.X), Belt{Value: 3}), F6_ONE),
f6Inv(f6ScalarMul(p.Y, Belt{Value: 2})),
)
xOut := f6Sub(f6Square(slope), f6ScalarMul(p.X, Belt{Value: 2}))
yOut := f6Sub(f6Mul(slope, f6Sub(p.X, xOut)), p.Y)
return CheetahPoint{
X: xOut,
Y: yOut,
Inf: false,
}
}
func f6Inv(a [6]Belt) [6]Belt {
if a == F6_ZERO {
panic("Cannot invert zero")
}
aPoly := Bpoly{Value: a[:]}
b := Bpoly{
Value: []Belt{
Belt{Value: bneg(7)},
BELT_ZERO,
BELT_ZERO,
BELT_ZERO,
BELT_ZERO,
BELT_ZERO,
BELT_ONE,
},
}
d, u, _ := Egcd(aPoly, b)
dInv := d.Value[0].Inv()
res := u.ScalarMul(dInv, 6)
return [6]Belt{res.Value[0], res.Value[1], res.Value[2], res.Value[3], res.Value[4], res.Value[5]}
}
func f6Mul(a, b [6]Belt) [6]Belt {
a0b0 := karat3([3]Belt{a[0], a[1], a[2]}, [3]Belt{b[0], b[1], b[2]})
a1b1 := karat3([3]Belt{a[3], a[4], a[5]}, [3]Belt{b[3], b[4], b[5]})
foil := karat3(
[3]Belt{a[0].Add(a[3]), a[1].Add(a[4]), a[2].Add(a[5])},
[3]Belt{b[0].Add(b[3]), b[1].Add(b[4]), b[2].Add(b[5])},
)
foil_0 := foil[0].Sub(a0b0[0])
foil_1 := foil[1].Sub(a0b0[1])
foil_2 := foil[2].Sub(a0b0[2])
foil_3 := foil[3].Sub(a0b0[3])
foil_4 := foil[4].Sub(a0b0[4])
cross := [5]Belt{
foil_0.Sub(a1b1[0]),
foil_1.Sub(a1b1[1]),
foil_2.Sub(a1b1[2]),
foil_3.Sub(a1b1[3]),
foil_4.Sub(a1b1[4]),
}
seven := Belt{Value: 7}
a0b0cross0 := a0b0[3].Add(cross[0])
a0b0cross1 := a0b0[4].Add(cross[1])
return [6]Belt{
a0b0[0].Add(seven.Mul(cross[3].Add(a1b1[0]))),
a0b0[1].Add(seven.Mul(cross[4].Add(a1b1[1]))),
a0b0[2].Add(seven.Mul(a1b1[2])),
a0b0cross0.Add(seven.Mul(a1b1[3])),
a0b0cross1.Add(seven.Mul(a1b1[4])),
cross[2],
}
}
func f6ScalarMul(a [6]Belt, scalar Belt) [6]Belt {
res := F6_ZERO
for i := range res {
res[i] = a[i].Mul(scalar)
}
return res
}
func f6Add(a, b [6]Belt) [6]Belt {
res := F6_ZERO
for i := range res {
res[i] = a[i].Add(b[i])
}
return res
}
func f6Sub(a, b [6]Belt) [6]Belt {
return f6Add(a, f6Neg(b))
}
func f6Neg(a [6]Belt) [6]Belt {
res := F6_ZERO
for i := range res {
res[i] = a[i].Neg()
}
return res
}
func f6Square(a [6]Belt) [6]Belt {
return f6Mul(a, a)
}
func karat3(a, b [3]Belt) [5]Belt {
m := [3]Belt{
a[0].Mul(b[0]),
a[1].Mul(b[1]),
a[2].Mul(b[2]),
}
a0a1 := a[0].Add(a[1])
b0b1 := b[0].Add(b[1])
m0m1 := m[0].Add(m[1])
a0a1b0b1 := a0a1.Mul(b0b1)
a0a2 := a[0].Add(a[2])
b0b2 := b[0].Add(b[2])
m0m2 := m[0].Add(m[2])
m0m2m1 := m0m2.Sub(m[1])
a0a2b0b2 := a0a2.Mul(b0b2)
a1a2 := a[1].Add(a[2])
b1b2 := b[1].Add(b[2])
m1m2 := m[1].Add(m[2])
a1a2b1b2 := a1a2.Mul(b1b2)
return [5]Belt{
m[0],
a0a1b0b1.Sub(m0m1),
a0a2b0b2.Sub(m0m2m1),
a1a2b1b2.Sub(m1m2),
m[2],
}
}

220
crypto/master_key.go Normal file
View File

@ -0,0 +1,220 @@
package crypto
import (
"crypto/hmac"
"crypto/sha256"
"crypto/sha512"
"encoding/binary"
"fmt"
"math/big"
"github.com/cosmos/go-bip39"
)
var (
DomainSeparator = []byte("Nockchain seed")
PrivateKeyStart = []byte{4, 178, 67, 11}
PublicKeyStart = []byte{234, 230, 92}
MagicDyckForPoint = []uint64{0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1}
MagicDyckForT8 = []uint64{0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}
Tip5Zero = [5]uint64{1730770831742798981, 2676322185709933211, 8329210750824781744, 16756092452590401876, 3547445316740171466}
Tip5One = [5]uint64{6727110957294540849, 15606243244732609007, 11887284596344881785, 10646863421881571398, 8146872807338919620}
Tip5ZeroZero = [5]uint64{4372149332062030091, 17876920912185183887, 13348798570422431948, 8872865212694716527, 3385176510443841516}
)
type MasterKey struct {
PrivateKey []byte
PublicKey []byte
ChainCode []byte
}
func (m *MasterKey) DeriveChild(index uint64) (MasterKey, error) {
idxBytes := make([]byte, 4)
binary.BigEndian.PutUint32(idxBytes, uint32(index))
if len(m.PrivateKey) == 0 {
// Derive public key to child
if index > 1<<31 {
return MasterKey{}, fmt.Errorf("public keys can't be hardened")
}
data := m.PublicKey
data = append(data, idxBytes...)
hash := hmac.New(sha512.New, m.ChainCode)
hash.Write(data)
hashed := hash.Sum(nil)
left := hashed[:32]
right := hashed[32:]
leftBigInt := new(big.Int).SetBytes(left)
pkPoint, err := CheetaPointFromBytes(m.PublicKey)
if err != nil {
return MasterKey{}, err
}
keyPoint := CheetahAdd(CheetahScaleBig(A_GEN, *leftBigInt), pkPoint)
for {
if leftBigInt.Cmp(G_ORDER) < 0 {
break
} else {
data = []byte{0x01}
data = append(data, right...)
data = append(data, idxBytes...)
hash := hmac.New(sha512.New, m.ChainCode)
hash.Write(data)
hashed = hash.Sum(nil)
left = hashed[:32]
right = hashed[32:]
leftBigInt = new(big.Int).SetBytes(left)
keyPoint = CheetahAdd(CheetahScaleBig(A_GEN, *leftBigInt), pkPoint)
}
}
return MasterKey{
PrivateKey: []byte{},
PublicKey: keyPoint.Bytes(),
ChainCode: right,
}, nil
} else {
hash := hmac.New(sha512.New, m.ChainCode)
var data []byte
if index > 1<<31 {
// hardened
data = []byte{0x00}
data = append(data, m.PrivateKey...)
data = append(data, idxBytes...)
} else {
data = m.PublicKey
data = append(data, idxBytes...)
}
hash.Write(data)
hashed := hash.Sum(nil)
left := hashed[:32]
right := hashed[32:]
leftBigInt := new(big.Int).SetBytes(left)
privBigInt := new(big.Int).SetBytes(m.PrivateKey)
sum := new(big.Int).Add(leftBigInt, privBigInt)
keyBigInt := new(big.Int).Mod(sum, G_ORDER)
for {
if leftBigInt.Cmp(G_ORDER) < 0 {
break
} else {
data = []byte{0x01}
data = append(data, right...)
data = append(data, idxBytes...)
hash := hmac.New(sha512.New, m.ChainCode)
hash.Write(data)
hashed = hash.Sum(nil)
left = hashed[:32]
right = hashed[32:]
leftBigInt = new(big.Int).SetBytes(left)
sum = new(big.Int).Add(leftBigInt, privBigInt)
keyBigInt = new(big.Int).Mod(sum, G_ORDER)
}
}
pkPoint := CheetahScaleBig(A_GEN, *keyBigInt)
return MasterKey{
PrivateKey: keyBigInt.Bytes(),
PublicKey: pkPoint.Bytes(),
ChainCode: right,
}, nil
}
}
func MasterKeyFromSeed(seed string) (*MasterKey, error) {
seedBytes, err := bip39.NewSeedWithErrorChecking(seed, "")
if err != nil {
return nil, fmt.Errorf("failed to parse seed: %v", err)
}
hash := hmac.New(sha512.New, DomainSeparator)
hash.Write(seedBytes)
hashedSeed := hash.Sum(nil)
left := hashedSeed[:32]
right := hashedSeed[32:]
leftBigInt := new(big.Int).SetBytes(left)
for {
if leftBigInt.Cmp(G_ORDER) < 0 {
break
} else {
hash := hmac.New(sha512.New, DomainSeparator)
hash.Write(hashedSeed)
hashedSeed = hash.Sum(nil)
left = hashedSeed[:32]
right = hashedSeed[32:]
leftBigInt = new(big.Int).SetBytes(left)
}
}
pkPoint := CheetahScaleBig(A_GEN, *leftBigInt)
return &MasterKey{
PrivateKey: left,
PublicKey: pkPoint.Bytes(),
ChainCode: right,
}, nil
}
func MasterKeyFromPrivKey(chainCode, key []byte) (*MasterKey, error) {
keyBigInt := new(big.Int).SetBytes(key)
pkPoint := CheetahScaleBig(A_GEN, *keyBigInt)
return &MasterKey{
PrivateKey: key,
PublicKey: pkPoint.Bytes(),
ChainCode: chainCode,
}, nil
}
func PrivKeyToT8(data []byte) [8]uint64 {
dataBigInt := new(big.Int).SetBytes(data)
res := rip(*dataBigInt)
return [8]uint64(res)
}
func BigIntToT8(data big.Int) [8]uint64 {
res := rip(data)
return [8]uint64(res)
}
func SerializeExtend(chainCode []byte, key []byte, version []byte) []byte {
data := version
// dep: depth in chain
// idx: index at depth
// pf: parent fingerprint
depth := 0
idx := []byte{0, 0, 0, 0}
pf := []byte{0, 0, 0, 0}
data = append(data, byte(depth%256))
data = append(data, pf...)
data = append(data, idx...)
data = append(data, chainCode...)
data = append(data, key...)
return AddChecksum(data)
}
func AddChecksum(data []byte) []byte {
hash1 := sha256.Sum256(data)
hash2 := sha256.Sum256(hash1[:])
checksum := hash2[:4]
data = append(data, checksum...)
return data
}
func rip(b big.Int) []uint64 {
if b.Cmp(big.NewInt(0)) == 0 {
return []uint64{}
}
res := []uint64{new(big.Int).And(&b, big.NewInt(0xFFFFFFFF)).Uint64()}
rsh := new(big.Int)
rsh.Div(&b, big.NewInt(4294967296))
res = append(res, rip(*rsh)...)
return res
}

301
crypto/tip5.go Normal file
View File

@ -0,0 +1,301 @@
package crypto
import (
"encoding/binary"
"fmt"
"math/big"
"github.com/btcsuite/btcd/btcutil/base58"
)
const (
DIGEST_LENGTH = 5
STATE_SIZE = 16
NUM_SPLIT_AND_LOOKUP = 4
LOG2_STATE_SIZE = 4
CAPACITY = 6
RATE = 10
NUM_ROUNDS = 7
R_MOD_P uint64 = 4294967295
)
var (
R, _ = new(big.Int).SetString("18446744073709551616", 10)
LOOKUP_TABLE = [256]uint8{
0, 7, 26, 63, 124, 215, 85, 254, 214, 228, 45, 185, 140, 173, 33, 240, 29, 177, 176, 32, 8,
110, 87, 202, 204, 99, 150, 106, 230, 14, 235, 128, 213, 239, 212, 138, 23, 130, 208, 6, 44,
71, 93, 116, 146, 189, 251, 81, 199, 97, 38, 28, 73, 179, 95, 84, 152, 48, 35, 119, 49, 88,
242, 3, 148, 169, 72, 120, 62, 161, 166, 83, 175, 191, 137, 19, 100, 129, 112, 55, 221, 102,
218, 61, 151, 237, 68, 164, 17, 147, 46, 234, 203, 216, 22, 141, 65, 57, 123, 12, 244, 54, 219,
231, 96, 77, 180, 154, 5, 253, 133, 165, 98, 195, 205, 134, 245, 30, 9, 188, 59, 142, 186, 197,
181, 144, 92, 31, 224, 163, 111, 74, 58, 69, 113, 196, 67, 246, 225, 10, 121, 50, 60, 157, 90,
122, 2, 250, 101, 75, 178, 159, 24, 36, 201, 11, 243, 132, 198, 190, 114, 233, 39, 52, 21, 209,
108, 238, 91, 187, 18, 104, 194, 37, 153, 34, 200, 143, 126, 155, 236, 118, 64, 80, 172, 89,
94, 193, 135, 183, 86, 107, 252, 13, 167, 206, 136, 220, 207, 103, 171, 160, 76, 182, 227, 217,
158, 56, 174, 4, 66, 109, 139, 162, 184, 211, 249, 47, 125, 232, 117, 43, 16, 42, 127, 20, 241,
25, 149, 105, 156, 51, 53, 168, 145, 247, 223, 79, 78, 226, 15, 222, 82, 115, 70, 210, 27, 41,
1, 170, 40, 131, 192, 229, 248, 255,
}
ROUND_CONSTANTS = [NUM_ROUNDS * STATE_SIZE]uint64{
// 1st round constants
1332676891236936200, 16607633045354064669, 12746538998793080786, 15240351333789289931,
10333439796058208418, 986873372968378050, 153505017314310505, 703086547770691416,
8522628845961587962, 1727254290898686320, 199492491401196126, 2969174933639985366,
1607536590362293391, 16971515075282501568, 15401316942841283351, 14178982151025681389,
// 2nd round constants
2916963588744282587, 5474267501391258599, 5350367839445462659, 7436373192934779388,
12563531800071493891, 12265318129758141428, 6524649031155262053, 1388069597090660214,
3049665785814990091, 5225141380721656276, 10399487208361035835, 6576713996114457203,
12913805829885867278, 10299910245954679423, 12980779960345402499, 593670858850716490,
// 3rd round constants
12184128243723146967, 1315341360419235257, 9107195871057030023, 4354141752578294067,
8824457881527486794, 14811586928506712910, 7768837314956434138, 2807636171572954860,
9487703495117094125, 13452575580428891895, 14689488045617615844, 16144091782672017853,
15471922440568867245, 17295382518415944107, 15054306047726632486, 5708955503115886019,
// 4th round constants
9596017237020520842, 16520851172964236909, 8513472793890943175, 8503326067026609602,
9402483918549940854, 8614816312698982446, 7744830563717871780, 14419404818700162041,
8090742384565069824, 15547662568163517559, 17314710073626307254, 10008393716631058961,
14480243402290327574, 13569194973291808551, 10573516815088946209, 15120483436559336219,
// 5th round constants
3515151310595301563, 1095382462248757907, 5323307938514209350, 14204542692543834582,
12448773944668684656, 13967843398310696452, 14838288394107326806, 13718313940616442191,
15032565440414177483, 13769903572116157488, 17074377440395071208, 16931086385239297738,
8723550055169003617, 590842605971518043, 16642348030861036090, 10708719298241282592,
// 6th round constants
12766914315707517909, 11780889552403245587, 113183285481780712, 9019899125655375514,
3300264967390964820, 12802381622653377935, 891063765000023873, 15939045541699412539,
3240223189948727743, 4087221142360949772, 10980466041788253952, 18199914337033135244,
7168108392363190150, 16860278046098150740, 13088202265571714855, 4712275036097525581,
// 7th round constants
16338034078141228133, 1455012125527134274, 5024057780895012002, 9289161311673217186,
9401110072402537104, 11919498251456187748, 4173156070774045271, 15647643457869530627,
15642078237964257476, 1405048341078324037, 3059193199283698832, 1605012781983592984,
7134876918849821827, 5796994175286958720, 7251651436095127661, 4565856221886323991,
}
MDS_MATRIX = [STATE_SIZE][STATE_SIZE]uint64{
{
61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454,
33823, 28750, 1108,
},
{
1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244,
7454, 33823, 28750,
},
{
28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865,
43244, 7454, 33823,
},
{
33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034,
53865, 43244, 7454,
},
{
7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951,
12034, 53865, 43244,
},
{
43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521,
56951, 12034, 53865,
},
{
53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351,
27521, 56951, 12034,
},
{
12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901,
41351, 27521, 56951,
},
{
56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021,
40901, 41351, 27521,
},
{
27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689,
12021, 40901, 41351,
},
{
41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798,
59689, 12021, 40901,
},
{
40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845,
26798, 59689, 12021,
},
{
12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402,
17845, 26798, 59689,
},
{
59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108,
61402, 17845, 26798,
},
{
26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750,
1108, 61402, 17845,
},
{
17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823,
28750, 1108, 61402,
},
}
INIT_SPONGE = [16]uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
INIT_SPONGE_FIX = [16]uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295}
)
func Tip5HashBelts(input []Belt) [5]uint64 {
inputLen := len(input)
q := inputLen / RATE
r := inputLen % RATE
for i := range input {
if !BaseCheck(input[i].Value) {
fmt.Printf("element %d must be inside the field\n", i)
}
input[i].Value = montify(input[i].Value)
}
input = append(input, Belt{Value: montify(1)})
for i := 0; i < (RATE-r)-1; i++ {
input = append(input, Belt{Value: montify(0)})
}
sponge := INIT_SPONGE
inputAbsorb := input
cntQ := q
for {
scagInput := inputAbsorb[:RATE]
slagInput := inputAbsorb[RATE:]
for i := 0; i < RATE; i++ {
sponge[i] = scagInput[i].Value
}
sponge = permute(sponge)
if cntQ == 0 {
break
}
cntQ--
inputAbsorb = slagInput
}
digest := [DIGEST_LENGTH]uint64{0, 0, 0, 0, 0}
for i := 0; i < DIGEST_LENGTH; i++ {
digest[i] = montReduction(new(big.Int).SetUint64(sponge[i]))
}
return digest
}
func Tip5HashTenCell(input []Belt) [5]uint64 {
inputLen := len(input)
q := inputLen / RATE
r := inputLen % RATE
if q != 1 || r != 0 {
panic("input is not 10 cell")
}
for i := range input {
if !BaseCheck(input[i].Value) {
fmt.Printf("element %d must be inside the field\n", i)
}
input[i].Value = montify(input[i].Value)
}
sponge := INIT_SPONGE_FIX
for i := 0; i < RATE; i++ {
sponge[i] = input[i].Value
}
sponge = permute(sponge)
digest := [DIGEST_LENGTH]uint64{0, 0, 0, 0, 0}
for i := 0; i < DIGEST_LENGTH; i++ {
digest[i] = montReduction(new(big.Int).SetUint64(sponge[i]))
}
return digest
}
func Tip5RehashTenCell(hash1 [5]uint64, hash2 [5]uint64) [5]uint64 {
belts := []Belt{}
for _, i := range hash1 {
belts = append(belts, Belt{Value: i})
}
for _, i := range hash2 {
belts = append(belts, Belt{Value: i})
}
return Tip5HashTenCell(belts)
}
func permute(sponge [16]uint64) [16]uint64 {
res := sponge
for i := 0; i < NUM_ROUNDS; i++ {
a := sboxLayer(res)
b := linearLayer(a)
for j := 0; j < STATE_SIZE; j++ {
roundConst := new(big.Int).SetUint64(ROUND_CONSTANTS[i*STATE_SIZE+j])
product := new(big.Int).Mul(roundConst, R)
roundConst = roundConst.Mod(product, PRIME_128)
res[j] = badd(roundConst.Uint64(), b[j])
}
}
return res
}
func Tip5HashToBase58(hash [5]uint64) string {
result := big.NewInt(0)
for i, value := range hash {
result.Add(result, new(big.Int).Mul(new(big.Int).SetUint64(value), new(big.Int).Exp(PRIME_128, big.NewInt(int64(i)), nil)))
}
return base58.Encode(result.Bytes())
}
func Base58ToTip5Hash(data string) [5]uint64 {
dataBigInt := new(big.Int).SetBytes(base58.Decode(data))
result := [5]uint64{}
for i := 0; i < 5; i++ {
resultBigInt := new(big.Int)
result[i] = resultBigInt.Mod(dataBigInt, PRIME_128).Uint64()
dataBigInt.Div(dataBigInt, PRIME_128)
}
return result
}
func TruncGOrder(a [5]uint64) *big.Int {
dataBigInt := new(big.Int).SetUint64(a[0])
dataBigInt.Add(dataBigInt, new(big.Int).Mul(P_BIG, new(big.Int).SetUint64(a[1])))
dataBigInt.Add(dataBigInt, new(big.Int).Mul(P_BIG_2, new(big.Int).SetUint64(a[2])))
dataBigInt.Add(dataBigInt, new(big.Int).Mul(P_BIG_3, new(big.Int).SetUint64(a[3])))
return dataBigInt.Mod(dataBigInt, G_ORDER)
}
func sboxLayer(state [16]uint64) [16]uint64 {
res := INIT_SPONGE
for i := 0; i < NUM_SPLIT_AND_LOOKUP; i++ {
bytes := make([]byte, 8)
binary.LittleEndian.PutUint64(bytes, state[i])
for j := 0; j < 8; j++ {
bytes[j] = LOOKUP_TABLE[bytes[j]]
}
res[i] = binary.LittleEndian.Uint64(bytes)
}
for i := NUM_SPLIT_AND_LOOKUP; i < STATE_SIZE; i++ {
res[i] = bpow(state[i], 7)
}
return res
}
func linearLayer(state [16]uint64) [16]uint64 {
res := INIT_SPONGE
for i := 0; i < 16; i++ {
for j := 0; j < 16; j++ {
matrixElement := MDS_MATRIX[i][j]
product := bmul(matrixElement, state[j])
res[i] = badd(res[i], product)
}
}
return res
}

18
go.mod Normal file
View File

@ -0,0 +1,18 @@
module github.com/phamminh0811/private-grpc
go 1.24.5
require (
github.com/btcsuite/btcd/btcutil v1.1.6
github.com/cosmos/go-bip39 v1.0.0
golang.org/x/crypto v0.39.0
google.golang.org/grpc v1.75.1
google.golang.org/protobuf v1.36.9
)
require (
golang.org/x/net v0.41.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.26.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
)

151
go.sum Normal file
View File

@ -0,0 +1,151 @@
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A=
github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg=
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00=
github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c=
github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

33
main.go Normal file
View File

@ -0,0 +1,33 @@
package main
import (
"log"
"net"
"github.com/phamminh0811/private-grpc/nockchain"
"github.com/phamminh0811/private-grpc/wallet"
"google.golang.org/grpc"
)
func main() {
nc, err := wallet.NewNockchainClient("nockchain-api.zorp.io:443")
if err != nil {
panic(err)
}
// TODO: read key from env
handler := wallet.NewGprcHandler(*nc)
server := grpc.NewServer()
nockchain.RegisterWalletServiceServer(server, &handler)
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
log.Println("gRPC server started on :50051")
if err := server.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}

1386
nockchain/blockchain.pb.go Normal file

File diff suppressed because it is too large Load Diff

554
nockchain/nockchain.pb.go Normal file
View File

@ -0,0 +1,554 @@
// nockchain/public/v1/nockchain.proto
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.9
// protoc v3.20.3
// source: nockchain.proto
package nockchain
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type WalletGetBalanceRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// pubkey cheetah point; specific address, or current wallet
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
// Pagination parameters. The server enforces limits and may return fewer
// entries than requested to respect message size and policy. For consistent
// paging across a stable snapshot, pass along the returned page_token from
// the previous response without modification.
Page *PageRequest `protobuf:"bytes,2,opt,name=page,proto3" json:"page,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *WalletGetBalanceRequest) Reset() {
*x = WalletGetBalanceRequest{}
mi := &file_nockchain_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *WalletGetBalanceRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WalletGetBalanceRequest) ProtoMessage() {}
func (x *WalletGetBalanceRequest) ProtoReflect() protoreflect.Message {
mi := &file_nockchain_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WalletGetBalanceRequest.ProtoReflect.Descriptor instead.
func (*WalletGetBalanceRequest) Descriptor() ([]byte, []int) {
return file_nockchain_proto_rawDescGZIP(), []int{0}
}
func (x *WalletGetBalanceRequest) GetAddress() string {
if x != nil {
return x.Address
}
return ""
}
func (x *WalletGetBalanceRequest) GetPage() *PageRequest {
if x != nil {
return x.Page
}
return nil
}
type WalletGetBalanceResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Types that are valid to be assigned to Result:
//
// *WalletGetBalanceResponse_Balance
// *WalletGetBalanceResponse_Error
Result isWalletGetBalanceResponse_Result `protobuf_oneof:"result"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *WalletGetBalanceResponse) Reset() {
*x = WalletGetBalanceResponse{}
mi := &file_nockchain_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *WalletGetBalanceResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WalletGetBalanceResponse) ProtoMessage() {}
func (x *WalletGetBalanceResponse) ProtoReflect() protoreflect.Message {
mi := &file_nockchain_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WalletGetBalanceResponse.ProtoReflect.Descriptor instead.
func (*WalletGetBalanceResponse) Descriptor() ([]byte, []int) {
return file_nockchain_proto_rawDescGZIP(), []int{1}
}
func (x *WalletGetBalanceResponse) GetResult() isWalletGetBalanceResponse_Result {
if x != nil {
return x.Result
}
return nil
}
func (x *WalletGetBalanceResponse) GetBalance() *WalletBalanceData {
if x != nil {
if x, ok := x.Result.(*WalletGetBalanceResponse_Balance); ok {
return x.Balance
}
}
return nil
}
func (x *WalletGetBalanceResponse) GetError() *ErrorStatus {
if x != nil {
if x, ok := x.Result.(*WalletGetBalanceResponse_Error); ok {
return x.Error
}
}
return nil
}
type isWalletGetBalanceResponse_Result interface {
isWalletGetBalanceResponse_Result()
}
type WalletGetBalanceResponse_Balance struct {
// Paginated wallet balance data with full entries and snapshot metadata.
// Continue paging using `balance.page.next_page_token` until empty. Clients
// should treat the page token as opaque; it may encode snapshot identity
// and the last returned key.
Balance *WalletBalanceData `protobuf:"bytes,1,opt,name=balance,proto3,oneof"`
}
type WalletGetBalanceResponse_Error struct {
Error *ErrorStatus `protobuf:"bytes,2,opt,name=error,proto3,oneof"`
}
func (*WalletGetBalanceResponse_Balance) isWalletGetBalanceResponse_Result() {}
func (*WalletGetBalanceResponse_Error) isWalletGetBalanceResponse_Result() {}
type WalletSendTransactionRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
TxId *Hash `protobuf:"bytes,1,opt,name=tx_id,json=txId,proto3" json:"tx_id,omitempty"` // base58 encoded transaction ID for tracking
RawTx *RawTransaction `protobuf:"bytes,2,opt,name=raw_tx,json=rawTx,proto3" json:"raw_tx,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *WalletSendTransactionRequest) Reset() {
*x = WalletSendTransactionRequest{}
mi := &file_nockchain_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *WalletSendTransactionRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WalletSendTransactionRequest) ProtoMessage() {}
func (x *WalletSendTransactionRequest) ProtoReflect() protoreflect.Message {
mi := &file_nockchain_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WalletSendTransactionRequest.ProtoReflect.Descriptor instead.
func (*WalletSendTransactionRequest) Descriptor() ([]byte, []int) {
return file_nockchain_proto_rawDescGZIP(), []int{2}
}
func (x *WalletSendTransactionRequest) GetTxId() *Hash {
if x != nil {
return x.TxId
}
return nil
}
func (x *WalletSendTransactionRequest) GetRawTx() *RawTransaction {
if x != nil {
return x.RawTx
}
return nil
}
type WalletSendTransactionResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Types that are valid to be assigned to Result:
//
// *WalletSendTransactionResponse_Ack
// *WalletSendTransactionResponse_Error
Result isWalletSendTransactionResponse_Result `protobuf_oneof:"result"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *WalletSendTransactionResponse) Reset() {
*x = WalletSendTransactionResponse{}
mi := &file_nockchain_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *WalletSendTransactionResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WalletSendTransactionResponse) ProtoMessage() {}
func (x *WalletSendTransactionResponse) ProtoReflect() protoreflect.Message {
mi := &file_nockchain_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WalletSendTransactionResponse.ProtoReflect.Descriptor instead.
func (*WalletSendTransactionResponse) Descriptor() ([]byte, []int) {
return file_nockchain_proto_rawDescGZIP(), []int{3}
}
func (x *WalletSendTransactionResponse) GetResult() isWalletSendTransactionResponse_Result {
if x != nil {
return x.Result
}
return nil
}
func (x *WalletSendTransactionResponse) GetAck() *Acknowledged {
if x != nil {
if x, ok := x.Result.(*WalletSendTransactionResponse_Ack); ok {
return x.Ack
}
}
return nil
}
func (x *WalletSendTransactionResponse) GetError() *ErrorStatus {
if x != nil {
if x, ok := x.Result.(*WalletSendTransactionResponse_Error); ok {
return x.Error
}
}
return nil
}
type isWalletSendTransactionResponse_Result interface {
isWalletSendTransactionResponse_Result()
}
type WalletSendTransactionResponse_Ack struct {
// true is request was acknowledge by node,
// this does not mean that the transaction was
// confirmed and/or accepted.
Ack *Acknowledged `protobuf:"bytes,1,opt,name=ack,proto3,oneof"`
}
type WalletSendTransactionResponse_Error struct {
Error *ErrorStatus `protobuf:"bytes,2,opt,name=error,proto3,oneof"`
}
func (*WalletSendTransactionResponse_Ack) isWalletSendTransactionResponse_Result() {}
func (*WalletSendTransactionResponse_Error) isWalletSendTransactionResponse_Result() {}
type TransactionAcceptedRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
TxId *Base58Hash `protobuf:"bytes,1,opt,name=tx_id,json=txId,proto3" json:"tx_id,omitempty"` // base58 encoded transaction ID for tracking
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *TransactionAcceptedRequest) Reset() {
*x = TransactionAcceptedRequest{}
mi := &file_nockchain_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TransactionAcceptedRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TransactionAcceptedRequest) ProtoMessage() {}
func (x *TransactionAcceptedRequest) ProtoReflect() protoreflect.Message {
mi := &file_nockchain_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TransactionAcceptedRequest.ProtoReflect.Descriptor instead.
func (*TransactionAcceptedRequest) Descriptor() ([]byte, []int) {
return file_nockchain_proto_rawDescGZIP(), []int{4}
}
func (x *TransactionAcceptedRequest) GetTxId() *Base58Hash {
if x != nil {
return x.TxId
}
return nil
}
type TransactionAcceptedResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// true if transaction was accepted by node. this not does mean that the
// transaction was confirmed. Just that it was validated by the node and
// added to its raw-tx set.
//
// Types that are valid to be assigned to Result:
//
// *TransactionAcceptedResponse_Accepted
// *TransactionAcceptedResponse_Error
Result isTransactionAcceptedResponse_Result `protobuf_oneof:"result"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *TransactionAcceptedResponse) Reset() {
*x = TransactionAcceptedResponse{}
mi := &file_nockchain_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TransactionAcceptedResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TransactionAcceptedResponse) ProtoMessage() {}
func (x *TransactionAcceptedResponse) ProtoReflect() protoreflect.Message {
mi := &file_nockchain_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TransactionAcceptedResponse.ProtoReflect.Descriptor instead.
func (*TransactionAcceptedResponse) Descriptor() ([]byte, []int) {
return file_nockchain_proto_rawDescGZIP(), []int{5}
}
func (x *TransactionAcceptedResponse) GetResult() isTransactionAcceptedResponse_Result {
if x != nil {
return x.Result
}
return nil
}
func (x *TransactionAcceptedResponse) GetAccepted() bool {
if x != nil {
if x, ok := x.Result.(*TransactionAcceptedResponse_Accepted); ok {
return x.Accepted
}
}
return false
}
func (x *TransactionAcceptedResponse) GetError() *ErrorStatus {
if x != nil {
if x, ok := x.Result.(*TransactionAcceptedResponse_Error); ok {
return x.Error
}
}
return nil
}
type isTransactionAcceptedResponse_Result interface {
isTransactionAcceptedResponse_Result()
}
type TransactionAcceptedResponse_Accepted struct {
Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3,oneof"`
}
type TransactionAcceptedResponse_Error struct {
Error *ErrorStatus `protobuf:"bytes,2,opt,name=error,proto3,oneof"`
}
func (*TransactionAcceptedResponse_Accepted) isTransactionAcceptedResponse_Result() {}
func (*TransactionAcceptedResponse_Error) isTransactionAcceptedResponse_Result() {}
var File_nockchain_proto protoreflect.FileDescriptor
const file_nockchain_proto_rawDesc = "" +
"\n" +
"\x0fnockchain.proto\x12\x13nockchain.public.v1\x1a\x10blockchain.proto\x1a\x10primitives.proto\x1a\x10pagination.proto\"i\n" +
"\x17WalletGetBalanceRequest\x12\x18\n" +
"\aaddress\x18\x01 \x01(\tR\aaddress\x124\n" +
"\x04page\x18\x02 \x01(\v2 .nockchain.public.v1.PageRequestR\x04page\"\xa2\x01\n" +
"\x18WalletGetBalanceResponse\x12B\n" +
"\abalance\x18\x01 \x01(\v2&.nockchain.public.v1.WalletBalanceDataH\x00R\abalance\x128\n" +
"\x05error\x18\x02 \x01(\v2 .nockchain.public.v1.ErrorStatusH\x00R\x05errorB\b\n" +
"\x06result\"\x8a\x01\n" +
"\x1cWalletSendTransactionRequest\x12.\n" +
"\x05tx_id\x18\x01 \x01(\v2\x19.nockchain.public.v1.HashR\x04txId\x12:\n" +
"\x06raw_tx\x18\x02 \x01(\v2#.nockchain.public.v1.RawTransactionR\x05rawTx\"\x9a\x01\n" +
"\x1dWalletSendTransactionResponse\x125\n" +
"\x03ack\x18\x01 \x01(\v2!.nockchain.public.v1.AcknowledgedH\x00R\x03ack\x128\n" +
"\x05error\x18\x02 \x01(\v2 .nockchain.public.v1.ErrorStatusH\x00R\x05errorB\b\n" +
"\x06result\"R\n" +
"\x1aTransactionAcceptedRequest\x124\n" +
"\x05tx_id\x18\x01 \x01(\v2\x1f.nockchain.public.v1.Base58HashR\x04txId\"\x7f\n" +
"\x1bTransactionAcceptedResponse\x12\x1c\n" +
"\baccepted\x18\x01 \x01(\bH\x00R\baccepted\x128\n" +
"\x05error\x18\x02 \x01(\v2 .nockchain.public.v1.ErrorStatusH\x00R\x05errorB\b\n" +
"\x06result2\xfd\x02\n" +
"\x10NockchainService\x12o\n" +
"\x10WalletGetBalance\x12,.nockchain.public.v1.WalletGetBalanceRequest\x1a-.nockchain.public.v1.WalletGetBalanceResponse\x12~\n" +
"\x15WalletSendTransaction\x121.nockchain.public.v1.WalletSendTransactionRequest\x1a2.nockchain.public.v1.WalletSendTransactionResponse\x12x\n" +
"\x13TransactionAccepted\x12/.nockchain.public.v1.TransactionAcceptedRequest\x1a0.nockchain.public.v1.TransactionAcceptedResponseB\x0eZ\f./;nockchainb\x06proto3"
var (
file_nockchain_proto_rawDescOnce sync.Once
file_nockchain_proto_rawDescData []byte
)
func file_nockchain_proto_rawDescGZIP() []byte {
file_nockchain_proto_rawDescOnce.Do(func() {
file_nockchain_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_nockchain_proto_rawDesc), len(file_nockchain_proto_rawDesc)))
})
return file_nockchain_proto_rawDescData
}
var file_nockchain_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_nockchain_proto_goTypes = []any{
(*WalletGetBalanceRequest)(nil), // 0: nockchain.public.v1.WalletGetBalanceRequest
(*WalletGetBalanceResponse)(nil), // 1: nockchain.public.v1.WalletGetBalanceResponse
(*WalletSendTransactionRequest)(nil), // 2: nockchain.public.v1.WalletSendTransactionRequest
(*WalletSendTransactionResponse)(nil), // 3: nockchain.public.v1.WalletSendTransactionResponse
(*TransactionAcceptedRequest)(nil), // 4: nockchain.public.v1.TransactionAcceptedRequest
(*TransactionAcceptedResponse)(nil), // 5: nockchain.public.v1.TransactionAcceptedResponse
(*PageRequest)(nil), // 6: nockchain.public.v1.PageRequest
(*WalletBalanceData)(nil), // 7: nockchain.public.v1.WalletBalanceData
(*ErrorStatus)(nil), // 8: nockchain.public.v1.ErrorStatus
(*Hash)(nil), // 9: nockchain.public.v1.Hash
(*RawTransaction)(nil), // 10: nockchain.public.v1.RawTransaction
(*Acknowledged)(nil), // 11: nockchain.public.v1.Acknowledged
(*Base58Hash)(nil), // 12: nockchain.public.v1.Base58Hash
}
var file_nockchain_proto_depIdxs = []int32{
6, // 0: nockchain.public.v1.WalletGetBalanceRequest.page:type_name -> nockchain.public.v1.PageRequest
7, // 1: nockchain.public.v1.WalletGetBalanceResponse.balance:type_name -> nockchain.public.v1.WalletBalanceData
8, // 2: nockchain.public.v1.WalletGetBalanceResponse.error:type_name -> nockchain.public.v1.ErrorStatus
9, // 3: nockchain.public.v1.WalletSendTransactionRequest.tx_id:type_name -> nockchain.public.v1.Hash
10, // 4: nockchain.public.v1.WalletSendTransactionRequest.raw_tx:type_name -> nockchain.public.v1.RawTransaction
11, // 5: nockchain.public.v1.WalletSendTransactionResponse.ack:type_name -> nockchain.public.v1.Acknowledged
8, // 6: nockchain.public.v1.WalletSendTransactionResponse.error:type_name -> nockchain.public.v1.ErrorStatus
12, // 7: nockchain.public.v1.TransactionAcceptedRequest.tx_id:type_name -> nockchain.public.v1.Base58Hash
8, // 8: nockchain.public.v1.TransactionAcceptedResponse.error:type_name -> nockchain.public.v1.ErrorStatus
0, // 9: nockchain.public.v1.NockchainService.WalletGetBalance:input_type -> nockchain.public.v1.WalletGetBalanceRequest
2, // 10: nockchain.public.v1.NockchainService.WalletSendTransaction:input_type -> nockchain.public.v1.WalletSendTransactionRequest
4, // 11: nockchain.public.v1.NockchainService.TransactionAccepted:input_type -> nockchain.public.v1.TransactionAcceptedRequest
1, // 12: nockchain.public.v1.NockchainService.WalletGetBalance:output_type -> nockchain.public.v1.WalletGetBalanceResponse
3, // 13: nockchain.public.v1.NockchainService.WalletSendTransaction:output_type -> nockchain.public.v1.WalletSendTransactionResponse
5, // 14: nockchain.public.v1.NockchainService.TransactionAccepted:output_type -> nockchain.public.v1.TransactionAcceptedResponse
12, // [12:15] is the sub-list for method output_type
9, // [9:12] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
}
func init() { file_nockchain_proto_init() }
func file_nockchain_proto_init() {
if File_nockchain_proto != nil {
return
}
file_blockchain_proto_init()
file_primitives_proto_init()
file_pagination_proto_init()
file_nockchain_proto_msgTypes[1].OneofWrappers = []any{
(*WalletGetBalanceResponse_Balance)(nil),
(*WalletGetBalanceResponse_Error)(nil),
}
file_nockchain_proto_msgTypes[3].OneofWrappers = []any{
(*WalletSendTransactionResponse_Ack)(nil),
(*WalletSendTransactionResponse_Error)(nil),
}
file_nockchain_proto_msgTypes[5].OneofWrappers = []any{
(*TransactionAcceptedResponse_Accepted)(nil),
(*TransactionAcceptedResponse_Error)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_nockchain_proto_rawDesc), len(file_nockchain_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_nockchain_proto_goTypes,
DependencyIndexes: file_nockchain_proto_depIdxs,
MessageInfos: file_nockchain_proto_msgTypes,
}.Build()
File_nockchain_proto = out.File
file_nockchain_proto_goTypes = nil
file_nockchain_proto_depIdxs = nil
}

View File

@ -0,0 +1,199 @@
// nockchain/public/v1/nockchain.proto
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v3.20.3
// source: nockchain.proto
package nockchain
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
NockchainService_WalletGetBalance_FullMethodName = "/nockchain.public.v1.NockchainService/WalletGetBalance"
NockchainService_WalletSendTransaction_FullMethodName = "/nockchain.public.v1.NockchainService/WalletSendTransaction"
NockchainService_TransactionAccepted_FullMethodName = "/nockchain.public.v1.NockchainService/TransactionAccepted"
)
// NockchainServiceClient is the client API for NockchainService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type NockchainServiceClient interface {
WalletGetBalance(ctx context.Context, in *WalletGetBalanceRequest, opts ...grpc.CallOption) (*WalletGetBalanceResponse, error)
WalletSendTransaction(ctx context.Context, in *WalletSendTransactionRequest, opts ...grpc.CallOption) (*WalletSendTransactionResponse, error)
TransactionAccepted(ctx context.Context, in *TransactionAcceptedRequest, opts ...grpc.CallOption) (*TransactionAcceptedResponse, error)
}
type nockchainServiceClient struct {
cc grpc.ClientConnInterface
}
func NewNockchainServiceClient(cc grpc.ClientConnInterface) NockchainServiceClient {
return &nockchainServiceClient{cc}
}
func (c *nockchainServiceClient) WalletGetBalance(ctx context.Context, in *WalletGetBalanceRequest, opts ...grpc.CallOption) (*WalletGetBalanceResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(WalletGetBalanceResponse)
err := c.cc.Invoke(ctx, NockchainService_WalletGetBalance_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *nockchainServiceClient) WalletSendTransaction(ctx context.Context, in *WalletSendTransactionRequest, opts ...grpc.CallOption) (*WalletSendTransactionResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(WalletSendTransactionResponse)
err := c.cc.Invoke(ctx, NockchainService_WalletSendTransaction_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *nockchainServiceClient) TransactionAccepted(ctx context.Context, in *TransactionAcceptedRequest, opts ...grpc.CallOption) (*TransactionAcceptedResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TransactionAcceptedResponse)
err := c.cc.Invoke(ctx, NockchainService_TransactionAccepted_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// NockchainServiceServer is the server API for NockchainService service.
// All implementations must embed UnimplementedNockchainServiceServer
// for forward compatibility.
type NockchainServiceServer interface {
WalletGetBalance(context.Context, *WalletGetBalanceRequest) (*WalletGetBalanceResponse, error)
WalletSendTransaction(context.Context, *WalletSendTransactionRequest) (*WalletSendTransactionResponse, error)
TransactionAccepted(context.Context, *TransactionAcceptedRequest) (*TransactionAcceptedResponse, error)
mustEmbedUnimplementedNockchainServiceServer()
}
// UnimplementedNockchainServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedNockchainServiceServer struct{}
func (UnimplementedNockchainServiceServer) WalletGetBalance(context.Context, *WalletGetBalanceRequest) (*WalletGetBalanceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WalletGetBalance not implemented")
}
func (UnimplementedNockchainServiceServer) WalletSendTransaction(context.Context, *WalletSendTransactionRequest) (*WalletSendTransactionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WalletSendTransaction not implemented")
}
func (UnimplementedNockchainServiceServer) TransactionAccepted(context.Context, *TransactionAcceptedRequest) (*TransactionAcceptedResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method TransactionAccepted not implemented")
}
func (UnimplementedNockchainServiceServer) mustEmbedUnimplementedNockchainServiceServer() {}
func (UnimplementedNockchainServiceServer) testEmbeddedByValue() {}
// UnsafeNockchainServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to NockchainServiceServer will
// result in compilation errors.
type UnsafeNockchainServiceServer interface {
mustEmbedUnimplementedNockchainServiceServer()
}
func RegisterNockchainServiceServer(s grpc.ServiceRegistrar, srv NockchainServiceServer) {
// If the following call pancis, it indicates UnimplementedNockchainServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&NockchainService_ServiceDesc, srv)
}
func _NockchainService_WalletGetBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(WalletGetBalanceRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(NockchainServiceServer).WalletGetBalance(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: NockchainService_WalletGetBalance_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NockchainServiceServer).WalletGetBalance(ctx, req.(*WalletGetBalanceRequest))
}
return interceptor(ctx, in, info, handler)
}
func _NockchainService_WalletSendTransaction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(WalletSendTransactionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(NockchainServiceServer).WalletSendTransaction(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: NockchainService_WalletSendTransaction_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NockchainServiceServer).WalletSendTransaction(ctx, req.(*WalletSendTransactionRequest))
}
return interceptor(ctx, in, info, handler)
}
func _NockchainService_TransactionAccepted_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TransactionAcceptedRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(NockchainServiceServer).TransactionAccepted(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: NockchainService_TransactionAccepted_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NockchainServiceServer).TransactionAccepted(ctx, req.(*TransactionAcceptedRequest))
}
return interceptor(ctx, in, info, handler)
}
// NockchainService_ServiceDesc is the grpc.ServiceDesc for NockchainService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var NockchainService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "nockchain.public.v1.NockchainService",
HandlerType: (*NockchainServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "WalletGetBalance",
Handler: _NockchainService_WalletGetBalance_Handler,
},
{
MethodName: "WalletSendTransaction",
Handler: _NockchainService_WalletSendTransaction_Handler,
},
{
MethodName: "TransactionAccepted",
Handler: _NockchainService_TransactionAccepted_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "nockchain.proto",
}

211
nockchain/pagination.pb.go Normal file
View File

@ -0,0 +1,211 @@
// nockchain/common/v1/pagination.proto
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.9
// protoc v3.20.3
// source: pagination.proto
package nockchain
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Generic pagination parameters for list-style RPCs.
// These types are intended to be reused across public APIs.
//
// Contract:
// - The server may return fewer items than requested (client_page_items_limit is a hint).
// - page_token is an opaque cursor produced by the server; clients must treat
// it as a black box. Servers may encode snapshot identity and last-key.
// - For consistent pagination, clients should include the returned page_token
// in the next request without modification.
// - Servers may enforce a maximum client_page_items_limit and/or byte budget regardless of
// client hints.
type PageRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Maximum number of items to return. The server may return fewer items
// than requested. Clients should not rely on receiving exactly this count.
ClientPageItemsLimit uint32 `protobuf:"varint,1,opt,name=client_page_items_limit,json=clientPageItemsLimit,proto3" json:"client_page_items_limit,omitempty"`
// Opaque cursor returned by a previous call. When set, the server resumes
// the listing from the position described by the token.
// An empty token indicates the first page.
PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"`
// Optional soft limit on the uncompressed bytes to return in a single page.
// The server may ignore or cap this value according to policy. This refers
// to the gRPC payload size after protobuf encoding and decompression.
MaxBytes uint64 `protobuf:"varint,3,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PageRequest) Reset() {
*x = PageRequest{}
mi := &file_pagination_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PageRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PageRequest) ProtoMessage() {}
func (x *PageRequest) ProtoReflect() protoreflect.Message {
mi := &file_pagination_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PageRequest.ProtoReflect.Descriptor instead.
func (*PageRequest) Descriptor() ([]byte, []int) {
return file_pagination_proto_rawDescGZIP(), []int{0}
}
func (x *PageRequest) GetClientPageItemsLimit() uint32 {
if x != nil {
return x.ClientPageItemsLimit
}
return 0
}
func (x *PageRequest) GetPageToken() string {
if x != nil {
return x.PageToken
}
return ""
}
func (x *PageRequest) GetMaxBytes() uint64 {
if x != nil {
return x.MaxBytes
}
return 0
}
type PageResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Opaque cursor for fetching the next page. Empty when there are no more
// results.
NextPageToken string `protobuf:"bytes,1,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PageResponse) Reset() {
*x = PageResponse{}
mi := &file_pagination_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PageResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PageResponse) ProtoMessage() {}
func (x *PageResponse) ProtoReflect() protoreflect.Message {
mi := &file_pagination_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PageResponse.ProtoReflect.Descriptor instead.
func (*PageResponse) Descriptor() ([]byte, []int) {
return file_pagination_proto_rawDescGZIP(), []int{1}
}
func (x *PageResponse) GetNextPageToken() string {
if x != nil {
return x.NextPageToken
}
return ""
}
var File_pagination_proto protoreflect.FileDescriptor
const file_pagination_proto_rawDesc = "" +
"\n" +
"\x10pagination.proto\x12\x13nockchain.public.v1\"\x80\x01\n" +
"\vPageRequest\x125\n" +
"\x17client_page_items_limit\x18\x01 \x01(\rR\x14clientPageItemsLimit\x12\x1d\n" +
"\n" +
"page_token\x18\x02 \x01(\tR\tpageToken\x12\x1b\n" +
"\tmax_bytes\x18\x03 \x01(\x04R\bmaxBytes\"6\n" +
"\fPageResponse\x12&\n" +
"\x0fnext_page_token\x18\x01 \x01(\tR\rnextPageTokenB\x0eZ\f./;nockchainb\x06proto3"
var (
file_pagination_proto_rawDescOnce sync.Once
file_pagination_proto_rawDescData []byte
)
func file_pagination_proto_rawDescGZIP() []byte {
file_pagination_proto_rawDescOnce.Do(func() {
file_pagination_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_pagination_proto_rawDesc), len(file_pagination_proto_rawDesc)))
})
return file_pagination_proto_rawDescData
}
var file_pagination_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_pagination_proto_goTypes = []any{
(*PageRequest)(nil), // 0: nockchain.public.v1.PageRequest
(*PageResponse)(nil), // 1: nockchain.public.v1.PageResponse
}
var file_pagination_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_pagination_proto_init() }
func file_pagination_proto_init() {
if File_pagination_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_pagination_proto_rawDesc), len(file_pagination_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_pagination_proto_goTypes,
DependencyIndexes: file_pagination_proto_depIdxs,
MessageInfos: file_pagination_proto_msgTypes,
}.Build()
File_pagination_proto = out.File
file_pagination_proto_goTypes = nil
file_pagination_proto_depIdxs = nil
}

1151
nockchain/primitives.pb.go Normal file

File diff suppressed because it is too large Load Diff

954
nockchain/service.pb.go Normal file
View File

@ -0,0 +1,954 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.9
// protoc v3.20.3
// source: service.proto
package nockchain
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type KeygenRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *KeygenRequest) Reset() {
*x = KeygenRequest{}
mi := &file_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *KeygenRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*KeygenRequest) ProtoMessage() {}
func (x *KeygenRequest) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use KeygenRequest.ProtoReflect.Descriptor instead.
func (*KeygenRequest) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{0}
}
type KeygenResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
PublicKey string `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
PrivateKey string `protobuf:"bytes,2,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"`
Seed string `protobuf:"bytes,3,opt,name=seed,proto3" json:"seed,omitempty"`
ChainCode string `protobuf:"bytes,4,opt,name=chain_code,json=chainCode,proto3" json:"chain_code,omitempty"`
ImportPrivateKey string `protobuf:"bytes,5,opt,name=import_private_key,json=importPrivateKey,proto3" json:"import_private_key,omitempty"`
ImportPublicKey string `protobuf:"bytes,6,opt,name=import_public_key,json=importPublicKey,proto3" json:"import_public_key,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *KeygenResponse) Reset() {
*x = KeygenResponse{}
mi := &file_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *KeygenResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*KeygenResponse) ProtoMessage() {}
func (x *KeygenResponse) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use KeygenResponse.ProtoReflect.Descriptor instead.
func (*KeygenResponse) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{1}
}
func (x *KeygenResponse) GetPublicKey() string {
if x != nil {
return x.PublicKey
}
return ""
}
func (x *KeygenResponse) GetPrivateKey() string {
if x != nil {
return x.PrivateKey
}
return ""
}
func (x *KeygenResponse) GetSeed() string {
if x != nil {
return x.Seed
}
return ""
}
func (x *KeygenResponse) GetChainCode() string {
if x != nil {
return x.ChainCode
}
return ""
}
func (x *KeygenResponse) GetImportPrivateKey() string {
if x != nil {
return x.ImportPrivateKey
}
return ""
}
func (x *KeygenResponse) GetImportPublicKey() string {
if x != nil {
return x.ImportPublicKey
}
return ""
}
type ImportKeysRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
ImportType ImportType `protobuf:"varint,2,opt,name=import_type,json=importType,proto3,enum=nockchain.public.v1.ImportType" json:"import_type,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ImportKeysRequest) Reset() {
*x = ImportKeysRequest{}
mi := &file_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ImportKeysRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ImportKeysRequest) ProtoMessage() {}
func (x *ImportKeysRequest) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ImportKeysRequest.ProtoReflect.Descriptor instead.
func (*ImportKeysRequest) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{2}
}
func (x *ImportKeysRequest) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *ImportKeysRequest) GetImportType() ImportType {
if x != nil {
return x.ImportType
}
return ImportType_UNDEFINED
}
type ImportKeysResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
PublicKey string `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
PrivateKey string `protobuf:"bytes,2,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"`
Seed string `protobuf:"bytes,3,opt,name=seed,proto3" json:"seed,omitempty"`
ChainCode string `protobuf:"bytes,4,opt,name=chain_code,json=chainCode,proto3" json:"chain_code,omitempty"`
ImportPrivateKey string `protobuf:"bytes,5,opt,name=import_private_key,json=importPrivateKey,proto3" json:"import_private_key,omitempty"`
ImportPublicKey string `protobuf:"bytes,6,opt,name=import_public_key,json=importPublicKey,proto3" json:"import_public_key,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ImportKeysResponse) Reset() {
*x = ImportKeysResponse{}
mi := &file_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ImportKeysResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ImportKeysResponse) ProtoMessage() {}
func (x *ImportKeysResponse) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ImportKeysResponse.ProtoReflect.Descriptor instead.
func (*ImportKeysResponse) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{3}
}
func (x *ImportKeysResponse) GetPublicKey() string {
if x != nil {
return x.PublicKey
}
return ""
}
func (x *ImportKeysResponse) GetPrivateKey() string {
if x != nil {
return x.PrivateKey
}
return ""
}
func (x *ImportKeysResponse) GetSeed() string {
if x != nil {
return x.Seed
}
return ""
}
func (x *ImportKeysResponse) GetChainCode() string {
if x != nil {
return x.ChainCode
}
return ""
}
func (x *ImportKeysResponse) GetImportPrivateKey() string {
if x != nil {
return x.ImportPrivateKey
}
return ""
}
func (x *ImportKeysResponse) GetImportPublicKey() string {
if x != nil {
return x.ImportPublicKey
}
return ""
}
type DeriveChildRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
ImportedKey string `protobuf:"bytes,1,opt,name=imported_key,json=importedKey,proto3" json:"imported_key,omitempty"`
Index uint64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"`
Hardened bool `protobuf:"varint,3,opt,name=hardened,proto3" json:"hardened,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeriveChildRequest) Reset() {
*x = DeriveChildRequest{}
mi := &file_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeriveChildRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeriveChildRequest) ProtoMessage() {}
func (x *DeriveChildRequest) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeriveChildRequest.ProtoReflect.Descriptor instead.
func (*DeriveChildRequest) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{4}
}
func (x *DeriveChildRequest) GetImportedKey() string {
if x != nil {
return x.ImportedKey
}
return ""
}
func (x *DeriveChildRequest) GetIndex() uint64 {
if x != nil {
return x.Index
}
return 0
}
func (x *DeriveChildRequest) GetHardened() bool {
if x != nil {
return x.Hardened
}
return false
}
type DeriveChildResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
PublicKey string `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
PrivateKey string `protobuf:"bytes,2,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"`
ChainCode string `protobuf:"bytes,3,opt,name=chain_code,json=chainCode,proto3" json:"chain_code,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeriveChildResponse) Reset() {
*x = DeriveChildResponse{}
mi := &file_service_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeriveChildResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeriveChildResponse) ProtoMessage() {}
func (x *DeriveChildResponse) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeriveChildResponse.ProtoReflect.Descriptor instead.
func (*DeriveChildResponse) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{5}
}
func (x *DeriveChildResponse) GetPublicKey() string {
if x != nil {
return x.PublicKey
}
return ""
}
func (x *DeriveChildResponse) GetPrivateKey() string {
if x != nil {
return x.PrivateKey
}
return ""
}
func (x *DeriveChildResponse) GetChainCode() string {
if x != nil {
return x.ChainCode
}
return ""
}
type CreateTxRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Names string `protobuf:"bytes,1,opt,name=names,proto3" json:"names,omitempty"`
Recipients string `protobuf:"bytes,2,opt,name=recipients,proto3" json:"recipients,omitempty"`
Gifts string `protobuf:"bytes,3,opt,name=gifts,proto3" json:"gifts,omitempty"`
Fee uint64 `protobuf:"varint,4,opt,name=fee,proto3" json:"fee,omitempty"`
IsMasterKey bool `protobuf:"varint,5,opt,name=is_master_key,json=isMasterKey,proto3" json:"is_master_key,omitempty"`
Key string `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"`
ChainCode string `protobuf:"bytes,7,opt,name=chain_code,json=chainCode,proto3" json:"chain_code,omitempty"`
Index uint64 `protobuf:"varint,8,opt,name=index,proto3" json:"index,omitempty"`
Hardened bool `protobuf:"varint,9,opt,name=hardened,proto3" json:"hardened,omitempty"`
TimelockIntent *TimelockIntent `protobuf:"bytes,10,opt,name=timelock_intent,json=timelockIntent,proto3" json:"timelock_intent,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateTxRequest) Reset() {
*x = CreateTxRequest{}
mi := &file_service_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateTxRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateTxRequest) ProtoMessage() {}
func (x *CreateTxRequest) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateTxRequest.ProtoReflect.Descriptor instead.
func (*CreateTxRequest) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{6}
}
func (x *CreateTxRequest) GetNames() string {
if x != nil {
return x.Names
}
return ""
}
func (x *CreateTxRequest) GetRecipients() string {
if x != nil {
return x.Recipients
}
return ""
}
func (x *CreateTxRequest) GetGifts() string {
if x != nil {
return x.Gifts
}
return ""
}
func (x *CreateTxRequest) GetFee() uint64 {
if x != nil {
return x.Fee
}
return 0
}
func (x *CreateTxRequest) GetIsMasterKey() bool {
if x != nil {
return x.IsMasterKey
}
return false
}
func (x *CreateTxRequest) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *CreateTxRequest) GetChainCode() string {
if x != nil {
return x.ChainCode
}
return ""
}
func (x *CreateTxRequest) GetIndex() uint64 {
if x != nil {
return x.Index
}
return 0
}
func (x *CreateTxRequest) GetHardened() bool {
if x != nil {
return x.Hardened
}
return false
}
func (x *CreateTxRequest) GetTimelockIntent() *TimelockIntent {
if x != nil {
return x.TimelockIntent
}
return nil
}
type CreateTxResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
RawTx *RawTx `protobuf:"bytes,1,opt,name=rawTx,proto3" json:"rawTx,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateTxResponse) Reset() {
*x = CreateTxResponse{}
mi := &file_service_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateTxResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateTxResponse) ProtoMessage() {}
func (x *CreateTxResponse) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateTxResponse.ProtoReflect.Descriptor instead.
func (*CreateTxResponse) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{7}
}
func (x *CreateTxResponse) GetRawTx() *RawTx {
if x != nil {
return x.RawTx
}
return nil
}
type SignTxRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
UnsignedTx string `protobuf:"bytes,1,opt,name=unsigned_tx,json=unsignedTx,proto3" json:"unsigned_tx,omitempty"`
Index uint64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"`
Hardened bool `protobuf:"varint,3,opt,name=hardened,proto3" json:"hardened,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SignTxRequest) Reset() {
*x = SignTxRequest{}
mi := &file_service_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SignTxRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SignTxRequest) ProtoMessage() {}
func (x *SignTxRequest) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SignTxRequest.ProtoReflect.Descriptor instead.
func (*SignTxRequest) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{8}
}
func (x *SignTxRequest) GetUnsignedTx() string {
if x != nil {
return x.UnsignedTx
}
return ""
}
func (x *SignTxRequest) GetIndex() uint64 {
if x != nil {
return x.Index
}
return 0
}
func (x *SignTxRequest) GetHardened() bool {
if x != nil {
return x.Hardened
}
return false
}
type SignTxResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
SignedTx string `protobuf:"bytes,1,opt,name=signed_tx,json=signedTx,proto3" json:"signed_tx,omitempty"`
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SignTxResponse) Reset() {
*x = SignTxResponse{}
mi := &file_service_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SignTxResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SignTxResponse) ProtoMessage() {}
func (x *SignTxResponse) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SignTxResponse.ProtoReflect.Descriptor instead.
func (*SignTxResponse) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{9}
}
func (x *SignTxResponse) GetSignedTx() string {
if x != nil {
return x.SignedTx
}
return ""
}
func (x *SignTxResponse) GetError() string {
if x != nil {
return x.Error
}
return ""
}
type ScanRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
MasterPubkey string `protobuf:"bytes,1,opt,name=master_pubkey,json=masterPubkey,proto3" json:"master_pubkey,omitempty"`
ChainCode string `protobuf:"bytes,2,opt,name=chain_code,json=chainCode,proto3" json:"chain_code,omitempty"`
SearchDepth uint64 `protobuf:"varint,3,opt,name=search_depth,json=searchDepth,proto3" json:"search_depth,omitempty"`
IncludeTimelocks bool `protobuf:"varint,4,opt,name=include_timelocks,json=includeTimelocks,proto3" json:"include_timelocks,omitempty"`
IncludeMultisig bool `protobuf:"varint,5,opt,name=include_multisig,json=includeMultisig,proto3" json:"include_multisig,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ScanRequest) Reset() {
*x = ScanRequest{}
mi := &file_service_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ScanRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ScanRequest) ProtoMessage() {}
func (x *ScanRequest) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ScanRequest.ProtoReflect.Descriptor instead.
func (*ScanRequest) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{10}
}
func (x *ScanRequest) GetMasterPubkey() string {
if x != nil {
return x.MasterPubkey
}
return ""
}
func (x *ScanRequest) GetChainCode() string {
if x != nil {
return x.ChainCode
}
return ""
}
func (x *ScanRequest) GetSearchDepth() uint64 {
if x != nil {
return x.SearchDepth
}
return 0
}
func (x *ScanRequest) GetIncludeTimelocks() bool {
if x != nil {
return x.IncludeTimelocks
}
return false
}
func (x *ScanRequest) GetIncludeMultisig() bool {
if x != nil {
return x.IncludeMultisig
}
return false
}
type ScanResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
ScanData []*ScanData `protobuf:"bytes,1,rep,name=scan_data,json=scanData,proto3" json:"scan_data,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ScanResponse) Reset() {
*x = ScanResponse{}
mi := &file_service_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ScanResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ScanResponse) ProtoMessage() {}
func (x *ScanResponse) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ScanResponse.ProtoReflect.Descriptor instead.
func (*ScanResponse) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{11}
}
func (x *ScanResponse) GetScanData() []*ScanData {
if x != nil {
return x.ScanData
}
return nil
}
var File_service_proto protoreflect.FileDescriptor
const file_service_proto_rawDesc = "" +
"\n" +
"\rservice.proto\x12\x13nockchain.public.v1\x1a\vtypes.proto\"\x0f\n" +
"\rKeygenRequest\"\xdd\x01\n" +
"\x0eKeygenResponse\x12\x1d\n" +
"\n" +
"public_key\x18\x01 \x01(\tR\tpublicKey\x12\x1f\n" +
"\vprivate_key\x18\x02 \x01(\tR\n" +
"privateKey\x12\x12\n" +
"\x04seed\x18\x03 \x01(\tR\x04seed\x12\x1d\n" +
"\n" +
"chain_code\x18\x04 \x01(\tR\tchainCode\x12,\n" +
"\x12import_private_key\x18\x05 \x01(\tR\x10importPrivateKey\x12*\n" +
"\x11import_public_key\x18\x06 \x01(\tR\x0fimportPublicKey\"g\n" +
"\x11ImportKeysRequest\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12@\n" +
"\vimport_type\x18\x02 \x01(\x0e2\x1f.nockchain.public.v1.ImportTypeR\n" +
"importType\"\xe1\x01\n" +
"\x12ImportKeysResponse\x12\x1d\n" +
"\n" +
"public_key\x18\x01 \x01(\tR\tpublicKey\x12\x1f\n" +
"\vprivate_key\x18\x02 \x01(\tR\n" +
"privateKey\x12\x12\n" +
"\x04seed\x18\x03 \x01(\tR\x04seed\x12\x1d\n" +
"\n" +
"chain_code\x18\x04 \x01(\tR\tchainCode\x12,\n" +
"\x12import_private_key\x18\x05 \x01(\tR\x10importPrivateKey\x12*\n" +
"\x11import_public_key\x18\x06 \x01(\tR\x0fimportPublicKey\"i\n" +
"\x12DeriveChildRequest\x12!\n" +
"\fimported_key\x18\x01 \x01(\tR\vimportedKey\x12\x14\n" +
"\x05index\x18\x02 \x01(\x04R\x05index\x12\x1a\n" +
"\bhardened\x18\x03 \x01(\bR\bhardened\"t\n" +
"\x13DeriveChildResponse\x12\x1d\n" +
"\n" +
"public_key\x18\x01 \x01(\tR\tpublicKey\x12\x1f\n" +
"\vprivate_key\x18\x02 \x01(\tR\n" +
"privateKey\x12\x1d\n" +
"\n" +
"chain_code\x18\x03 \x01(\tR\tchainCode\"\xc4\x02\n" +
"\x0fCreateTxRequest\x12\x14\n" +
"\x05names\x18\x01 \x01(\tR\x05names\x12\x1e\n" +
"\n" +
"recipients\x18\x02 \x01(\tR\n" +
"recipients\x12\x14\n" +
"\x05gifts\x18\x03 \x01(\tR\x05gifts\x12\x10\n" +
"\x03fee\x18\x04 \x01(\x04R\x03fee\x12\"\n" +
"\ris_master_key\x18\x05 \x01(\bR\visMasterKey\x12\x10\n" +
"\x03key\x18\x06 \x01(\tR\x03key\x12\x1d\n" +
"\n" +
"chain_code\x18\a \x01(\tR\tchainCode\x12\x14\n" +
"\x05index\x18\b \x01(\x04R\x05index\x12\x1a\n" +
"\bhardened\x18\t \x01(\bR\bhardened\x12L\n" +
"\x0ftimelock_intent\x18\n" +
" \x01(\v2#.nockchain.public.v1.TimelockIntentR\x0etimelockIntent\"D\n" +
"\x10CreateTxResponse\x120\n" +
"\x05rawTx\x18\x01 \x01(\v2\x1a.nockchain.public.v1.RawTxR\x05rawTx\"b\n" +
"\rSignTxRequest\x12\x1f\n" +
"\vunsigned_tx\x18\x01 \x01(\tR\n" +
"unsignedTx\x12\x14\n" +
"\x05index\x18\x02 \x01(\x04R\x05index\x12\x1a\n" +
"\bhardened\x18\x03 \x01(\bR\bhardened\"C\n" +
"\x0eSignTxResponse\x12\x1b\n" +
"\tsigned_tx\x18\x01 \x01(\tR\bsignedTx\x12\x14\n" +
"\x05error\x18\x02 \x01(\tR\x05error\"\xcc\x01\n" +
"\vScanRequest\x12#\n" +
"\rmaster_pubkey\x18\x01 \x01(\tR\fmasterPubkey\x12\x1d\n" +
"\n" +
"chain_code\x18\x02 \x01(\tR\tchainCode\x12!\n" +
"\fsearch_depth\x18\x03 \x01(\x04R\vsearchDepth\x12+\n" +
"\x11include_timelocks\x18\x04 \x01(\bR\x10includeTimelocks\x12)\n" +
"\x10include_multisig\x18\x05 \x01(\bR\x0fincludeMultisig\"J\n" +
"\fScanResponse\x12:\n" +
"\tscan_data\x18\x01 \x03(\v2\x1d.nockchain.public.v1.ScanDataR\bscanData2\x9c\x04\n" +
"\rWalletService\x12Q\n" +
"\x06Keygen\x12\".nockchain.public.v1.KeygenRequest\x1a#.nockchain.public.v1.KeygenResponse\x12]\n" +
"\n" +
"ImportKeys\x12&.nockchain.public.v1.ImportKeysRequest\x1a'.nockchain.public.v1.ImportKeysResponse\x12`\n" +
"\vDeriveChild\x12'.nockchain.public.v1.DeriveChildRequest\x1a(.nockchain.public.v1.DeriveChildResponse\x12W\n" +
"\bCreateTx\x12$.nockchain.public.v1.CreateTxRequest\x1a%.nockchain.public.v1.CreateTxResponse\x12Q\n" +
"\x06SignTx\x12\".nockchain.public.v1.SignTxRequest\x1a#.nockchain.public.v1.SignTxResponse\x12K\n" +
"\x04Scan\x12 .nockchain.public.v1.ScanRequest\x1a!.nockchain.public.v1.ScanResponseB\x0eZ\f./;nockchainb\x06proto3"
var (
file_service_proto_rawDescOnce sync.Once
file_service_proto_rawDescData []byte
)
func file_service_proto_rawDescGZIP() []byte {
file_service_proto_rawDescOnce.Do(func() {
file_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_service_proto_rawDesc), len(file_service_proto_rawDesc)))
})
return file_service_proto_rawDescData
}
var file_service_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_service_proto_goTypes = []any{
(*KeygenRequest)(nil), // 0: nockchain.public.v1.KeygenRequest
(*KeygenResponse)(nil), // 1: nockchain.public.v1.KeygenResponse
(*ImportKeysRequest)(nil), // 2: nockchain.public.v1.ImportKeysRequest
(*ImportKeysResponse)(nil), // 3: nockchain.public.v1.ImportKeysResponse
(*DeriveChildRequest)(nil), // 4: nockchain.public.v1.DeriveChildRequest
(*DeriveChildResponse)(nil), // 5: nockchain.public.v1.DeriveChildResponse
(*CreateTxRequest)(nil), // 6: nockchain.public.v1.CreateTxRequest
(*CreateTxResponse)(nil), // 7: nockchain.public.v1.CreateTxResponse
(*SignTxRequest)(nil), // 8: nockchain.public.v1.SignTxRequest
(*SignTxResponse)(nil), // 9: nockchain.public.v1.SignTxResponse
(*ScanRequest)(nil), // 10: nockchain.public.v1.ScanRequest
(*ScanResponse)(nil), // 11: nockchain.public.v1.ScanResponse
(ImportType)(0), // 12: nockchain.public.v1.ImportType
(*TimelockIntent)(nil), // 13: nockchain.public.v1.TimelockIntent
(*RawTx)(nil), // 14: nockchain.public.v1.RawTx
(*ScanData)(nil), // 15: nockchain.public.v1.ScanData
}
var file_service_proto_depIdxs = []int32{
12, // 0: nockchain.public.v1.ImportKeysRequest.import_type:type_name -> nockchain.public.v1.ImportType
13, // 1: nockchain.public.v1.CreateTxRequest.timelock_intent:type_name -> nockchain.public.v1.TimelockIntent
14, // 2: nockchain.public.v1.CreateTxResponse.rawTx:type_name -> nockchain.public.v1.RawTx
15, // 3: nockchain.public.v1.ScanResponse.scan_data:type_name -> nockchain.public.v1.ScanData
0, // 4: nockchain.public.v1.WalletService.Keygen:input_type -> nockchain.public.v1.KeygenRequest
2, // 5: nockchain.public.v1.WalletService.ImportKeys:input_type -> nockchain.public.v1.ImportKeysRequest
4, // 6: nockchain.public.v1.WalletService.DeriveChild:input_type -> nockchain.public.v1.DeriveChildRequest
6, // 7: nockchain.public.v1.WalletService.CreateTx:input_type -> nockchain.public.v1.CreateTxRequest
8, // 8: nockchain.public.v1.WalletService.SignTx:input_type -> nockchain.public.v1.SignTxRequest
10, // 9: nockchain.public.v1.WalletService.Scan:input_type -> nockchain.public.v1.ScanRequest
1, // 10: nockchain.public.v1.WalletService.Keygen:output_type -> nockchain.public.v1.KeygenResponse
3, // 11: nockchain.public.v1.WalletService.ImportKeys:output_type -> nockchain.public.v1.ImportKeysResponse
5, // 12: nockchain.public.v1.WalletService.DeriveChild:output_type -> nockchain.public.v1.DeriveChildResponse
7, // 13: nockchain.public.v1.WalletService.CreateTx:output_type -> nockchain.public.v1.CreateTxResponse
9, // 14: nockchain.public.v1.WalletService.SignTx:output_type -> nockchain.public.v1.SignTxResponse
11, // 15: nockchain.public.v1.WalletService.Scan:output_type -> nockchain.public.v1.ScanResponse
10, // [10:16] is the sub-list for method output_type
4, // [4:10] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_service_proto_init() }
func file_service_proto_init() {
if File_service_proto != nil {
return
}
file_types_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_service_proto_rawDesc), len(file_service_proto_rawDesc)),
NumEnums: 0,
NumMessages: 12,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_service_proto_goTypes,
DependencyIndexes: file_service_proto_depIdxs,
MessageInfos: file_service_proto_msgTypes,
}.Build()
File_service_proto = out.File
file_service_proto_goTypes = nil
file_service_proto_depIdxs = nil
}

View File

@ -0,0 +1,311 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v3.20.3
// source: service.proto
package nockchain
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
WalletService_Keygen_FullMethodName = "/nockchain.public.v1.WalletService/Keygen"
WalletService_ImportKeys_FullMethodName = "/nockchain.public.v1.WalletService/ImportKeys"
WalletService_DeriveChild_FullMethodName = "/nockchain.public.v1.WalletService/DeriveChild"
WalletService_CreateTx_FullMethodName = "/nockchain.public.v1.WalletService/CreateTx"
WalletService_SignTx_FullMethodName = "/nockchain.public.v1.WalletService/SignTx"
WalletService_Scan_FullMethodName = "/nockchain.public.v1.WalletService/Scan"
)
// WalletServiceClient is the client API for WalletService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type WalletServiceClient interface {
Keygen(ctx context.Context, in *KeygenRequest, opts ...grpc.CallOption) (*KeygenResponse, error)
ImportKeys(ctx context.Context, in *ImportKeysRequest, opts ...grpc.CallOption) (*ImportKeysResponse, error)
DeriveChild(ctx context.Context, in *DeriveChildRequest, opts ...grpc.CallOption) (*DeriveChildResponse, error)
CreateTx(ctx context.Context, in *CreateTxRequest, opts ...grpc.CallOption) (*CreateTxResponse, error)
SignTx(ctx context.Context, in *SignTxRequest, opts ...grpc.CallOption) (*SignTxResponse, error)
Scan(ctx context.Context, in *ScanRequest, opts ...grpc.CallOption) (*ScanResponse, error)
}
type walletServiceClient struct {
cc grpc.ClientConnInterface
}
func NewWalletServiceClient(cc grpc.ClientConnInterface) WalletServiceClient {
return &walletServiceClient{cc}
}
func (c *walletServiceClient) Keygen(ctx context.Context, in *KeygenRequest, opts ...grpc.CallOption) (*KeygenResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(KeygenResponse)
err := c.cc.Invoke(ctx, WalletService_Keygen_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *walletServiceClient) ImportKeys(ctx context.Context, in *ImportKeysRequest, opts ...grpc.CallOption) (*ImportKeysResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ImportKeysResponse)
err := c.cc.Invoke(ctx, WalletService_ImportKeys_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *walletServiceClient) DeriveChild(ctx context.Context, in *DeriveChildRequest, opts ...grpc.CallOption) (*DeriveChildResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeriveChildResponse)
err := c.cc.Invoke(ctx, WalletService_DeriveChild_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *walletServiceClient) CreateTx(ctx context.Context, in *CreateTxRequest, opts ...grpc.CallOption) (*CreateTxResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CreateTxResponse)
err := c.cc.Invoke(ctx, WalletService_CreateTx_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *walletServiceClient) SignTx(ctx context.Context, in *SignTxRequest, opts ...grpc.CallOption) (*SignTxResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SignTxResponse)
err := c.cc.Invoke(ctx, WalletService_SignTx_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *walletServiceClient) Scan(ctx context.Context, in *ScanRequest, opts ...grpc.CallOption) (*ScanResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ScanResponse)
err := c.cc.Invoke(ctx, WalletService_Scan_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// WalletServiceServer is the server API for WalletService service.
// All implementations must embed UnimplementedWalletServiceServer
// for forward compatibility.
type WalletServiceServer interface {
Keygen(context.Context, *KeygenRequest) (*KeygenResponse, error)
ImportKeys(context.Context, *ImportKeysRequest) (*ImportKeysResponse, error)
DeriveChild(context.Context, *DeriveChildRequest) (*DeriveChildResponse, error)
CreateTx(context.Context, *CreateTxRequest) (*CreateTxResponse, error)
SignTx(context.Context, *SignTxRequest) (*SignTxResponse, error)
Scan(context.Context, *ScanRequest) (*ScanResponse, error)
mustEmbedUnimplementedWalletServiceServer()
}
// UnimplementedWalletServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedWalletServiceServer struct{}
func (UnimplementedWalletServiceServer) Keygen(context.Context, *KeygenRequest) (*KeygenResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Keygen not implemented")
}
func (UnimplementedWalletServiceServer) ImportKeys(context.Context, *ImportKeysRequest) (*ImportKeysResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ImportKeys not implemented")
}
func (UnimplementedWalletServiceServer) DeriveChild(context.Context, *DeriveChildRequest) (*DeriveChildResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeriveChild not implemented")
}
func (UnimplementedWalletServiceServer) CreateTx(context.Context, *CreateTxRequest) (*CreateTxResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateTx not implemented")
}
func (UnimplementedWalletServiceServer) SignTx(context.Context, *SignTxRequest) (*SignTxResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SignTx not implemented")
}
func (UnimplementedWalletServiceServer) Scan(context.Context, *ScanRequest) (*ScanResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Scan not implemented")
}
func (UnimplementedWalletServiceServer) mustEmbedUnimplementedWalletServiceServer() {}
func (UnimplementedWalletServiceServer) testEmbeddedByValue() {}
// UnsafeWalletServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to WalletServiceServer will
// result in compilation errors.
type UnsafeWalletServiceServer interface {
mustEmbedUnimplementedWalletServiceServer()
}
func RegisterWalletServiceServer(s grpc.ServiceRegistrar, srv WalletServiceServer) {
// If the following call pancis, it indicates UnimplementedWalletServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&WalletService_ServiceDesc, srv)
}
func _WalletService_Keygen_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(KeygenRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletServiceServer).Keygen(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WalletService_Keygen_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletServiceServer).Keygen(ctx, req.(*KeygenRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WalletService_ImportKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ImportKeysRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletServiceServer).ImportKeys(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WalletService_ImportKeys_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletServiceServer).ImportKeys(ctx, req.(*ImportKeysRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WalletService_DeriveChild_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeriveChildRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletServiceServer).DeriveChild(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WalletService_DeriveChild_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletServiceServer).DeriveChild(ctx, req.(*DeriveChildRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WalletService_CreateTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateTxRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletServiceServer).CreateTx(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WalletService_CreateTx_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletServiceServer).CreateTx(ctx, req.(*CreateTxRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WalletService_SignTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SignTxRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletServiceServer).SignTx(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WalletService_SignTx_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletServiceServer).SignTx(ctx, req.(*SignTxRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WalletService_Scan_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ScanRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletServiceServer).Scan(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: WalletService_Scan_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletServiceServer).Scan(ctx, req.(*ScanRequest))
}
return interceptor(ctx, in, info, handler)
}
// WalletService_ServiceDesc is the grpc.ServiceDesc for WalletService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var WalletService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "nockchain.public.v1.WalletService",
HandlerType: (*WalletServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Keygen",
Handler: _WalletService_Keygen_Handler,
},
{
MethodName: "ImportKeys",
Handler: _WalletService_ImportKeys_Handler,
},
{
MethodName: "DeriveChild",
Handler: _WalletService_DeriveChild_Handler,
},
{
MethodName: "CreateTx",
Handler: _WalletService_CreateTx_Handler,
},
{
MethodName: "SignTx",
Handler: _WalletService_SignTx_Handler,
},
{
MethodName: "Scan",
Handler: _WalletService_Scan_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "service.proto",
}

1070
nockchain/types.pb.go Normal file

File diff suppressed because it is too large Load Diff

134
proto/blockchain.proto Normal file
View File

@ -0,0 +1,134 @@
// nockchain/common/v1/blockchain.proto
syntax = "proto3";
package nockchain.public.v1;
import "primitives.proto";
import "pagination.proto";
option go_package = "./;nockchain";
message WalletBalanceData {
// Page of full UTXO entries for the requested wallet. Entries are ordered
// by (Name.first, Name.last) to support consistent pagination.
repeated BalanceEntry notes = 1; // note name -> amount
// Snapshot metadata where this page was computed. Clients should include
// the returned page token to continue paging against the same snapshot.
BlockHeight height = 2; // block height where balance was computed
optional Hash block_id = 3; // block where balance was computed
// Pagination cursor for fetching the next page in a paginated view.
// When empty, there are no further results for this snapshot.
PageResponse page = 4;
}
message BalanceEntry {
Name name = 1;
Note note = 2;
}
// the string key is the name of the input
// message RawTransaction { map<Name, Input> inputs = 1; }
message RawTransaction {
repeated NamedInput named_inputs = 1;
TimeLockRangeAbsolute timelock_range = 2;
Nicks total_fees = 3;
Hash id = 4;
}
message NamedInput {
Name name = 1;
Input input = 2;
}
message Input {
Note note = 1;
Spend spend = 2;
}
message Spend {
Signature signature = 1;
repeated Seed seeds = 2;
Nicks miner_fee_nicks = 3;
}
message Seed {
optional OutputSource output_source = 1;
Lock recipient = 2;
optional TimeLockIntent timelock_intent = 3;
Nicks gift = 4;
Hash parent_hash = 5;
}
message OutputSource { optional Source source = 1; }
message Source {
Hash hash = 1;
bool coinbase = 2;
}
message TimeLockIntent {
oneof value {
TimeLockRangeAbsolute absolute = 1;
TimeLockRangeRelative relative = 2;
TimeLockRangeAbsoluteAndRelative absolute_and_relative = 3;
}
}
message TimeLockRangeAbsoluteAndRelative {
optional TimeLockRangeAbsolute absolute = 1;
optional TimeLockRangeRelative relative = 2;
}
// min and max are absolute origin page numbers
message TimeLockRangeAbsolute {
optional BlockHeight min = 1;
optional BlockHeight max = 2;
}
// min and max are relative to the note's creation page
message TimeLockRangeRelative {
optional BlockHeightDelta min = 1;
optional BlockHeightDelta max = 2;
}
// ===================================================================
// Wallet Domain Types: UTXO (nnote), Lock, and Signature (multisig)
// ===================================================================
message Lock {
uint32 keys_required = 1; // threshold of keys required to spend the note
// DEPRECATED: repeated string schnorr_pubkeys_b58 = 2;
repeated SchnorrPubkey schnorr_pubkeys =
2; // schnorr pubkeys (curve: cheetah)
}
message Name {
// First is the hash of whether the note has a timelock and the lock
Hash first = 1;
// Last is the hash of the actual timelock and the source
Hash last = 2;
}
message Note {
BlockHeight origin_page = 1; // page-number when added to balance
optional TimeLockIntent timelock = 2; // enforced timelock
Name name = 3; // nname (human/name label)
Lock lock = 4; // spending condition
Source source = 5; // provenance commitment
Nicks assets = 6; // coin amount (nicks)
NoteVersion version = 7; // note version (currently 0)
}
message Signature { repeated SignatureEntry entries = 1; }
message SignatureEntry {
SchnorrPubkey schnorr_pubkey =
1; // serialized pubkey corresponding to the signer
SchnorrSignature signature = 2;
}
message SchnorrSignature {
EightBelt chal = 1;
EightBelt sig = 2;
}

91
proto/nockchain.proto Normal file
View File

@ -0,0 +1,91 @@
// nockchain/public/v1/nockchain.proto
syntax = "proto3";
package nockchain.public.v1;
import "blockchain.proto";
import "primitives.proto";
import "pagination.proto";
option go_package = "./;nockchain";
service NockchainService {
rpc WalletGetBalance(WalletGetBalanceRequest)
returns (WalletGetBalanceResponse);
rpc WalletSendTransaction(WalletSendTransactionRequest)
returns (WalletSendTransactionResponse);
rpc TransactionAccepted(TransactionAcceptedRequest)
returns (TransactionAcceptedResponse);
//rpc TransactionConfirmation(TransactionConfirmationRequest)
// returns (TransactionConfirmationResponse);
}
message WalletGetBalanceRequest {
// pubkey cheetah point; specific address, or current wallet
string address = 1;
// Pagination parameters. The server enforces limits and may return fewer
// entries than requested to respect message size and policy. For consistent
// paging across a stable snapshot, pass along the returned page_token from
// the previous response without modification.
PageRequest page = 2;
}
message WalletGetBalanceResponse {
oneof result {
// Paginated wallet balance data with full entries and snapshot metadata.
// Continue paging using `balance.page.next_page_token` until empty. Clients
// should treat the page token as opaque; it may encode snapshot identity
// and the last returned key.
WalletBalanceData balance = 1;
ErrorStatus error = 2;
}
}
message WalletSendTransactionRequest {
Hash tx_id = 1; // base58 encoded transaction ID for tracking
RawTransaction raw_tx = 2;
}
message WalletSendTransactionResponse {
oneof result {
// true is request was acknowledge by node,
// this does not mean that the transaction was
// confirmed and/or accepted.
Acknowledged ack = 1;
ErrorStatus error = 2;
}
}
message TransactionAcceptedRequest {
Base58Hash tx_id = 1; // base58 encoded transaction ID for tracking
}
message TransactionAcceptedResponse {
// true if transaction was accepted by node. this not does mean that the
// transaction was confirmed. Just that it was validated by the node and
// added to its raw-tx set.
oneof result {
bool accepted = 1;
ErrorStatus error = 2;
}
}
//message TransactionConfirmationRequest {
// // base58 encoded transaction ID
// Base58Hash tx_id = 1;
//}
//
//// TODO: Handle re-orgs / orphaned transactions
//message TransactionConfirmationResponse {
// oneof result {
// // Number of blocks between the transaction's origin page and the current
// // chain tip. 0 = mempool, no block contains the transaction yet.
// // 1 = first block containing the transaction, current heaviest block.
// // > 1 = number of blocks between the transaction's origin page and the
// // current chain tip.
// BlockHeightDelta confirmations = 1;
// // Transaction not found in mempool or chain
// bool transaction_not_found = 2;
// ErrorStatus error = 3;
// }
//}

39
proto/pagination.proto Normal file
View File

@ -0,0 +1,39 @@
// nockchain/common/v1/pagination.proto
syntax = "proto3";
package nockchain.public.v1;
option go_package = "./;nockchain";
// Generic pagination parameters for list-style RPCs.
// These types are intended to be reused across public APIs.
//
// Contract:
// - The server may return fewer items than requested (client_page_items_limit is a hint).
// - page_token is an opaque cursor produced by the server; clients must treat
// it as a black box. Servers may encode snapshot identity and last-key.
// - For consistent pagination, clients should include the returned page_token
// in the next request without modification.
// - Servers may enforce a maximum client_page_items_limit and/or byte budget regardless of
// client hints.
message PageRequest {
// Maximum number of items to return. The server may return fewer items
// than requested. Clients should not rely on receiving exactly this count.
uint32 client_page_items_limit = 1;
// Opaque cursor returned by a previous call. When set, the server resumes
// the listing from the position described by the token.
// An empty token indicates the first page.
string page_token = 2;
// Optional soft limit on the uncompressed bytes to return in a single page.
// The server may ignore or cap this value according to policy. This refers
// to the gRPC payload size after protobuf encoding and decompression.
uint64 max_bytes = 3;
}
message PageResponse {
// Opaque cursor for fetching the next page. Empty when there are no more
// results.
string next_page_token = 1;
}

108
proto/primitives.proto Normal file
View File

@ -0,0 +1,108 @@
// nockchain/common/v1/primitives.proto
syntax = "proto3";
package nockchain.public.v1;
option go_package = "./;nockchain";
message ErrorStatus {
ErrorCode code = 1;
string message = 2;
optional string details = 3; // additional error context
}
message Acknowledged {}
enum ErrorCode {
ERROR_CODE_UNSPECIFIED = 0;
ERROR_CODE_INVALID_REQUEST = 1;
ERROR_CODE_PEEK_FAILED = 2;
ERROR_CODE_PEEK_RETURNED_NO_DATA = 3;
ERROR_CODE_POKE_FAILED = 4;
ERROR_CODE_NACKAPP_ERROR = 5;
ERROR_CODE_TIMEOUT = 6;
ERROR_CODE_INTERNAL_ERROR = 7;
ERROR_CODE_NOT_FOUND = 8;
ERROR_CODE_PERMISSION_DENIED = 9;
ERROR_CODE_INVALID_WIRE = 10;
ERROR_CODE_KERNEL_ERROR = 11;
}
// ===================================================================
// Wire types for NockApp pokes
// ===================================================================
message Wire {
string source = 1; // e.g., "http", "file", "wallet", "grpc"
uint64 version = 2; // wire format version
repeated WireTag tags = 3; // operation-specific tags
}
message WireTag {
oneof value {
string text = 1;
uint64 number = 2;
}
}
// Note: prefer using raw numeric fields in messages
// instead of these wrappers to simplify conversions.
// These remain defined for potential future use.
message NoteVersion { uint32 value = 1; }
message BlockHeight { uint64 value = 1; }
message BlockHeightDelta { uint64 value = 1; }
message Nicks { uint64 value = 1; }
// pub chal: [Belt; 8],
// pub sig: [Belt; 8],
message EightBelt {
Belt belt_1 = 1;
Belt belt_2 = 2;
Belt belt_3 = 3;
Belt belt_4 = 4;
Belt belt_5 = 5;
Belt belt_6 = 6;
Belt belt_7 = 7;
Belt belt_8 = 8;
}
// pub struct Hash(pub [Belt; 5]);
// Use fixed fields to avoid variable-length vectors.
message Hash {
Belt belt_1 = 1;
Belt belt_2 = 2;
Belt belt_3 = 3;
Belt belt_4 = 4;
Belt belt_5 = 5;
}
message Base58Hash {
string hash = 1;
}
// pub struct SchnorrPubkey(pub CheetahPoint);
message SchnorrPubkey { CheetahPoint value = 1; }
// pub struct CheetahPoint {
// pub x: F6lt,
// pub y: F6lt,
// pub inf: bool,
// }
message CheetahPoint {
SixBelt x = 1;
SixBelt y = 2;
bool inf = 3;
}
// pub struct F6lt(pub [Belt; 6]);
message SixBelt {
Belt belt_1 = 1;
Belt belt_2 = 2;
Belt belt_3 = 3;
Belt belt_4 = 4;
Belt belt_5 = 5;
Belt belt_6 = 6;
}
// pub struct Belt(pub u64);
message Belt { uint64 value = 1; }

91
proto/service.proto Normal file
View File

@ -0,0 +1,91 @@
syntax = "proto3";
package nockchain.public.v1;
option go_package = "./;nockchain";
import "types.proto";
service WalletService {
rpc Keygen(KeygenRequest) returns (KeygenResponse);
rpc ImportKeys(ImportKeysRequest) returns (ImportKeysResponse);
rpc DeriveChild(DeriveChildRequest) returns (DeriveChildResponse);
rpc CreateTx(CreateTxRequest) returns (CreateTxResponse);
rpc SignTx(SignTxRequest) returns (SignTxResponse);
rpc Scan(ScanRequest) returns (ScanResponse);
}
message KeygenRequest {}
message KeygenResponse {
string public_key = 1;
string private_key = 2;
string seed = 3;
string chain_code = 4;
string import_private_key = 5;
string import_public_key = 6;
}
message ImportKeysRequest {
string key = 1;
ImportType import_type = 2;
}
message ImportKeysResponse {
string public_key = 1;
string private_key = 2;
string seed = 3;
string chain_code = 4;
string import_private_key = 5;
string import_public_key = 6;
}
message DeriveChildRequest {
string imported_key = 1;
uint64 index = 2;
bool hardened = 3;
}
message DeriveChildResponse {
string public_key = 1;
string private_key = 2;
string chain_code = 3;
}
message CreateTxRequest {
string names = 1;
string recipients = 2;
string gifts = 3;
uint64 fee = 4;
bool is_master_key = 5;
string key = 6;
string chain_code = 7;
uint64 index = 8;
bool hardened = 9;
TimelockIntent timelock_intent = 10;
}
message CreateTxResponse {
RawTx rawTx = 1;
}
message SignTxRequest {
string unsigned_tx = 1;
uint64 index = 2;
bool hardened = 3;
}
message SignTxResponse {
string signed_tx = 1;
string error = 2;
}
message ScanRequest {
string master_pubkey = 1;
string chain_code = 2;
uint64 search_depth = 3;
bool include_timelocks = 4;
bool include_multisig = 5;
}
message ScanResponse {
repeated ScanData scan_data = 1;
}

92
proto/types.proto Normal file
View File

@ -0,0 +1,92 @@
syntax = "proto3";
package nockchain.public.v1;
option go_package = "./;nockchain";
import "blockchain.proto";
message ScanData {
string pubkey = 1;
WalletBalanceData data = 2;
}
enum ImportType {
UNDEFINED = 0;
EXTENDED_KEY = 1;
SEEDPHRASE = 2;
MASTER_PRIVKEY = 3;
WATCH_ONLY = 4;
}
message TimelockIntent {
optional TimelockRange absolute = 1;
optional TimelockRange relative = 2;
}
message TimelockRange {
optional Timelock min = 1;
optional Timelock max = 2;
}
message Timelock {
uint64 value = 1;
}
message RawTx {
string tx_id = 1;
repeated NockchainInput inputs = 2;
TimelockRange timelock_range = 3;
uint64 total_fees = 4;
}
message NockchainSpend {
repeated NockchainSignature signatures = 1;
repeated NockchainSeed seeds = 2;
uint64 fee = 3;
}
message NockchainNote {
Version version = 1;
uint64 block_height = 2;
optional TimelockIntent timelock = 3;
NockchainName name = 4;
NockchainLock lock = 5;
NockchainSource source = 6;
uint64 asset =7;
}
message NockchainName {
string first = 1;
string last = 2;
}
message NockchainInput {
NockchainName name = 1;
NockchainNote note = 2;
NockchainSpend spend = 3;
}
message NockchainSignature {
string pubkey = 1;
repeated uint64 chal = 2;
repeated uint64 sig = 3;
}
message NockchainSeed {
optional NockchainSource output_source = 1;
NockchainLock recipient = 2;
optional TimelockIntent timelock_intent = 3;
uint64 gift = 4;
string parent_hash = 5;
}
message NockchainLock {
uint64 keys_required = 1;
repeated string pubkeys = 2;
}
message NockchainSource {
string source = 1;
bool is_coinbase = 2;
}
enum Version {
V0 = 0;
V1 = 1;
V2 = 2;
}

115
wallet/nockchain_service.go Normal file
View File

@ -0,0 +1,115 @@
package wallet
import (
context "context"
"fmt"
"github.com/phamminh0811/private-grpc/nockchain"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
type NockchainClient struct {
conn *grpc.ClientConn
client nockchain.NockchainServiceClient
}
// NewNockchainClient creates a new gRPC client connection
func NewNockchainClient(address string) (*NockchainClient, error) {
creds := credentials.NewClientTLSFromCert(nil, "")
conn, err := grpc.NewClient(
address,
grpc.WithTransportCredentials(creds),
)
if err != nil {
return nil, fmt.Errorf("failed to connect: %w", err)
}
client := nockchain.NewNockchainServiceClient(conn)
return &NockchainClient{
conn: conn,
client: client,
}, nil
}
func (nc *NockchainClient) Close() error {
return nc.conn.Close()
}
func (nc *NockchainClient) WalletGetBalance(address string) (*nockchain.WalletBalanceData, error) {
pageToken := ""
allNotes := []*nockchain.BalanceEntry{}
var height *nockchain.BlockHeight
var blockId *nockchain.Hash
for {
req := nockchain.WalletGetBalanceRequest{
Address: address,
Page: &nockchain.PageRequest{
ClientPageItemsLimit: 0,
PageToken: pageToken,
MaxBytes: 0,
},
}
resp, err := nc.client.WalletGetBalance(context.Background(), &req)
if err != nil {
return nil, err
}
balance := nockchain.WalletBalanceData{}
switch resp.Result.(type) {
case *nockchain.WalletGetBalanceResponse_Balance:
balance = *resp.GetBalance()
case *nockchain.WalletGetBalanceResponse_Error:
return nil, fmt.Errorf("error: %s", resp.GetError().Message)
default:
return nil, fmt.Errorf("invalid result type")
}
if height == nil {
height = balance.Height
blockId = balance.BlockId
}
if balance.Height != height || balance.BlockId != blockId {
return nil, fmt.Errorf("snapshot changed during pagination; retry")
}
allNotes = append(allNotes, balance.Notes...)
if balance.Page.NextPageToken == "" {
break
} else {
pageToken = balance.Page.NextPageToken
}
}
return &nockchain.WalletBalanceData{
Notes: allNotes,
Height: height,
BlockId: blockId,
Page: &nockchain.PageResponse{
NextPageToken: "",
},
}, nil
}
func (nc *NockchainClient) TxAccepted(txId string) (*nockchain.TransactionAcceptedResponse, error) {
req := nockchain.TransactionAcceptedRequest{
TxId: &nockchain.Base58Hash{
Hash: txId,
},
}
resp, err := nc.client.TransactionAccepted(context.Background(), &req)
if err != nil {
return nil, err
}
switch resp.Result.(type) {
case *nockchain.TransactionAcceptedResponse_Accepted:
return resp, nil
case *nockchain.TransactionAcceptedResponse_Error:
return nil, fmt.Errorf("error: %s", resp.GetError().Message)
default:
return nil, fmt.Errorf("invalid result type")
}
}

294
wallet/nockhash.go Normal file
View File

@ -0,0 +1,294 @@
package wallet
import (
"fmt"
"math/big"
"github.com/btcsuite/btcd/btcutil/base58"
"github.com/phamminh0811/private-grpc/crypto"
"github.com/phamminh0811/private-grpc/nockchain"
)
var LastName = [5]uint64{9541855607561054508, 12383849149342406623, 11220017934615522559, 678840671137489369, 8985908938884028381}
func HashPubkey(pkPoint crypto.CheetahPoint) [5]uint64 {
belts := []crypto.Belt{{Value: 13}}
belts = append(belts, pkPoint.X[:]...)
belts = append(belts, pkPoint.Y[:]...)
belts = append(belts, crypto.BELT_ONE)
for _, i := range crypto.MagicDyckForPoint {
belts = append(belts, crypto.Belt{Value: i})
}
return crypto.Tip5HashBelts(belts)
}
func HashSignature(signature *nockchain.NockchainSignature) ([5]uint64, error) {
belts := []crypto.Belt{{Value: 16}}
for _, i := range signature.Chal {
belts = append(belts, crypto.Belt{Value: i})
}
for _, i := range signature.Sig {
belts = append(belts, crypto.Belt{Value: i})
}
for _, i := range crypto.MagicDyckForT8 {
belts = append(belts, crypto.Belt{Value: i})
}
sigHash := crypto.Tip5HashBelts(belts)
pkPoint, err := crypto.CheetaPointFromBytes(base58.Decode(signature.Pubkey))
if err != nil {
return [5]uint64{}, err
}
pkHash := HashPubkey(pkPoint)
sigHash = crypto.Tip5RehashTenCell(pkHash, sigHash)
sigHash = crypto.Tip5RehashTenCell(sigHash, crypto.Tip5ZeroZero)
return crypto.Tip5RehashTenCell(crypto.Tip5Zero, sigHash), nil
}
func HashOwner(pkPoint crypto.CheetahPoint) [5]uint64 {
pkHashedBelts := HashPubkey(pkPoint)
pkHashedZeroZero := crypto.Tip5RehashTenCell(pkHashedBelts, crypto.Tip5ZeroZero)
return crypto.Tip5RehashTenCell(crypto.Tip5One, pkHashedZeroZero)
}
func NockName(ownerHash [5]uint64) ([5]uint64, [5]uint64) {
firstName := first(ownerHash)
return firstName, LastName
}
func HashName(name *nockchain.NockchainName) [5]uint64 {
firstNameHash := crypto.Base58ToTip5Hash(name.First)
lastNameHash := crypto.Base58ToTip5Hash(name.Last)
return crypto.Tip5RehashTenCell(firstNameHash, crypto.Tip5RehashTenCell(lastNameHash, crypto.Tip5Zero))
}
func HashNote(note *nockchain.NockchainNote) ([5]uint64, error) {
versionHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: uint64(note.Version)}})
blockHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: note.BlockHeight}})
timelockHash := HashTimelockIntent(note.Timelock)
hashBlockTimeLock := crypto.Tip5RehashTenCell(blockHash, timelockHash)
p := crypto.Tip5RehashTenCell(versionHash, hashBlockTimeLock)
nameHash := HashName(note.Name)
lockHash, err := HashLock(note.Lock)
if err != nil {
return [5]uint64{}, err
}
sourceHash := HashSource(note.Source)
assetHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: uint64(note.Asset)}})
hashSourceAsset := crypto.Tip5RehashTenCell(sourceHash, assetHash)
q := crypto.Tip5RehashTenCell(nameHash, crypto.Tip5RehashTenCell(lockHash, hashSourceAsset))
return crypto.Tip5RehashTenCell(p, q), nil
}
func HashTimelockIntent(timelock *nockchain.TimelockIntent) [5]uint64 {
if timelock == nil {
return crypto.Tip5Zero
}
if timelock.Absolute == nil && timelock.Relative == nil {
return crypto.Tip5ZeroZero
}
absoluteHash := HashTimelockRange(timelock.Absolute)
relativeHash := HashTimelockRange(timelock.Relative)
return crypto.Tip5RehashTenCell(absoluteHash, relativeHash)
}
func HashTimelockRange(timelockRange *nockchain.TimelockRange) [5]uint64 {
hash := crypto.Tip5Zero
if timelockRange != nil {
minHash := crypto.Tip5Zero
if timelockRange.Min != nil {
minHash = crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: timelockRange.Min.Value}})
}
maxHash := crypto.Tip5Zero
if timelockRange.Max != nil {
maxHash = crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: timelockRange.Max.Value}})
}
hash = crypto.Tip5RehashTenCell(minHash, maxHash)
}
return hash
}
func HashLock(lock *nockchain.NockchainLock) ([5]uint64, error) {
keysRequiredHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: lock.KeysRequired}})
finalPk := base58.Decode(lock.Pubkeys[lock.KeysRequired-1])
finalPkPoint, err := crypto.CheetaPointFromBytes(finalPk)
if err != nil {
return [5]uint64{}, err
}
finalPkHash := HashPubkey(finalPkPoint)
finalHash := crypto.Tip5RehashTenCell(finalPkHash, crypto.Tip5ZeroZero)
if lock.KeysRequired != 1 {
for i := uint64(1); i < lock.KeysRequired; i++ {
pk := base58.Decode(lock.Pubkeys[lock.KeysRequired-1-i])
pkPoint, err := crypto.CheetaPointFromBytes(pk)
if err != nil {
return [5]uint64{}, err
}
pkHash := HashPubkey(pkPoint)
finalHash = crypto.Tip5RehashTenCell(pkHash, finalHash)
}
}
return crypto.Tip5RehashTenCell(keysRequiredHash, finalHash), nil
}
func HashSource(source *nockchain.NockchainSource) [5]uint64 {
if source == nil {
return crypto.Tip5Zero
}
sourceHash := crypto.Base58ToTip5Hash(source.Source)
if source.IsCoinbase {
return crypto.Tip5RehashTenCell(sourceHash, crypto.Tip5One)
} else {
return crypto.Tip5RehashTenCell(sourceHash, crypto.Tip5Zero)
}
}
func HashSeedWithoutSource(seed *nockchain.NockchainSeed) ([5]uint64, error) {
lockHash, err := HashLock(seed.Recipient)
if err != nil {
return [5]uint64{}, nil
}
timelockIntentHash := HashTimelockIntent(seed.TimelockIntent)
assetHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: seed.Gift}})
parentHash := crypto.Base58ToTip5Hash(seed.ParentHash)
assetHashparentHash := crypto.Tip5RehashTenCell(assetHash, parentHash)
timelockHashAssetParentHash := crypto.Tip5RehashTenCell(timelockIntentHash, assetHashparentHash)
seedHash := crypto.Tip5RehashTenCell(lockHash, timelockHashAssetParentHash)
return seedHash, nil
}
func HashSeed(seed *nockchain.NockchainSeed) ([5]uint64, error) {
seedHash, err := HashSeedWithoutSource(seed)
if err != nil {
return [5]uint64{}, nil
}
sourceHash := HashSource(seed.OutputSource)
return crypto.Tip5RehashTenCell(sourceHash, seedHash), nil
}
func HashNonce(pkPoint crypto.CheetahPoint, message [5]uint64) ([]crypto.Belt, [5]uint64) {
belts := []crypto.Belt{}
for _, belt := range pkPoint.X {
belts = append(belts, belt)
}
for _, belt := range pkPoint.Y {
belts = append(belts, belt)
}
for _, belt := range message {
belts = append(belts, crypto.Belt{Value: belt})
}
resBelts := make([]crypto.Belt, len(belts))
copy(resBelts, belts)
return resBelts, crypto.Tip5HashBelts(belts)
}
func HashSpend(spend *nockchain.NockchainSpend) ([5]uint64, error) {
// TODO: handle multiple sig
sigHash, err := HashSignature(spend.Signatures[0])
if err != nil {
return [5]uint64{}, err
}
seedsCount := len(spend.Seeds)
finalSeedHash, err := HashSeedWithoutSource(spend.Seeds[seedsCount-1])
if err != nil {
return [5]uint64{}, err
}
finalSeedHash = crypto.Tip5RehashTenCell(finalSeedHash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(finalSeedHash, crypto.Tip5Zero)
if seedsCount != 1 {
for i := 1; i < seedsCount; i++ {
seedHash, err := HashSeedWithoutSource(spend.Seeds[seedsCount-1-i])
if err != nil {
return [5]uint64{}, err
}
fmt.Println("")
finalSeedHash = crypto.Tip5RehashTenCell(seedHash, finalSeedHash)
}
}
feeHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: spend.Fee}})
seedHashFee := crypto.Tip5RehashTenCell(finalSeedHash, feeHash)
return crypto.Tip5RehashTenCell(sigHash, seedHashFee), nil
}
func HashInput(input *nockchain.NockchainInput) ([5]uint64, error) {
nameHash := HashName(input.Name)
noteHash, err := HashNote(input.Note)
if err != nil {
return [5]uint64{}, err
}
spendHash, err := HashSpend(input.Spend)
if err != nil {
return [5]uint64{}, err
}
hashNoteSpend := crypto.Tip5RehashTenCell(noteHash, spendHash)
inputHash := crypto.Tip5RehashTenCell(nameHash, hashNoteSpend)
return crypto.Tip5RehashTenCell(inputHash, crypto.Tip5ZeroZero), nil
}
func ComputeTxId(inputs []*nockchain.NockchainInput, timelockRange *nockchain.TimelockRange, totalFees uint64) ([5]uint64, error) {
// TODO: do it with multiple intputs
input := inputs[0]
inputHash, err := HashInput(input)
if err != nil {
return [5]uint64{}, err
}
timelockHash := HashTimelockRange(timelockRange)
totalFeesHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: totalFees}})
q := crypto.Tip5RehashTenCell(timelockHash, totalFeesHash)
return crypto.Tip5RehashTenCell(inputHash, q), nil
}
func ComputeSig(m crypto.MasterKey, msg [5]uint64) ([8]uint64, [8]uint64, error) {
pkPoint, err := crypto.CheetaPointFromBytes(m.PublicKey)
if err != nil {
return [8]uint64{}, [8]uint64{}, err
}
belts, nonce := HashNonce(pkPoint, msg)
nonceBigInt := crypto.TruncGOrder(nonce)
scalar := crypto.CheetahScaleBig(crypto.A_GEN, *nonceBigInt)
scalarBelts := []crypto.Belt{}
scalarBelts = append(scalarBelts, scalar.X[:]...)
scalarBelts = append(scalarBelts, scalar.Y[:]...)
belts = append(scalarBelts, belts...)
chal := crypto.Tip5HashBelts(belts)
chalBigInt := crypto.TruncGOrder(chal)
skBigInt := new(big.Int).SetBytes(m.PrivateKey)
sig := new(big.Int).Mul(chalBigInt, skBigInt)
sig.Add(sig, nonceBigInt)
sig.Mod(sig, crypto.G_ORDER)
chalT8 := crypto.BigIntToT8(*chalBigInt)
sigT8 := crypto.BigIntToT8(*sig)
return chalT8, sigT8, nil
}
func first(ownerHash [5]uint64) [5]uint64 {
ownerHashZero := crypto.Tip5RehashTenCell(ownerHash, crypto.Tip5Zero)
ownerHashZeroOne := crypto.Tip5RehashTenCell(crypto.Tip5One, ownerHashZero)
return crypto.Tip5RehashTenCell(crypto.Tip5Zero, ownerHashZeroOne)
}

425
wallet/service.go Normal file
View File

@ -0,0 +1,425 @@
package wallet
import (
context "context"
"crypto/rand"
"crypto/sha256"
"fmt"
"slices"
"strconv"
"strings"
"github.com/btcsuite/btcd/btcutil/base58"
"github.com/cosmos/go-bip39"
"github.com/phamminh0811/private-grpc/crypto"
"github.com/phamminh0811/private-grpc/nockchain"
)
type GprcHandler struct {
nockchain.UnimplementedWalletServiceServer
client NockchainClient
}
func NewGprcHandler(client NockchainClient) GprcHandler {
return GprcHandler{
client: client,
}
}
func (h *GprcHandler) Keygen(ctx context.Context, req *nockchain.KeygenRequest) (*nockchain.KeygenResponse, error) {
var entropy [32]byte
_, err := rand.Read(entropy[:]) // Fill the slice with random bytes
if err != nil {
return nil, err
}
var salt [16]byte
_, err = rand.Read(salt[:])
if err != nil {
return nil, err
}
argonBytes := crypto.DeriveKey(0, entropy[:], salt[:], nil, nil, 6, 786432, 4, 32)
slices.Reverse(argonBytes)
mnemonic, err := bip39.NewMnemonic(argonBytes)
if err != nil {
return nil, fmt.Errorf("failed to generate mnemonic: %v", err)
}
masterKey, err := crypto.MasterKeyFromSeed(mnemonic)
if err != nil {
return nil, err
}
privBytes := append([]byte{0x00}, masterKey.PrivateKey...)
return &nockchain.KeygenResponse{
Seed: mnemonic,
PrivateKey: base58.Encode(masterKey.PrivateKey),
PublicKey: base58.Encode(masterKey.PublicKey),
ChainCode: base58.Encode(masterKey.ChainCode),
ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart)),
ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart)),
}, nil
}
func (h *GprcHandler) ImportKeys(ctx context.Context, req *nockchain.ImportKeysRequest) (*nockchain.ImportKeysResponse, error) {
switch req.ImportType {
case nockchain.ImportType_UNDEFINED:
return nil, fmt.Errorf("invalid import type")
case nockchain.ImportType_EXTENDED_KEY:
// metadata layout: [version][depth][parent-fp][index][chain-code][key-data][checksum]
data := base58.Decode(req.Key)
switch {
case strings.HasPrefix(req.Key, "zprv"):
if len(data) != 82 {
return nil, fmt.Errorf("invalid extended private key length: %d (expected 82)", len(data))
}
if data[45] != 0x00 {
return nil, fmt.Errorf("invalid private key prefix at byte 45: 0x%02x (expected 0x00)", data[45])
}
hash := sha256.Sum256(data[:78])
hash = sha256.Sum256(hash[:])
if !slices.Equal(hash[:4], data[78:]) {
return nil, fmt.Errorf("invalid checksum")
}
chainCode := make([]byte, 32)
copy(chainCode, data[13:45])
privateKey := make([]byte, 32)
copy(privateKey, data[46:78])
masterKey, err := crypto.MasterKeyFromPrivKey(chainCode, privateKey)
if err != nil {
return nil, err
}
privBytes := append([]byte{0x00}, masterKey.PrivateKey...)
return &nockchain.ImportKeysResponse{
Seed: "",
PrivateKey: base58.Encode(masterKey.PrivateKey),
PublicKey: base58.Encode(masterKey.PublicKey),
ChainCode: base58.Encode(masterKey.ChainCode),
ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart)),
ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart)),
}, nil
case strings.HasPrefix(req.Key, "zpub"):
if len(data) != 145 {
return nil, fmt.Errorf("invalid extended public key length: %d (expected 145)", len(data))
}
hash := sha256.Sum256(data[:141])
hash = sha256.Sum256(hash[:])
if !slices.Equal(hash[:4], data[141:]) {
return nil, fmt.Errorf("invalid checksum")
}
chainCode := make([]byte, 32)
copy(chainCode, data[13:45])
publicKey := make([]byte, 97)
copy(publicKey, data[45:141])
return &nockchain.ImportKeysResponse{
Seed: "",
PrivateKey: "",
PublicKey: base58.Encode(publicKey),
ChainCode: base58.Encode(chainCode),
ImportPrivateKey: "",
ImportPublicKey: base58.Encode(crypto.SerializeExtend(chainCode, publicKey, crypto.PublicKeyStart)),
}, nil
default:
return nil, fmt.Errorf("invalid extended key")
}
case nockchain.ImportType_MASTER_PRIVKEY:
splits := strings.Split(req.Key, ",")
if len(splits) != 2 {
return nil, fmt.Errorf("master key must be in [chain_code],[key] format")
}
chainCode := base58.Decode(splits[0])
key := base58.Decode(splits[1])
masterKey, err := crypto.MasterKeyFromPrivKey(chainCode, key)
if err != nil {
return nil, err
}
privBytes := append([]byte{0x00}, masterKey.PrivateKey...)
return &nockchain.ImportKeysResponse{
Seed: "",
PrivateKey: base58.Encode(masterKey.PrivateKey),
PublicKey: base58.Encode(masterKey.PublicKey),
ChainCode: base58.Encode(masterKey.ChainCode),
ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart)),
ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart)),
}, nil
case nockchain.ImportType_SEEDPHRASE:
masterKey, err := crypto.MasterKeyFromSeed(req.Key)
if err != nil {
return nil, err
}
privBytes := append([]byte{0x00}, masterKey.PrivateKey...)
return &nockchain.ImportKeysResponse{
Seed: "",
PrivateKey: base58.Encode(masterKey.PrivateKey),
PublicKey: base58.Encode(masterKey.PublicKey),
ChainCode: base58.Encode(masterKey.ChainCode),
ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart)),
ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart)),
}, nil
case nockchain.ImportType_WATCH_ONLY:
pubKey := base58.Decode(req.Key)
return &nockchain.ImportKeysResponse{
Seed: "",
PrivateKey: "",
PublicKey: base58.Encode(pubKey),
ChainCode: "",
ImportPrivateKey: "",
ImportPublicKey: "",
}, nil
default:
return nil, fmt.Errorf("invalid import type")
}
}
func (h *GprcHandler) DeriveChild(ctx context.Context, req *nockchain.DeriveChildRequest) (*nockchain.DeriveChildResponse, error) {
data := base58.Decode(req.ImportedKey)
index := req.Index
if index > 1<<32 {
return nil, fmt.Errorf("child index %d out of range, child indices are capped to values between [0, 2^32)", index)
}
if req.Hardened {
index += 1 << 31
}
switch {
case strings.HasPrefix(req.ImportedKey, "zprv"):
if len(data) != 82 {
return nil, fmt.Errorf("invalid extended private key length: %d (expected 82)", len(data))
}
if data[45] != 0x00 {
return nil, fmt.Errorf("invalid private key prefix at byte 45: 0x%02x (expected 0x00)", data[45])
}
hash := sha256.Sum256(data[:78])
hash = sha256.Sum256(hash[:])
if !slices.Equal(hash[:4], data[78:]) {
return nil, fmt.Errorf("invalid checksum")
}
chainCode := make([]byte, 32)
copy(chainCode, data[13:45])
privateKey := make([]byte, 32)
copy(privateKey, data[46:78])
masterKey, err := crypto.MasterKeyFromPrivKey(chainCode, privateKey)
if err != nil {
return nil, err
}
childKey, err := masterKey.DeriveChild(index)
if err != nil {
return nil, err
}
return &nockchain.DeriveChildResponse{
PublicKey: base58.Encode(childKey.PublicKey),
PrivateKey: base58.Encode(childKey.PrivateKey),
ChainCode: base58.Encode(childKey.ChainCode),
}, nil
case strings.HasPrefix(req.ImportedKey, "zpub"):
if len(data) != 145 {
return nil, fmt.Errorf("invalid extended public key length: %d (expected 145)", len(data))
}
hash := sha256.Sum256(data[:141])
hash = sha256.Sum256(hash[:])
if !slices.Equal(hash[:4], data[141:]) {
return nil, fmt.Errorf("invalid checksum")
}
chainCode := make([]byte, 32)
copy(chainCode, data[13:45])
publicKey := make([]byte, 97)
copy(publicKey, data[45:141])
masterKey := crypto.MasterKey{
PublicKey: publicKey,
ChainCode: chainCode,
PrivateKey: []byte{},
}
childKey, err := masterKey.DeriveChild(index)
if err != nil {
return nil, err
}
return &nockchain.DeriveChildResponse{
PublicKey: base58.Encode(childKey.PublicKey),
PrivateKey: "",
ChainCode: base58.Encode(childKey.ChainCode),
}, nil
default:
return nil, fmt.Errorf("invalid extended key")
}
}
// - `names` - Comma-separated list of note name pairs in format "[first last]"
// Example: "[first1 last1],[first2 last2]"
//
// - `recipients` - Comma-separated list of recipient $locks
// Example: "[1 pk1],[2 pk2,pk3,pk4]"
// A simple comma-separated list is also supported: "pk1,pk2,pk3",
// where it is presumed that all recipients are single-signature,
// that is to say, it is the same as "[1 pk1],[1 pk2],[1 pk3]"
//
// - `gifts` - Comma-separated list of amounts to send to each recipient
// Example: "100,200"
//
// - `fee` - Transaction fee to be subtracted from one of the input notes
func (h *GprcHandler) CreateTx(ctx context.Context, req *nockchain.CreateTxRequest) (*nockchain.CreateTxResponse, error) {
firstNames := [][5]uint64{}
lastNames := [][5]uint64{}
for _, name := range strings.Split(req.Names, ",") {
name = strings.TrimSpace(name)
if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
inner := name[1 : len(name)-1]
part := strings.Split(inner, " ")
if len(part) == 2 {
firstNames = append(firstNames, crypto.Base58ToTip5Hash(part[0]))
lastNames = append(lastNames, crypto.Base58ToTip5Hash(part[1]))
}
}
}
type Recipent struct {
index uint64
pubkeys [][]byte
}
recipents := []Recipent{}
if strings.Contains(req.Recipients, "[") {
pairs := strings.Split(req.Recipients, ",")
for _, pair := range pairs {
pair = strings.TrimSpace(pair)
if strings.HasPrefix(pair, "[") && strings.HasSuffix(pair, "]") {
inner := pair[1 : len(pair)-1]
parts := strings.SplitN(inner, " ", 2)
if len(parts) == 2 {
number, err := strconv.ParseUint(parts[0], 10, 64)
if err != nil {
continue
}
pubkeyStrs := strings.Split(parts[1], ",")
var pubkeys [][]byte
for _, s := range pubkeyStrs {
pubkeys = append(pubkeys, base58.Decode(strings.TrimSpace(s)))
}
recipents = append(recipents, Recipent{index: number, pubkeys: pubkeys})
}
}
}
} else {
// Parse simple format: "pk1,pk2,pk3"
addrs := strings.Split(req.Recipients, ",")
for _, addr := range addrs {
recipents = append(recipents, Recipent{index: uint64(1), pubkeys: [][]byte{base58.Decode(strings.TrimSpace(addr))}})
}
}
gifts := []uint64{}
for _, gift := range strings.Split(req.Gifts, ",") {
gift, err := strconv.ParseUint(gift, 10, 64)
if err != nil {
continue
}
gifts = append(gifts, gift)
}
// Verify lengths based on single vs multiple mode
if len(recipents) == 1 && len(gifts) == 1 {
// Single mode: can spend from multiple notes to single recipient
// No additional validation needed - any number of names is allowed
} else {
// Multiple mode: all lengths must match
if len(firstNames) != len(recipents) || len(firstNames) != len(gifts) {
return nil, fmt.Errorf("multiple recipient mode requires names, recipients, and gifts to have the same length")
}
}
var masterKey *crypto.MasterKey
chainCode := base58.Decode(req.ChainCode)
key := base58.Decode(req.Key)
_, err := crypto.CheetaPointFromBytes(key)
if err != nil {
// priv key
masterKey, err = crypto.MasterKeyFromPrivKey(chainCode, key)
if err != nil {
return nil, err
}
} else {
masterKey = &crypto.MasterKey{
PrivateKey: []byte{},
PublicKey: key,
ChainCode: chainCode,
}
}
if !req.IsMasterKey {
index := req.Index
if index > 1<<32 {
return nil, fmt.Errorf("child index %d out of range, child indices are capped to values between [0, 2^32)", index)
}
if req.Hardened {
index += 1 << 31
}
childKey, err := masterKey.DeriveChild(index)
if err != nil {
return nil, err
}
masterKey = &childKey
}
// Scan key to get notes
masterKeyScan, err := h.client.WalletGetBalance(base58.Encode(masterKey.PublicKey))
if err != nil {
return nil, err
}
if len(masterKeyScan.Notes) != 0 {
// TODO: check notes by first and last name
}
return nil, nil
}
func (h *GprcHandler) Scan(ctx context.Context, req *nockchain.ScanRequest) (*nockchain.ScanResponse, error) {
scanData := []*nockchain.ScanData{}
keyBytes := base58.Decode(req.MasterPubkey)
chainCode := base58.Decode(req.ChainCode)
masterKey := crypto.MasterKey{
PublicKey: keyBytes,
ChainCode: chainCode,
PrivateKey: []byte{},
}
masterKeyScan, err := h.client.WalletGetBalance(req.MasterPubkey)
if err != nil {
return nil, err
}
if len(masterKeyScan.Notes) != 0 {
scanData = append(scanData, &nockchain.ScanData{
Pubkey: req.MasterPubkey,
Data: masterKeyScan,
})
}
for i := uint64(0); i < req.SearchDepth; i++ {
childKey, err := masterKey.DeriveChild(i)
if err != nil {
continue
}
childKeyScan, err := h.client.WalletGetBalance(base58.Encode(childKey.PublicKey))
if err != nil {
continue
}
if len(childKeyScan.Notes) != 0 {
scanData = append(scanData, &nockchain.ScanData{
Pubkey: base58.Encode(childKey.PublicKey),
Data: childKeyScan,
})
}
}
return &nockchain.ScanResponse{
ScanData: scanData,
}, nil
}
func (h *GprcHandler) SignTx(context.Context, *nockchain.SignTxRequest) (*nockchain.SignTxResponse, error) {
return nil, nil
}