• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 15951470896

29 Jun 2025 04:23AM UTC coverage: 67.594% (-0.01%) from 67.606%
15951470896

Pull #9751

github

web-flow
Merge 599d9b051 into 6290edf14
Pull Request #9751: multi: update Go to 1.23.10 and update some packages

135088 of 199851 relevant lines covered (67.59%)

21909.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.48
/shachain/store.go
1
package shachain
2

3
import (
4
        "encoding/binary"
5
        "io"
6

7
        "github.com/btcsuite/btcd/chaincfg/chainhash"
8
        "github.com/go-errors/errors"
9
)
10

11
// Store is an interface which serves as an abstraction over data structure
12
// responsible for efficiently storing and restoring of hash secrets by given
13
// indexes.
14
//
15
// Description: The Lightning Network wants a chain of (say 1 million)
16
// unguessable 256 bit values; we generate them and send them one at a time to
17
// a remote node.  We don't want the remote node to have to store all the
18
// values, so it's better if they can derive them once they see them.
19
type Store interface {
20
        // LookUp function is used to restore/lookup/fetch the previous secret
21
        // by its index.
22
        LookUp(uint64) (*chainhash.Hash, error)
23

24
        // AddNextEntry attempts to store the given hash within its internal
25
        // storage in an efficient manner.
26
        //
27
        // NOTE: The hashes derived from the shachain MUST be inserted in the
28
        // order they're produced by a shachain.Producer.
29
        AddNextEntry(*chainhash.Hash) error
30

31
        // Encode writes a binary serialization of the shachain elements
32
        // currently saved by implementation of shachain.Store to the passed
33
        // io.Writer.
34
        Encode(io.Writer) error
35
}
36

37
// RevocationStore is a concrete implementation of the Store interface. The
38
// revocation store is able to efficiently store N derived shachain elements in
39
// a space efficient manner with a space complexity of O(log N). The original
40
// description of the storage methodology can be found here:
41
// https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#efficient-per-commitment-secret-storage
42
type RevocationStore struct {
43
        // lenBuckets stores the number of currently active buckets.
44
        lenBuckets uint8
45

46
        // buckets is an array of elements from which we may derive all
47
        // previous elements, each bucket corresponds to the element with the
48
        // particular number of trailing zeros.
49
        buckets [maxHeight]element
50

51
        // index is an available index which will be assigned to the new
52
        // element.
53
        index index
54
}
55

56
// A compile time check to ensure RevocationStore implements the Store
57
// interface.
58
var _ Store = (*RevocationStore)(nil)
59

60
// NewRevocationStore creates the new shachain store.
61
func NewRevocationStore() *RevocationStore {
930✔
62
        return &RevocationStore{
930✔
63
                lenBuckets: 0,
930✔
64
                index:      startIndex,
930✔
65
        }
930✔
66
}
930✔
67

68
// NewRevocationStoreFromBytes recreates the initial store state from the given
69
// binary shachain store representation.
70
func NewRevocationStoreFromBytes(r io.Reader) (*RevocationStore, error) {
9,052✔
71
        store := &RevocationStore{}
9,052✔
72

9,052✔
73
        if err := binary.Read(r, binary.BigEndian, &store.lenBuckets); err != nil {
9,052✔
74
                return nil, err
×
75
        }
×
76

77
        for i := uint8(0); i < store.lenBuckets; i++ {
35,989✔
78
                var hashIndex index
26,937✔
79
                err := binary.Read(r, binary.BigEndian, &hashIndex)
26,937✔
80
                if err != nil {
26,937✔
81
                        return nil, err
×
82
                }
×
83

84
                var nextHash chainhash.Hash
26,937✔
85
                if _, err := io.ReadFull(r, nextHash[:]); err != nil {
26,937✔
86
                        return nil, err
×
87
                }
×
88

89
                store.buckets[i] = element{
26,937✔
90
                        index: hashIndex,
26,937✔
91
                        hash:  nextHash,
26,937✔
92
                }
26,937✔
93
        }
94

95
        if err := binary.Read(r, binary.BigEndian, &store.index); err != nil {
9,052✔
96
                return nil, err
×
97
        }
×
98

99
        return store, nil
9,052✔
100
}
101

102
// LookUp function is used to restore/lookup/fetch the previous secret by its
103
// index. If secret which corresponds to given index was not previously placed
104
// in store we will not able to derive it and function will fail.
105
//
106
// NOTE: This function is part of the Store interface.
107
func (store *RevocationStore) LookUp(v uint64) (*chainhash.Hash, error) {
12,906✔
108
        ind := newIndex(v)
12,906✔
109

12,906✔
110
        // Trying to derive the index from one of the existing buckets elements.
12,906✔
111
        for i := uint8(0); i < store.lenBuckets; i++ {
142,325✔
112
                element, err := store.buckets[i].derive(ind)
129,419✔
113
                if err != nil {
245,935✔
114
                        continue
116,516✔
115
                }
116

117
                return &element.hash, nil
12,906✔
118
        }
119

120
        return nil, errors.Errorf("unable to derive hash #%v", ind)
×
121
}
122

123
// AddNextEntry attempts to store the given hash within its internal storage in
124
// an efficient manner.
125
//
126
// NOTE: The hashes derived from the shachain MUST be inserted in the order
127
// they're produced by a shachain.Producer.
128
//
129
// NOTE: This function is part of the Store interface.
130
func (store *RevocationStore) AddNextEntry(hash *chainhash.Hash) error {
12,229✔
131
        newElement := &element{
12,229✔
132
                index: store.index,
12,229✔
133
                hash:  *hash,
12,229✔
134
        }
12,229✔
135

12,229✔
136
        bucket := countTrailingZeros(newElement.index)
12,229✔
137

12,229✔
138
        for i := uint8(0); i < bucket; i++ {
23,793✔
139
                e, err := newElement.derive(store.buckets[i].index)
11,564✔
140
                if err != nil {
11,564✔
141
                        return err
×
142
                }
×
143

144
                if !e.isEqual(&store.buckets[i]) {
11,572✔
145
                        return errors.New("hash isn't derivable from " +
8✔
146
                                "previous ones")
8✔
147
                }
8✔
148
        }
149

150
        store.buckets[bucket] = *newElement
12,221✔
151
        if bucket+1 > store.lenBuckets {
13,226✔
152
                store.lenBuckets = bucket + 1
1,005✔
153
        }
1,005✔
154

155
        store.index--
12,221✔
156
        return nil
12,221✔
157
}
158

159
// Encode writes a binary serialization of the shachain elements currently
160
// saved by implementation of shachain.Store to the passed io.Writer.
161
//
162
// NOTE: This function is part of the Store interface.
163
func (store *RevocationStore) Encode(w io.Writer) error {
6,483✔
164
        err := binary.Write(w, binary.BigEndian, store.lenBuckets)
6,483✔
165
        if err != nil {
6,483✔
166
                return err
×
167
        }
×
168

169
        for i := uint8(0); i < store.lenBuckets; i++ {
20,300✔
170
                element := store.buckets[i]
13,817✔
171

13,817✔
172
                err := binary.Write(w, binary.BigEndian, element.index)
13,817✔
173
                if err != nil {
13,817✔
174
                        return err
×
175
                }
×
176

177
                if _, err = w.Write(element.hash[:]); err != nil {
13,817✔
178
                        return err
×
179
                }
×
180

181
        }
182

183
        return binary.Write(w, binary.BigEndian, store.index)
6,483✔
184
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc