@@ -19,7 +19,10 @@ import (
19
19
"golang.org/x/crypto/blake2b"
20
20
)
21
21
22
- var ErrUnknownLatestCertificate = errors .New ("latest certificate is not known" )
22
+ var (
23
+ ErrUnknownLatestCertificate = errors .New ("latest certificate is not known" )
24
+ ErrNoCertificateExtracted = errors .New ("no certificate is found in the snapshot" )
25
+ )
23
26
24
27
// ExportLatestSnapshot exports an F3 snapshot that includes the finality certificate chain until the current `latestCertificate`.
25
28
//
@@ -104,34 +107,79 @@ func importSnapshotToDatastoreWithTestingPowerTableFrequency(ctx context.Context
104
107
dsb := autobatch .NewAutoBatching (ds , 1000 )
105
108
defer dsb .Flush (ctx )
106
109
cs , err := OpenOrCreateStore (ctx , dsb , header .FirstInstance , header .InitialPowerTable )
107
- if testingPowerTableFrequency > 0 {
108
- cs .powerTableFrequency = testingPowerTableFrequency
109
- }
110
110
if err != nil {
111
111
return err
112
112
}
113
- pt := header .InitialPowerTable
114
- for {
113
+ if testingPowerTableFrequency > 0 {
114
+ cs .powerTableFrequency = testingPowerTableFrequency
115
+ }
116
+ var latestCert * certs.FinalityCertificate
117
+ ptm := certs .PowerTableArrayToMap (header .InitialPowerTable )
118
+ for i := header .FirstInstance ; ; i += 1 {
115
119
certBytes , err := readSnapshotBlockBytes (snapshot )
116
120
if err == io .EOF {
117
121
break
118
122
} else if err != nil {
119
123
return fmt .Errorf ("failed to decode finality certificate: %w" , err )
120
124
}
125
+
121
126
var cert certs.FinalityCertificate
122
- cert .UnmarshalCBOR (bytes .NewReader (certBytes ))
123
- if err = cs .Put (ctx , & cert ); err != nil {
127
+ if err = cert .UnmarshalCBOR (bytes .NewReader (certBytes )); err != nil {
124
128
return err
125
129
}
126
- if pt , err = certs .ApplyPowerTableDiffs (pt , cert .PowerTableDelta ); err != nil {
130
+ latestCert = & cert
131
+
132
+ if i != cert .GPBFTInstance {
133
+ return fmt .Errorf ("the certificate of instance %d is missing" , i )
134
+ }
135
+
136
+ if i > header .LatestInstance {
137
+ return fmt .Errorf ("certificate of instance %d is found, expected latest instance %d" , i , header .LatestInstance )
138
+ }
139
+
140
+ if err := cs .ds .Put (ctx , cs .keyForCert (cert .GPBFTInstance ), certBytes ); err != nil {
127
141
return err
128
142
}
143
+
144
+ if ptm , err = certs .ApplyPowerTableDiffsToMap (ptm , cert .PowerTableDelta ); err != nil {
145
+ return err
146
+ }
147
+
129
148
if (cert .GPBFTInstance + 1 )% cs .powerTableFrequency == 0 {
149
+ pt := certs .PowerTableMapToArray (ptm )
150
+ if err = checkPowerTable (pt , cert .SupplementalData .PowerTable ); err != nil {
151
+ return err
152
+ }
130
153
if err := cs .putPowerTable (ctx , cert .GPBFTInstance + 1 , pt ); err != nil {
131
154
return err
132
155
}
133
156
}
134
157
}
158
+
159
+ if latestCert == nil {
160
+ return ErrNoCertificateExtracted
161
+ }
162
+
163
+ if latestCert .GPBFTInstance != header .LatestInstance {
164
+ return fmt .Errorf ("extracted latest instance %d, but %d is expected" , latestCert .GPBFTInstance , header .LatestInstance )
165
+ }
166
+
167
+ pt := certs .PowerTableMapToArray (ptm )
168
+ if err = checkPowerTable (pt , latestCert .SupplementalData .PowerTable ); err != nil {
169
+ return err
170
+ }
171
+
172
+ return cs .writeInstanceNumber (ctx , certStoreLatestKey , header .LatestInstance )
173
+ }
174
+
175
+ func checkPowerTable (pt gpbft.PowerEntries , expectedCid cid.Cid ) error {
176
+ ptCid , err := certs .MakePowerTableCID (pt )
177
+ if err != nil {
178
+ return err
179
+ }
180
+ if ptCid != expectedCid {
181
+ return fmt .Errorf ("new power table differs from expected power table: %s != %s" , ptCid , expectedCid )
182
+ }
135
183
return nil
136
184
}
137
185
0 commit comments