mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-05-04 19:02:28 +00:00
Persist blockchain with leveldb on disk (#48)
* Created test_data folder with block json files for testing + create separate file for block base. * Fixed bug in WriteVarUint + Trim logic + unit tests * Refactored store and add more tests for it. * restore headerList from chain file * Fix tx decode bug + lots of housekeeping. * Implemented Node restore state from chain file. * Created standalone package for storage. Added couple more methods to Batch and Store interfaces. * Block persisting + tests * bumped version -> 0.31.0
This commit is contained in:
parent
b41e14e0f0
commit
a67728628e
45 changed files with 1419 additions and 530 deletions
|
@ -1,6 +1,13 @@
|
|||
package core
|
||||
|
||||
import "github.com/CityOfZion/neo-go/pkg/util"
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"sort"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// Utilities for quick bootstrapping blockchains. Normally we should
|
||||
// create the genisis block. For now (to speed up development) we will add
|
||||
|
@ -20,3 +27,75 @@ func GenesisHashMainNet() util.Uint256 {
|
|||
hash, _ := util.Uint256DecodeString("d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf")
|
||||
return hash
|
||||
}
|
||||
|
||||
// headerSliceReverse reverses the given slice of *Header.
|
||||
func headerSliceReverse(dest []*Header) {
|
||||
for i, j := 0, len(dest)-1; i < j; i, j = i+1, j-1 {
|
||||
dest[i], dest[j] = dest[j], dest[i]
|
||||
}
|
||||
}
|
||||
|
||||
// storeAsCurrentBlock stores the given block witch prefix
|
||||
// SYSCurrentBlock.
|
||||
func storeAsCurrentBlock(batch storage.Batch, block *Block) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.Write(block.Hash().BytesReverse())
|
||||
b := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(b, block.Index)
|
||||
buf.Write(b)
|
||||
batch.Put(storage.SYSCurrentBlock.Bytes(), buf.Bytes())
|
||||
}
|
||||
|
||||
// storeAsBlock stores the given block as DataBlock.
|
||||
func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error {
|
||||
var (
|
||||
key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesReverse())
|
||||
buf = new(bytes.Buffer)
|
||||
)
|
||||
|
||||
b := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(b, sysFee)
|
||||
|
||||
b, err := block.Trim()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf.Write(b)
|
||||
batch.Put(key, buf.Bytes())
|
||||
return nil
|
||||
}
|
||||
|
||||
// readStoredHeaderHashes returns a sorted list of header hashes
|
||||
// retrieved from the given Store.
|
||||
func readStoredHeaderHashes(store storage.Store) ([]util.Uint256, error) {
|
||||
hashMap := make(map[uint32][]util.Uint256)
|
||||
store.Seek(storage.IXHeaderHashList.Bytes(), func(k, v []byte) {
|
||||
storedCount := binary.LittleEndian.Uint32(k[1:])
|
||||
hashes, err := util.Read2000Uint256Hashes(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
hashMap[storedCount] = hashes
|
||||
})
|
||||
|
||||
var (
|
||||
i = 0
|
||||
sortedKeys = make([]int, len(hashMap))
|
||||
)
|
||||
|
||||
for k, _ := range hashMap {
|
||||
sortedKeys[i] = int(k)
|
||||
i++
|
||||
}
|
||||
sort.Ints(sortedKeys)
|
||||
|
||||
hashes := []util.Uint256{}
|
||||
for _, key := range sortedKeys {
|
||||
values := hashMap[uint32(key)]
|
||||
for _, hash := range values {
|
||||
hashes = append(hashes, hash)
|
||||
}
|
||||
}
|
||||
|
||||
return hashes, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue