THIN_HISTORY - Reinstate incarnation encoding in ChangeSets, but remove from index keys (#443)

* Cutting incarnation out of history and changeset keys

* Rollback the remove of incarnation only in changesets

* Fix linter

* Remove debug printing

* Reinstate encoding of incarnations in the ChangeSets

* Fix linter

* Fix linter

* Fix DefaultIncarnation

* Fixes

* Fix lint

* Fix to history writing

* Fix linter
This commit is contained in:
ledgerwatch 2020-04-12 19:36:27 +01:00 committed by GitHub
parent 9e65f886ea
commit fbe7a2cb06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 212 additions and 145 deletions

View File

@ -11,8 +11,9 @@ import (
)
const (
DefaultIncarnation = uint64(1)
storageEnodingIndexSize = 4
storageEnodingStartElem = uint32(4)
storageEnodingStartElem = 4
storageEnodingLengthOfNumOfElements = 4
storageEnodingLengthOfDict = 2
storageEnodingLengthOfNumTypeOfElements = 2
@ -40,6 +41,7 @@ numOfUint32Values uint16
[len(val0), len(val0)+len(val1), ..., len(val0)+len(val1)+...+len(val_{numOfUint8Values-1})] []uint8
[len(valnumOfUint8Values), len(val0)+len(val1), ..., len(val0)+len(val1)+...+len(val_{numOfUint16Values-1})] []uint16
[len(valnumOfUint16Values), len(val0)+len(val1), ..., len(val0)+len(val1)+...+len(val_{numOfUint32Values-1})] []uint32
[elementNum:incarnation] - optional [uint32:uint64...]
*/
func EncodeStorage(s *ChangeSet) ([]byte, error) {
@ -54,30 +56,32 @@ func EncodeStorage(s *ChangeSet) ([]byte, error) {
return nil, err
}
addrHashesMap := make(map[common.Hash]uint32)
addrHashList := make([]byte, 0)
addrHashesMap := make([]uint32, n)
var addrHashList []byte
notDefaultIncarnationList := make([]byte, 0)
//collect information about unique addHashes and non default incarnations
nextIDAddrHash := uint32(0)
var addrHash common.Hash
for i := 0; i < n; i++ {
//copy addrHash
copy(
addrHash[:],
s.Changes[i].Key[0:common.HashLength],
)
//fill addrHashesMap and addrHashList
if _, ok := addrHashesMap[addrHash]; !ok {
addrHashesMap[addrHash] = nextIDAddrHash
nextIDAddrHash++
addrHashList = append(addrHashList, addrHash[:]...)
var addrID uint32
var addrIdxToIncarnation [12]byte
for i, change := range s.Changes {
if i == 0 || !bytes.Equal(change.Key[:common.HashLength], s.Changes[i-1].Key[:common.HashLength]) {
if i > 0 {
addrID++
}
addrHashList = append(addrHashList, change.Key[:common.HashLength]...)
incarnation := ^binary.BigEndian.Uint64(change.Key[common.HashLength : common.HashLength+common.IncarnationLength])
if incarnation != DefaultIncarnation {
binary.BigEndian.PutUint32(addrIdxToIncarnation[:4], addrID)
binary.BigEndian.PutUint64(addrIdxToIncarnation[4:12], ^incarnation)
notDefaultIncarnationList = append(notDefaultIncarnationList, addrIdxToIncarnation[:]...)
}
}
addrHashesMap[i] = addrID
}
//write numOfUniqAddrHashes
numOfUniqAddrHashes := make([]byte, storageEnodingLengthOfDict)
binary.BigEndian.PutUint16(numOfUniqAddrHashes, uint16(len(addrHashesMap)))
binary.BigEndian.PutUint16(numOfUniqAddrHashes, uint16(addrID+1))
if _, err := buf.Write(numOfUniqAddrHashes); err != nil {
return nil, err
}
@ -87,60 +91,62 @@ func EncodeStorage(s *ChangeSet) ([]byte, error) {
return nil, err
}
lenOfAddr := getNumOfBytesByLen(len(addrHashesMap))
values := new(bytes.Buffer)
lengthes := make([]byte, storageEnodingLengthOfNumTypeOfElements*3)
lenOfAddr := getNumOfBytesByLen(int(addrID + 1))
numOfUint8 := uint16(0)
numOfUint16 := uint16(0)
numOfUint32 := uint16(0)
keys := new(bytes.Buffer)
lengthOfValues := uint32(0)
row := make([]byte, lenOfAddr+common.HashLength)
for i := 0; i < len(s.Changes); i++ {
for i, change := range s.Changes {
writeKeyRow(
addrHashesMap[common.BytesToHash(s.Changes[i].Key[0:common.HashLength])],
addrHashesMap[i],
row[0:lenOfAddr],
)
copy(row[lenOfAddr:lenOfAddr+common.HashLength], common.CopyBytes(s.Changes[i].Key[common.IncarnationLength+common.HashLength:common.IncarnationLength+2*common.HashLength]))
keys.Write(row)
lengthOfValues += uint32(len(s.Changes[i].Value))
copy(row[lenOfAddr:lenOfAddr+common.HashLength], change.Key[common.IncarnationLength+common.HashLength:common.IncarnationLength+2*common.HashLength])
buf.Write(row)
}
// Remember position to fix up the lengths later
lengthPos := buf.Len()
uint16b := make([]byte, 2)
// Reserve 3 positions for lengths
buf.Write(uint16b)
buf.Write(uint16b)
buf.Write(uint16b)
uint32b := make([]byte, 4)
for _, change := range s.Changes {
lengthOfValues += uint32(len(change.Value))
switch {
case lengthOfValues <= 255:
numOfUint8++
lengthes = append(lengthes, uint8(lengthOfValues))
buf.WriteByte(uint8(lengthOfValues))
case lengthOfValues <= 65535:
numOfUint16++
uint16b := make([]byte, 2)
binary.BigEndian.PutUint16(uint16b, uint16(lengthOfValues))
lengthes = append(lengthes, uint16b...)
buf.Write(uint16b)
default:
numOfUint32++
uint32b := make([]byte, 4)
binary.BigEndian.PutUint32(uint32b, lengthOfValues)
lengthes = append(lengthes, uint32b...)
buf.Write(uint32b)
}
values.Write(s.Changes[i].Value)
}
binary.BigEndian.PutUint16(lengthes[0:storageEnodingLengthOfNumTypeOfElements], numOfUint8)
binary.BigEndian.PutUint16(lengthes[storageEnodingLengthOfNumTypeOfElements:2*storageEnodingLengthOfNumTypeOfElements], numOfUint16)
binary.BigEndian.PutUint16(lengthes[2*storageEnodingLengthOfNumTypeOfElements:3*storageEnodingLengthOfNumTypeOfElements], numOfUint32)
if _, err := buf.Write(keys.Bytes()); err != nil {
return nil, err
for _, change := range s.Changes {
buf.Write(change.Value)
}
if _, err := buf.Write(lengthes); err != nil {
return nil, err
if len(notDefaultIncarnationList) > 0 {
if _, err := buf.Write(notDefaultIncarnationList); err != nil {
return nil, err
}
}
if _, err := buf.Write(values.Bytes()); err != nil {
return nil, err
}
byt := buf.Bytes()
return byt, nil
b := buf.Bytes()
// Fix up the lengths
binary.BigEndian.PutUint16(b[lengthPos:], numOfUint8)
binary.BigEndian.PutUint16(b[lengthPos+2:], numOfUint16)
binary.BigEndian.PutUint16(b[lengthPos+4:], numOfUint32)
return b, nil
}
func DecodeStorage(b []byte) (*ChangeSet, error) {
@ -153,50 +159,65 @@ func DecodeStorage(b []byte) (*ChangeSet, error) {
return h, fmt.Errorf("decode: input too short (%d bytes)", len(b))
}
//numOfElements uint32
numOfElements := binary.BigEndian.Uint32(b[0:storageEnodingLengthOfNumOfElements])
numOfElements := int(binary.BigEndian.Uint32(b[0:storageEnodingLengthOfNumOfElements]))
h.Changes = make([]Change, numOfElements)
if numOfElements == 0 {
return h, nil
}
dictLen := binary.BigEndian.Uint16(b[storageEnodingLengthOfNumOfElements : storageEnodingLengthOfNumOfElements+storageEnodingLengthOfDict])
addMap := make(map[uint32]common.Hash)
for i := 0; i < int(dictLen); i++ {
dictLen := int(binary.BigEndian.Uint16(b[storageEnodingLengthOfNumOfElements : storageEnodingLengthOfNumOfElements+storageEnodingLengthOfDict]))
addMap := make(map[uint32][]byte)
for i := 0; i < dictLen; i++ {
elemStart := storageEnodingLengthOfNumOfElements + storageEnodingLengthOfDict + i*common.HashLength
addMap[uint32(i)] = common.BytesToHash(b[elemStart : elemStart+common.HashLength])
addMap[uint32(i)] = b[elemStart : elemStart+common.HashLength]
}
lenOfValsPos := storageEnodingStartElem +
2 + uint32(dictLen)*common.HashLength +
numOfElements*uint32(getNumOfBytesByLen(int(dictLen))+common.HashLength)
2 + dictLen*common.HashLength +
numOfElements*(getNumOfBytesByLen(dictLen)+common.HashLength)
numOfUint8 := int(binary.BigEndian.Uint16(b[lenOfValsPos : lenOfValsPos+2]))
numOfUint16 := int(binary.BigEndian.Uint16(b[lenOfValsPos+2 : lenOfValsPos+4]))
numOfUint32 := int(binary.BigEndian.Uint16(b[lenOfValsPos+4 : lenOfValsPos+6]))
lenOfValsPos = lenOfValsPos + 3*storageEnodingLengthOfNumTypeOfElements
valuesPos := lenOfValsPos + uint32(numOfUint8) + uint32(numOfUint16*2) + uint32(numOfUint32*4)
valuesPos := lenOfValsPos + numOfUint8 + numOfUint16*2 + numOfUint32*4
elementStart := storageEnodingStartElem + storageEnodingLengthOfDict + uint32(dictLen)*common.HashLength
key := make([]byte, common.HashLength*2+common.IncarnationLength)
incarnationPosition := lenOfValsPos + calculateIncarnationPos3(b[lenOfValsPos:], numOfUint8, numOfUint16, numOfUint32)
notDefaultIncarnation := make(map[uint32]uint64)
lenOfAddHash := uint32(getNumOfBytesByLen(len(addMap)))
//lastValLen:=0
for i := uint32(0); i < numOfElements; i++ {
if len(b) > incarnationPosition {
if len(b[incarnationPosition:])%12 != 0 {
return h, fmt.Errorf("decode: incarnatin part is incorrect(%d bytes)", len(b[incarnationPosition:]))
}
for i := incarnationPosition; i < len(b); i += 12 {
id := binary.BigEndian.Uint32(b[i : i+4])
inc := ^binary.BigEndian.Uint64(b[i+4 : i+12])
notDefaultIncarnation[id] = inc
}
}
elementStart := storageEnodingStartElem + storageEnodingLengthOfDict + dictLen*common.HashLength
lenOfAddHash := getNumOfBytesByLen(len(addMap))
for i := 0; i < numOfElements; i++ {
//copy addrHash
key := make([]byte, common.HashLength*2+common.IncarnationLength)
elem := elementStart + i*(lenOfAddHash+common.HashLength)
copy(
key[0:common.HashLength],
readFromMap(addMap, b[elem:elem+lenOfAddHash]).Bytes(),
)
addrIdx := getUint32(b[elem : elem+lenOfAddHash])
copy(key[:common.HashLength], addMap[addrIdx])
if inc, ok := notDefaultIncarnation[addrIdx]; ok {
binary.BigEndian.PutUint64(key[common.HashLength:], ^inc)
} else {
binary.BigEndian.PutUint64(key[common.HashLength:], ^DefaultIncarnation)
}
//copy key hash
copy(
key[common.HashLength+common.IncarnationLength:2*common.HashLength+common.IncarnationLength],
common.CopyBytes(b[elem+lenOfAddHash:elem+lenOfAddHash+common.HashLength]),
)
binary.BigEndian.PutUint64(key[common.HashLength:common.HashLength+common.IncarnationLength], ^uint64(1))
h.Changes[i].Key = common.CopyBytes(key)
h.Changes[i].Key = key
h.Changes[i].Value = findVal(b[lenOfValsPos:valuesPos], b[valuesPos:], i, numOfUint8, numOfUint16, numOfUint32)
}
return h, nil
@ -216,41 +237,57 @@ func getNumOfBytesByLen(n int) int {
}
}
func findVal(lenOfVals []byte, values []byte, i uint32, numOfUint8, numOfUint16, numOfUint32 int) []byte {
lenOfValStart := uint32(0)
lenOfValEnd := uint32(0)
func calculateIncarnationPos3(b []byte, numOfUint8, numOfUint16, numOfUint32 int) int {
res := 0
end := 0
switch {
case i < uint32(numOfUint8):
lenOfValEnd = uint32(lenOfVals[i])
case numOfUint32 > 0:
end = numOfUint8 + numOfUint16*2 + numOfUint32*4
res = int(binary.BigEndian.Uint32(b[end-4:end])) + end
case numOfUint16 > 0:
end = numOfUint8 + numOfUint16*2
res = int(binary.BigEndian.Uint16(b[end-2:end])) + end
case numOfUint8 > 0:
end = numOfUint8
res = int(b[end-1]) + end
default:
return 0
}
return res
}
func findVal(lenOfVals []byte, values []byte, i int, numOfUint8, numOfUint16, numOfUint32 int) []byte {
lenOfValStart := 0
lenOfValEnd := 0
switch {
case i < numOfUint8:
lenOfValEnd = int(lenOfVals[i])
if i > 0 {
lenOfValStart = uint32(lenOfVals[i-1])
lenOfValStart = int(lenOfVals[i-1])
}
return common.CopyBytes(values[lenOfValStart:lenOfValEnd])
case i < uint32(numOfUint8)+uint32(numOfUint16):
one := uint32(numOfUint8) + (i-uint32(numOfUint8))*2
lenOfValEnd = uint32(binary.BigEndian.Uint16(lenOfVals[one : one+2]))
if i-1 < uint32(numOfUint8) {
lenOfValStart = uint32(lenOfVals[i-1])
case i < numOfUint8+numOfUint16:
one := (i-numOfUint8)*2 + numOfUint8
lenOfValEnd = int(binary.BigEndian.Uint16(lenOfVals[one : one+2]))
if i-1 < numOfUint8 {
lenOfValStart = int(lenOfVals[i-1])
} else {
one = uint32(numOfUint8) + (i-1-uint32(numOfUint8))*2
lenOfValStart = uint32(binary.BigEndian.Uint16(lenOfVals[one : one+2]))
one = (i-1)*2 - numOfUint8
lenOfValStart = int(binary.BigEndian.Uint16(lenOfVals[one : one+2]))
}
return common.CopyBytes(values[lenOfValStart:lenOfValEnd])
case i < uint32(numOfUint8)+uint32(numOfUint16)+uint32(numOfUint32):
fmt.Println(i, uint32(numOfUint8), numOfUint16, numOfUint32)
one := uint32(numOfUint8) + uint32(numOfUint16)*2 + (i-uint32(numOfUint8)-uint32(numOfUint16))*4
lenOfValEnd = binary.BigEndian.Uint32(lenOfVals[one : one+4])
if i-1 < uint32(numOfUint8)+uint32(numOfUint16) {
one = uint32(numOfUint8) + (i-1-uint32(numOfUint8))*2
lenOfValStart = uint32(binary.BigEndian.Uint16(lenOfVals[one : one+2]))
case i < numOfUint8+numOfUint16+numOfUint32:
one := numOfUint8 + numOfUint16*2 + (i-numOfUint8-numOfUint16)*4
lenOfValEnd = int(binary.BigEndian.Uint32(lenOfVals[one : one+4]))
if i-1 < numOfUint8+numOfUint16 {
one = (i-1)*2 - numOfUint8
lenOfValStart = int(binary.BigEndian.Uint16(lenOfVals[one : one+2]))
} else {
one := uint32(numOfUint8) + uint32(numOfUint16)*2 + (i-1-uint32(numOfUint8)-uint32(numOfUint16))*4
lenOfValStart = binary.BigEndian.Uint32(lenOfVals[one : one+4])
one = numOfUint8 + numOfUint16*2 + (i-1-numOfUint8-numOfUint16)*4
lenOfValStart = int(binary.BigEndian.Uint32(lenOfVals[one : one+4]))
}
return common.CopyBytes(values[lenOfValStart:lenOfValEnd])
default:
panic("findval err")
}
return common.CopyBytes(values[lenOfValStart:lenOfValEnd])
}
func writeKeyRow(id uint32, row []byte) {
@ -267,16 +304,17 @@ func writeKeyRow(id uint32, row []byte) {
panic("wrong size of row")
}
}
func readFromMap(m map[uint32]common.Hash, row []byte) common.Hash {
func getUint32(row []byte) uint32 {
switch len(row) {
case 1:
return m[uint32(row[0])]
return uint32(row[0])
case 2:
return m[uint32(binary.BigEndian.Uint16(row))]
return uint32(binary.BigEndian.Uint16(row))
case 4:
return m[binary.BigEndian.Uint32(row)]
return binary.BigEndian.Uint32(row)
case 8:
return m[uint32(binary.BigEndian.Uint64(row))]
return uint32(binary.BigEndian.Uint64(row))
default:
panic("wrong")
}
@ -292,50 +330,65 @@ func (b StorageChangeSetBytes) Walk(f func(k, v []byte) error) error {
return fmt.Errorf("decode: input too short (%d bytes)", len(b))
}
numOfItems := binary.BigEndian.Uint32(b[0:4])
numOfItems := int(binary.BigEndian.Uint32(b[0:4]))
if numOfItems == 0 {
return nil
}
numOfUniqueItems := binary.BigEndian.Uint16(b[storageEnodingLengthOfNumOfElements : storageEnodingLengthOfNumOfElements+storageEnodingLengthOfDict])
numOfUniqueItems := int(binary.BigEndian.Uint16(b[storageEnodingLengthOfNumOfElements : storageEnodingLengthOfNumOfElements+storageEnodingLengthOfDict]))
lenOfValsPos := storageEnodingStartElem +
storageEnodingLengthOfDict +
uint32(numOfUniqueItems)*common.HashLength +
numOfItems*uint32(getNumOfBytesByLen(int(numOfUniqueItems))+common.HashLength)
numOfUniqueItems*common.HashLength +
numOfItems*(getNumOfBytesByLen(numOfUniqueItems)+common.HashLength)
numOfUint8 := int(binary.BigEndian.Uint16(b[lenOfValsPos : lenOfValsPos+storageEnodingLengthOfNumTypeOfElements]))
numOfUint16 := int(binary.BigEndian.Uint16(b[lenOfValsPos+storageEnodingLengthOfNumTypeOfElements : lenOfValsPos+storageEnodingLengthOfNumTypeOfElements*2]))
numOfUint32 := int(binary.BigEndian.Uint16(b[lenOfValsPos+storageEnodingLengthOfNumTypeOfElements*2 : lenOfValsPos+storageEnodingLengthOfNumTypeOfElements*3]))
lenOfValsPos += storageEnodingLengthOfNumTypeOfElements * 3
valuesPos := lenOfValsPos +
uint32(numOfUint8) +
uint32(numOfUint16*2) +
uint32(numOfUint32*4)
valuesPos := lenOfValsPos + numOfUint8 + numOfUint16*2 + numOfUint32*4
addrHashMap := make(map[uint32]common.Hash, numOfUniqueItems)
incarnationPosition := lenOfValsPos + calculateIncarnationPos3(b[lenOfValsPos:], numOfUint8, numOfUint16, numOfUint32)
notDefaultIncarnation := make(map[uint32]uint64)
if len(b) > incarnationPosition {
if len(b[incarnationPosition:])%12 != 0 {
return fmt.Errorf("decode: incarnatin part is incorrect(%d bytes)", len(b[incarnationPosition:]))
}
for i := incarnationPosition; i < len(b); i += 12 {
id := binary.BigEndian.Uint32(b[i : i+4])
inc := ^binary.BigEndian.Uint64(b[i+4 : i+12])
notDefaultIncarnation[id] = inc
}
}
addrHashMap := make(map[uint32][]byte, numOfUniqueItems)
for i := uint32(0); i < uint32(numOfUniqueItems); i++ {
elemStart := storageEnodingStartElem + storageEnodingLengthOfDict + i*(common.HashLength)
addrHashMap[i] = common.BytesToHash(b[elemStart : elemStart+common.HashLength])
addrHashMap[i] = b[elemStart : elemStart+common.HashLength]
}
key := make([]byte, common.HashLength*2+common.IncarnationLength)
elemLength := uint32(getNumOfBytesByLen(int(numOfUniqueItems)))
for i := uint32(0); i < numOfItems; i++ {
elemLength := getNumOfBytesByLen(numOfUniqueItems)
for i := 0; i < numOfItems; i++ {
elemStart := storageEnodingStartElem +
storageEnodingLengthOfDict +
uint32(numOfUniqueItems)*(common.HashLength) +
numOfUniqueItems*(common.HashLength) +
i*(elemLength+common.HashLength)
//copy addrHash
copy(key[0:common.HashLength], readFromMap(addrHashMap, b[elemStart:elemStart+elemLength]).Bytes())
addrIdx := getUint32(b[elemStart : elemStart+elemLength])
copy(key[:common.HashLength], addrHashMap[addrIdx])
if inc, ok := notDefaultIncarnation[addrIdx]; ok {
binary.BigEndian.PutUint64(key[common.HashLength:common.HashLength+common.IncarnationLength], ^inc)
} else {
binary.BigEndian.PutUint64(key[common.HashLength:common.HashLength+common.IncarnationLength], ^DefaultIncarnation)
}
//copy key hash
copy(
key[common.HashLength+common.IncarnationLength:2*common.HashLength+common.IncarnationLength],
b[elemStart+elemLength:elemStart+elemLength+common.HashLength],
)
binary.BigEndian.PutUint64(key[common.HashLength:common.HashLength+common.IncarnationLength], ^uint64(1))
err := f(common.CopyBytes(key), findVal(b[lenOfValsPos:valuesPos], b[valuesPos:], i, numOfUint8, numOfUint16, numOfUint32))
if err != nil {
return err
@ -352,52 +405,50 @@ func (b StorageChangeSetBytes) Find(addrHash []byte, keyHash []byte) ([]byte, er
return nil, fmt.Errorf("decode: input too short (%d bytes)", len(b))
}
numOfItems := binary.BigEndian.Uint32(b[0:storageEnodingLengthOfNumOfElements])
numOfItems := int(binary.BigEndian.Uint32(b[:storageEnodingLengthOfNumOfElements]))
if numOfItems == 0 {
return nil, nil
}
numOfUniqueItems := binary.BigEndian.Uint16(b[storageEnodingLengthOfNumOfElements : storageEnodingLengthOfNumOfElements+storageEnodingLengthOfDict])
numOfUniqueItems := int(binary.BigEndian.Uint16(b[storageEnodingLengthOfNumOfElements:]))
var addHashID uint32
found := false
var elemStart uint32
elemStart := storageEnodingLengthOfNumOfElements + storageEnodingLengthOfDict
//todo[boris] here should be binary search
for i := uint32(0); i < uint32(numOfUniqueItems); i++ {
elemStart = storageEnodingLengthOfNumOfElements + storageEnodingLengthOfDict + i*common.HashLength
for i := 0; i < numOfUniqueItems; i++ {
if bytes.Equal(addrHash, b[elemStart:elemStart+common.HashLength]) {
found = true
addHashID = i
addHashID = uint32(i)
break
}
elemStart += common.HashLength
}
if !found {
fmt.Printf("did not find addrHash %x\n", addrHash)
return nil, ErrNotFound
}
elemLength := getNumOfBytesByLen(numOfUniqueItems)
lenOfValsPos := storageEnodingStartElem +
storageEnodingLengthOfDict +
uint32(numOfUniqueItems)*common.HashLength +
numOfItems*uint32(getNumOfBytesByLen(int(numOfUniqueItems))+common.HashLength)
numOfUniqueItems*common.HashLength +
numOfItems*(elemLength+common.HashLength)
numOfUint8 := int(binary.BigEndian.Uint16(b[lenOfValsPos : lenOfValsPos+storageEnodingLengthOfNumTypeOfElements]))
numOfUint16 := int(binary.BigEndian.Uint16(b[lenOfValsPos+storageEnodingLengthOfNumTypeOfElements : lenOfValsPos+storageEnodingLengthOfNumTypeOfElements*2]))
numOfUint32 := int(binary.BigEndian.Uint16(b[lenOfValsPos+storageEnodingLengthOfNumTypeOfElements*2 : lenOfValsPos+storageEnodingLengthOfNumTypeOfElements*3]))
numOfUint8 := int(binary.BigEndian.Uint16(b[lenOfValsPos:]))
numOfUint16 := int(binary.BigEndian.Uint16(b[lenOfValsPos+storageEnodingLengthOfNumTypeOfElements:]))
numOfUint32 := int(binary.BigEndian.Uint16(b[lenOfValsPos+storageEnodingLengthOfNumTypeOfElements*2:]))
lenOfValsPos += storageEnodingLengthOfNumTypeOfElements * 3
valuesPos := lenOfValsPos +
uint32(numOfUint8) +
uint32(numOfUint16*2) +
uint32(numOfUint32*4)
valuesPos := lenOfValsPos + numOfUint8 + numOfUint16*2 + numOfUint32*4
//here should be binary search too
elemLength := uint32(getNumOfBytesByLen(int(numOfUniqueItems)))
encodedAddHashID := make([]byte, elemLength)
writeKeyRow(addHashID, encodedAddHashID)
for i := uint32(0); i < numOfItems; i++ {
for i := 0; i < numOfItems; i++ {
elemStart := storageEnodingStartElem +
storageEnodingLengthOfDict +
uint32(numOfUniqueItems)*(common.HashLength) +
numOfUniqueItems*(common.HashLength) +
i*(elemLength+common.HashLength)
if !bytes.Equal(encodedAddHashID, b[elemStart:elemStart+elemLength]) {

View File

@ -3,6 +3,7 @@ package changeset
import (
"bytes"
"fmt"
"math/rand"
"reflect"
"sort"
"strconv"
@ -17,7 +18,7 @@ const (
defaultIncarnation = 1
)
func TestEncodingStorageWithoutNotDefaultIncarnation(t *testing.T) {
func TestEncodingStorageWithoutNotDefaultIncarnation1(t *testing.T) {
f := func(t *testing.T, numOfElements int) {
// empty StorageChangeSset first
ch := NewStorageChangeSet()
@ -84,7 +85,7 @@ func TestEncodingStorageWithtRandomIncarnation(t *testing.T) {
addrHash, _ := common.HashData([]byte("addrHash" + strconv.Itoa(i)))
key, _ := common.HashData([]byte("key" + strconv.Itoa(i)))
val, _ := common.HashData([]byte("val" + strconv.Itoa(i)))
err = ch.Add(dbutils.GenerateCompositeStorageKey(addrHash, defaultIncarnation, key), val.Bytes())
err = ch.Add(dbutils.GenerateCompositeStorageKey(addrHash, rand.Uint64(), key), val.Bytes())
if err != nil {
t.Error(err)
}
@ -150,10 +151,10 @@ func TestEncodingStorageWithoutNotDefaultIncarnationWalk(t *testing.T) {
i := 0
err = StorageChangeSetBytes(b).Walk(func(k, v []byte) error {
if !bytes.Equal(k, ch.Changes[i].Key) {
t.Error(i, "key was incorrect", k, ch.Changes[i].Key)
t.Errorf("%d key was incorrect %x %x", i, k, ch.Changes[i].Key)
}
if !bytes.Equal(v, ch.Changes[i].Value) {
t.Error(i, "val is incorrect", v, ch.Changes[i].Value)
t.Errorf("%d val is incorrect %x %x", i, v, ch.Changes[i].Value)
}
i++
return nil
@ -202,7 +203,7 @@ func TestEncodingStorageWithoutNotDefaultIncarnationFind(t *testing.T) {
t.Error(err, i)
}
if !bytes.Equal(val, v.Value) {
t.Error("not equal for ", v, val)
t.Errorf("not equal for %x %x", v, val)
}
}
}

View File

@ -110,7 +110,7 @@ func GenerateCompositeStorageKey(addressHash common.Hash, incarnation uint64, se
func GenerateStoragePrefix(addressHash common.Hash, incarnation uint64) []byte {
prefix := make([]byte, common.HashLength+8)
copy(prefix, addressHash[:])
binary.BigEndian.PutUint64(prefix[common.HashLength:], incarnation^^uint64(0))
binary.BigEndian.PutUint64(prefix[common.HashLength:], ^incarnation)
return prefix
}

View File

@ -859,6 +859,7 @@ func (tds *TrieDbState) GetBlockNr() uint64 {
}
func (tds *TrieDbState) UnwindTo(blockNr uint64) error {
//fmt.Printf("Unwind from block %d to block %d\n", tds.blockNr, blockNr)
tds.StartNewBuffer()
b := tds.currentBuffer

View File

@ -187,13 +187,16 @@ func (dsw *DbStateWriter) WriteHistory() error {
}
if debug.IsThinHistory() {
for _, change := range storageChanges.Changes {
value, err1 := dsw.tds.db.Get(dbutils.StorageHistoryBucket, change.Key)
keyNoInc := make([]byte, len(change.Key)-common.IncarnationLength)
copy(keyNoInc, change.Key[:common.HashLength])
copy(keyNoInc[common.HashLength:], change.Key[common.HashLength+common.IncarnationLength:])
value, err1 := dsw.tds.db.Get(dbutils.StorageHistoryBucket, keyNoInc)
if err1 != nil && err1 != ethdb.ErrKeyNotFound {
return fmt.Errorf("db.Get failed: %w", err1)
}
index := dbutils.WrapHistoryIndex(value)
index.Append(dsw.tds.blockNr)
if err := dsw.tds.db.Put(dbutils.StorageHistoryBucket, change.Key, *index); err != nil {
if err := dsw.tds.db.Put(dbutils.StorageHistoryBucket, keyNoInc, *index); err != nil {
return err
}
}

View File

@ -324,7 +324,7 @@ func TestMutationCommitThinHistory(t *testing.T) {
resultHash := common.BytesToHash(res)
if resultHash != v {
t.Fatal("incorrect storage history for ", addrHash.String(), v, resultHash)
t.Fatalf("incorrect storage history for %x %x %x", addrHash.String(), v, resultHash)
}
}
}

View File

@ -507,6 +507,9 @@ func (db *BoltDatabase) walkAsOfThinStorage(startkey []byte, fixedbits uint, tim
if csB == nil {
return fmt.Errorf("storageChangeBucket not found")
}
startkeyNoInc := make([]byte, len(startkey)-common.IncarnationLength)
copy(startkeyNoInc, startkey[:common.HashLength])
copy(startkeyNoInc[common.HashLength:], startkey[common.HashLength+common.IncarnationLength:])
//for storage
mainCursor := newSplitCursor(
b,
@ -518,8 +521,8 @@ func (db *BoltDatabase) walkAsOfThinStorage(startkey []byte, fixedbits uint, tim
//for historic data
historyCursor := newSplitCursor(
hB,
startkey,
fixedbits,
startkeyNoInc,
fixedbits-8*common.IncarnationLength,
common.HashLength, /* part1end */
common.HashLength+common.IncarnationLength, /* part2start */
)
@ -912,7 +915,15 @@ func BoltDBFindByHistory(tx *bolt.Tx, hBucket []byte, key []byte, timestamp uint
if hB == nil {
return nil, ErrKeyNotFound
}
v, _ := hB.Get(key)
var v []byte
if bytes.Equal(dbutils.StorageHistoryBucket, hBucket) {
keyNoInc := make([]byte, len(key)-common.IncarnationLength)
copy(keyNoInc, key[:common.HashLength])
copy(keyNoInc[common.HashLength:], key[common.HashLength+common.IncarnationLength:])
v, _ = hB.Get(keyNoInc)
} else {
v, _ = hB.Get(key)
}
index := dbutils.WrapHistoryIndex(v)
changeSetBlock, ok := index.Search(timestamp)
@ -933,9 +944,9 @@ func BoltDBFindByHistory(tx *bolt.Tx, hBucket []byte, key []byte, timestamp uint
err error
)
switch {
case debug.IsThinHistory() && bytes.Equal(dbutils.AccountsHistoryBucket, hBucket):
case bytes.Equal(dbutils.AccountsHistoryBucket, hBucket):
data, err = changeset.AccountChangeSetBytes(changeSetData).FindLast(key)
case debug.IsThinHistory() && bytes.Equal(dbutils.StorageHistoryBucket, hBucket):
case bytes.Equal(dbutils.StorageHistoryBucket, hBucket):
data, err = changeset.StorageChangeSetBytes(changeSetData).Find(key[:common.HashLength], key[common.HashLength+common.IncarnationLength:])
default:
data, err = changeset.FindLast(changeSetData, key)