107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
package compliance
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
|
|
"github.com/ethereum/go-ethereum/core"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
"github.com/cerc-io/eth-statediff-compliance/internal/statediff"
|
|
)
|
|
|
|
// arg 0 is filename
|
|
func WriteDiffs(outputDir string,
|
|
chain *core.BlockChain,
|
|
blocks []*types.Block,
|
|
) {
|
|
sdb := chain.StateCache()
|
|
builder := statediff.MakeBuilder(sdb)
|
|
|
|
// For each block, run the builder and output to a file
|
|
for i, block := range blocks {
|
|
args := statediff.Args{
|
|
NewStateRoot: block.Root(),
|
|
BlockNumber: block.Number(),
|
|
BlockHash: block.Hash(),
|
|
}
|
|
if i != 0 {
|
|
args.OldStateRoot = blocks[i-1].Root()
|
|
}
|
|
|
|
diff, err := builder.BuildStateDiffObject(args, statediff.Params{})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
writeDiff(outputDir, i, &diff)
|
|
}
|
|
}
|
|
|
|
// Sorts contained state nodes, storage nodes, and IPLDs
|
|
// Outputs them to respective files in given dir
|
|
func writeDiff(outputDir string, number int, diff *statediff.StateObject) {
|
|
sort.Slice(diff.IPLDs, func(i, j int) bool {
|
|
return diff.IPLDs[i].CID < diff.IPLDs[j].CID
|
|
})
|
|
sort.Slice(diff.Nodes, func(i, j int) bool {
|
|
return bytes.Compare(
|
|
diff.Nodes[i].AccountWrapper.LeafKey,
|
|
diff.Nodes[j].AccountWrapper.LeafKey,
|
|
) < 0
|
|
})
|
|
for _, node := range diff.Nodes {
|
|
sort.Slice(node.StorageDiff, func(i, j int) bool {
|
|
return bytes.Compare(
|
|
node.StorageDiff[i].LeafKey,
|
|
node.StorageDiff[j].LeafKey,
|
|
) < 0
|
|
})
|
|
}
|
|
|
|
// open file and dump sorted node CIDs
|
|
ipldsPath := filepath.Join(outputDir, fmt.Sprintf("%d_diff.txt", number))
|
|
f, err := os.Create(ipldsPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer f.Close()
|
|
for _, item := range diff.IPLDs {
|
|
s := fmt.Sprintf("ipld,%s,%x\n",
|
|
item.CID,
|
|
item.Content,
|
|
)
|
|
if _, err = f.WriteString(s); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
for _, item := range diff.Nodes {
|
|
s := fmt.Sprintf("state,%s,%x,%t,%v,%v,%s,%x\n",
|
|
item.AccountWrapper.CID,
|
|
item.AccountWrapper.LeafKey,
|
|
item.Removed,
|
|
item.AccountWrapper.Account.Nonce,
|
|
item.AccountWrapper.Account.Balance,
|
|
item.AccountWrapper.Account.Root,
|
|
item.AccountWrapper.Account.CodeHash,
|
|
)
|
|
if _, err = f.WriteString(s); err != nil {
|
|
panic(err)
|
|
}
|
|
for _, storage := range item.StorageDiff {
|
|
s := fmt.Sprintf("storage,%s,%x,%t,%x\n",
|
|
storage.CID,
|
|
storage.LeafKey,
|
|
storage.Removed,
|
|
storage.Value,
|
|
)
|
|
if _, err = f.WriteString(s); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
}
|
|
}
|