-
Notifications
You must be signed in to change notification settings - Fork 0
/
ledger_key.go
179 lines (160 loc) · 4.74 KB
/
ledger_key.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package xdr
import (
"encoding/base64"
"fmt"
"strings"
)
// LedgerKey implements the `Keyer` interface
func (key *LedgerKey) LedgerKey() LedgerKey {
return *key
}
// Equals returns true if `other` is equivalent to `key`
func (key *LedgerKey) Equals(other LedgerKey) bool {
if key.Type != other.Type {
return false
}
switch key.Type {
case LedgerEntryTypeAccount:
l := key.MustAccount()
r := other.MustAccount()
return l.AccountId.Equals(r.AccountId)
case LedgerEntryTypeData:
l := key.MustData()
r := other.MustData()
return l.AccountId.Equals(r.AccountId) && l.DataName == r.DataName
case LedgerEntryTypeOffer:
l := key.MustOffer()
r := other.MustOffer()
return l.SellerId.Equals(r.SellerId) && l.OfferId == r.OfferId
case LedgerEntryTypeTrustline:
l := key.MustTrustLine()
r := other.MustTrustLine()
return l.AccountId.Equals(r.AccountId) && l.Asset.Equals(r.Asset)
default:
panic(fmt.Errorf("Unknown ledger key type: %v", key.Type))
}
}
// SetAccount mutates `key` such that it represents the identity of `account`
func (key *LedgerKey) SetAccount(account AccountId) error {
data := LedgerKeyAccount{account}
nkey, err := NewLedgerKey(LedgerEntryTypeAccount, data)
if err != nil {
return err
}
*key = nkey
return nil
}
// SetData mutates `key` such that it represents the identity of the
// data entry owned by `account` and for `name`.
func (key *LedgerKey) SetData(account AccountId, name string) error {
data := LedgerKeyData{account, String64(name)}
nkey, err := NewLedgerKey(LedgerEntryTypeData, data)
if err != nil {
return err
}
*key = nkey
return nil
}
// SetOffer mutates `key` such that it represents the identity of the
// data entry owned by `account` and for offer `id`.
func (key *LedgerKey) SetOffer(account AccountId, id uint64) error {
data := LedgerKeyOffer{account, Int64(id)}
nkey, err := NewLedgerKey(LedgerEntryTypeOffer, data)
if err != nil {
return err
}
*key = nkey
return nil
}
// SetTrustline mutates `key` such that it represents the identity of the
// trustline owned by `account` and for `asset`.
func (key *LedgerKey) SetTrustline(account AccountId, line Asset) error {
data := LedgerKeyTrustLine{account, line}
nkey, err := NewLedgerKey(LedgerEntryTypeTrustline, data)
if err != nil {
return err
}
*key = nkey
return nil
}
// SetClaimableBalance mutates `key` such that it represents the identity of a
// claimable balance.
func (key *LedgerKey) SetClaimableBalance(balanceID ClaimableBalanceId) error {
data := LedgerKeyClaimableBalance{balanceID}
nkey, err := NewLedgerKey(LedgerEntryTypeClaimableBalance, data)
if err != nil {
return err
}
*key = nkey
return nil
}
// MarshalBinaryCompress marshals LedgerKey to []byte but unlike
// MarshalBinary() it removes all unnecessary bytes, exploting the fact
// that XDR is padding data to 4 bytes in union discriminants etc.
// It's primary use is in ingest/io.StateReader that keep LedgerKeys in
// memory so this function decrease memory requirements.
//
// Warning, do not use UnmarshalBinary() on data encoded using this method!
//
// Optimizations:
// - Writes a single byte for union discriminants vs 4 bytes.
// - Removes type and code padding for Asset.
func (key LedgerKey) MarshalBinaryCompress() ([]byte, error) {
m := []byte{byte(key.Type)}
switch key.Type {
case LedgerEntryTypeAccount:
account, err := key.Account.AccountId.MarshalBinaryCompress()
if err != nil {
return nil, err
}
m = append(m, account...)
case LedgerEntryTypeTrustline:
account, err := key.TrustLine.AccountId.MarshalBinaryCompress()
if err != nil {
return nil, err
}
m = append(m, account...)
asset, err := key.TrustLine.Asset.MarshalBinaryCompress()
if err != nil {
return nil, err
}
m = append(m, asset...)
case LedgerEntryTypeOffer:
seller, err := key.Offer.SellerId.MarshalBinaryCompress()
if err != nil {
return nil, err
}
m = append(m, seller...)
offer, err := key.Offer.OfferId.MarshalBinary()
if err != nil {
return nil, err
}
m = append(m, offer...)
case LedgerEntryTypeData:
account, err := key.Data.AccountId.MarshalBinaryCompress()
if err != nil {
return nil, err
}
m = append(m, account...)
dataName := []byte(strings.TrimRight(string(key.Data.DataName), "\x00"))
m = append(m, dataName...)
case LedgerEntryTypeClaimableBalance:
cBalance, err := key.ClaimableBalance.BalanceId.MarshalBinaryCompress()
if err != nil {
return nil, err
}
m = append(m, cBalance...)
default:
panic("Unknown type")
}
return m, nil
}
// MarshalBinaryBase64 marshals XDR into a binary form and then encodes it
// using base64.
func (key LedgerKey) MarshalBinaryBase64() (string, error) {
b, err := key.MarshalBinary()
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(b), nil
}