diff --git a/chain/db.go b/chain/db.go index 9f1eda0..d2e9f98 100644 --- a/chain/db.go +++ b/chain/db.go @@ -37,6 +37,29 @@ func (sb *supplementedBlock) DecodeFrom(d *types.Decoder) { } } +func (sb *supplementedBlock) decodeOldSupplement(d *types.Decoder) { + if v := d.ReadUint8(); v != 2 { + d.SetErr(fmt.Errorf("incompatible version (%d)", v)) + } + (*types.V2Block)(&sb.Block).DecodeFrom(d) + if d.ReadBool() { + sb.Supplement = new(consensus.V1BlockSupplement) + types.DecodeSliceFn(d, &sb.Supplement.Transactions, func(d *types.Decoder) (ts consensus.V1TransactionSupplement) { + types.DecodeSlice(d, &ts.SiacoinInputs) + types.DecodeSlice(d, &ts.SiafundInputs) + types.DecodeSlice(d, &ts.RevisedFileContracts) + var fces []types.FileContractElement + types.DecodeSlice(d, &fces) + ts.StorageProofs = make([]consensus.V1StorageProofSupplement, len(fces)) + for i, fce := range fces { + ts.StorageProofs[i] = consensus.V1StorageProofSupplement{FileContract: fce} + } + return + }) + types.DecodeSlice(d, &sb.Supplement.ExpiringFileContracts) + } +} + // helper type for decoding just the header information from a block type supplementedHeader struct { ParentID types.BlockID @@ -306,8 +329,22 @@ func (db *DBStore) putState(cs consensus.State) { func (db *DBStore) getBlock(id types.BlockID) (b types.Block, bs *consensus.V1BlockSupplement, _ bool) { var sb supplementedBlock - ok := db.bucket(bBlocks).get(id[:], &sb) - return sb.Block, sb.Supplement, ok + + val := db.bucket(bBlocks).getRaw(id[:]) + if val == nil { + return b, bs, false + } + // fallback to old encoding before panicking + d := types.NewBufDecoder(val) + sb.DecodeFrom(d) + if d.Err() != nil { + d = types.NewBufDecoder(val) + sb.decodeOldSupplement(d) + } + if d.Err() != nil { + check(fmt.Errorf("error decoding %T: %w", &sb, d.Err())) + } + return sb.Block, sb.Supplement, true } func (db *DBStore) putBlock(b types.Block, bs *consensus.V1BlockSupplement) {