forked from fivebinaries/go-cardano-serialization
/
pointer.go
112 lines (96 loc) · 3.02 KB
/
pointer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package address
import (
"errors"
"reflect"
"github.com/btcsuite/btcutil/bech32"
"github.com/fxamacker/cbor/v2"
"github.com/milos-ethernal/go-cardano-serialization/network"
)
type StakePointer struct {
Slot uint64
TxIndex uint64
CertIndex uint64
}
// A pointer address indirectly specifies the staking key that should control the stake for the address.
type PointerAddress struct {
Network network.NetworkInfo
Payment StakeCredential
Stake StakePointer
}
func VariableNatEncode(num uint64) []byte {
var output []byte
output = append(output, byte(num)&0x7F)
num /= 128
for num > 0 {
output = append(output, byte(num)&0x7F|0x80)
num /= 128
}
reverseAny(output)
return output
}
func VariableNatDecode(raw []byte) (uint64, int, error) {
var output uint64
output = 0
bytes_read := 0
for _, rbyte := range raw {
output = (output << 7) | uint64(rbyte&0x7F)
bytes_read += 1
if (rbyte & 0x80) == 0 {
return output, bytes_read, nil
}
}
return 0, 0, errors.New("unexpected bytes")
}
func reverseAny(s interface{}) {
n := reflect.ValueOf(s).Len()
swap := reflect.Swapper(s)
for i, j := 0, n-1; i < j; i, j = i+1, j-1 {
swap(i, j)
}
}
// MarshalCBOR returns a cbor encoded byte slice of the enterprise address.
func (p *PointerAddress) MarshalCBOR() (bytes []byte, err error) {
return cbor.Marshal(p.Bytes())
}
// Bytes retuns a byte slice representation of the pointer address.
func (p *PointerAddress) Bytes() (bytes []byte) {
var buf []byte
header := 0b0100_0000 | (byte(p.Payment.Kind) << 4) | (byte(p.Network.NetworkId) & 0xF)
buf = append(buf, header)
buf = append(buf, p.Payment.Payload...)
buf = append(buf, VariableNatEncode(p.Stake.Slot)...)
buf = append(buf, VariableNatEncode(p.Stake.TxIndex)...)
return append(buf, VariableNatEncode(p.Stake.CertIndex)...)
}
// String returns a bech32 encoded string of the Enterprise Address.
func (p *PointerAddress) String() string {
str, _ := bech32.Encode(p.Prefix(), p.Bytes())
return str
}
// Prefix returns the string prefix for the base address. Prefix `addr` for mainnet addresses and `addr_test` for testnet.
func (p *PointerAddress) Prefix() string {
if p.Network == *network.TestNet() {
return "addr_test"
}
return "addr"
}
// NetworkInfo returns NetworkInfo{ProtocolMagigic and NetworkId}.
func (p *PointerAddress) NetworkInfo() *network.NetworkInfo {
return &(p.Network)
}
// NewPointer returns a pointer to a new StakePointer given slot, transaction index and certificate index.
func NewPointer(slot, txIndex, certIndex uint64) *StakePointer {
return &StakePointer{
Slot: slot,
TxIndex: txIndex,
CertIndex: certIndex,
}
}
// NewPointerAddress returns a pointer to a new Pointer address given the network, payment and stake credentials.
func NewPointerAddress(net network.NetworkInfo, payment StakeCredential, stake StakePointer) *PointerAddress {
return &PointerAddress{
Network: net,
Payment: payment,
Stake: stake,
}
}