Skip to content

Commit 45e8f07

Browse files
WIP - writing state diff to a CSV
1 parent 097a907 commit 45e8f07

File tree

3 files changed

+355
-40
lines changed

3 files changed

+355
-40
lines changed

statediff/config.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ type Config struct {
3030
type StateDiffMode int
3131

3232
const (
33-
IPLD StateDiffMode = iota
33+
CSV StateDiffMode = iota
34+
IPLD
3435
LDB
3536
SQL
3637
)
@@ -42,6 +43,8 @@ func (mode StateDiffMode) IsValid() bool {
4243
// String implements the stringer interface.
4344
func (mode StateDiffMode) String() string {
4445
switch mode {
46+
case CSV:
47+
return "csv"
4548
case IPLD:
4649
return "ipfs"
4750
case LDB:
@@ -55,6 +58,8 @@ func (mode StateDiffMode) String() string {
5558

5659
func (mode StateDiffMode) MarshalText() ([]byte, error) {
5760
switch mode {
61+
case CSV:
62+
return []byte("ipfs"), nil
5863
case IPLD:
5964
return []byte("ipfs"), nil
6065
case LDB:
@@ -68,6 +73,8 @@ func (mode StateDiffMode) MarshalText() ([]byte, error) {
6873

6974
func (mode *StateDiffMode) UnmarshalText(text []byte) error {
7075
switch string(text) {
76+
case "csv":
77+
*mode = CSV
7178
case "ipfs":
7279
*mode = IPLD
7380
case "ldb":

statediff/publisher.go

Lines changed: 141 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,44 +20,166 @@
2020
package statediff
2121

2222
import (
23-
"errors"
24-
"github.com/ethereum/go-ethereum/statediff/ipfs"
23+
"os"
24+
"encoding/csv"
25+
"time"
26+
"strconv"
27+
"strings"
2528
)
2629

2730
type Publisher interface {
2831
PublishStateDiff(sd *StateDiff) (string, error)
2932
}
3033

3134
type publisher struct {
32-
ipfs.DagPutter
33-
Config
35+
Config Config
3436
}
3537

36-
func NewPublisher(config Config) (*publisher, error) {
37-
adder, err := ipfs.NewAdder(config.Path)
38-
if err != nil {
39-
return nil, err
38+
var (
39+
Headers = []string{
40+
"blockNumber", "blockHash", "accountAction",
41+
"code", "codeHash",
42+
"oldNonceValue", "newNonceValue",
43+
"oldBalanceValue", "newBalanceValue",
44+
"oldContractRoot", "newContractRoot",
45+
"storageDiffPaths",
4046
}
4147

48+
timeStampFormat = "20060102150405.00000"
49+
deletedAccountAction = "deleted"
50+
createdAccountAction = "created"
51+
updatedAccountAction = "updated"
52+
)
53+
54+
func NewPublisher(config Config) (*publisher, error) {
4255
return &publisher{
43-
DagPutter: ipfs.NewDagPutter(adder),
4456
Config: config,
4557
}, nil
4658
}
4759

4860
func (p *publisher) PublishStateDiff(sd *StateDiff) (string, error) {
49-
switch p.Mode {
50-
case IPLD:
51-
cidStr, err := p.DagPut(sd)
61+
switch p.Config.Mode {
62+
case CSV:
63+
return "", p.publishStateDiffToCSV(*sd)
64+
default:
65+
return "", p.publishStateDiffToCSV(*sd)
66+
}
67+
}
68+
69+
func (p *publisher) publishStateDiffToCSV(sd StateDiff) error {
70+
now := time.Now()
71+
timeStamp := now.Format(timeStampFormat)
72+
filePath := p.Config.Path + timeStamp + ".csv"
73+
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
74+
if err != nil {
75+
return err
76+
}
77+
defer file.Close()
78+
79+
writer := csv.NewWriter(file)
80+
defer writer.Flush()
81+
82+
var data [][]string
83+
data = append(data, Headers)
84+
for _, row := range accumulateCreatedAccountRows(sd) {
85+
data = append(data, row)
86+
}
87+
for _, row := range accumulateUpdatedAccountRows(sd) {
88+
data = append(data, row)
89+
}
90+
91+
for _, row := range accumulateDeletedAccountRows(sd) {
92+
data = append(data, row)
93+
}
94+
95+
for _, value := range data{
96+
err := writer.Write(value)
5297
if err != nil {
53-
return "", err
98+
return err
5499
}
100+
}
55101

56-
return cidStr, err
57-
case LDB:
58-
case SQL:
59-
default:
102+
return nil
103+
}
104+
105+
func accumulateUpdatedAccountRows(sd StateDiff) [][]string {
106+
var updatedAccountRows [][]string
107+
for _, accountDiff := range sd.UpdatedAccounts {
108+
formattedAccountData := formatAccountDiffIncremental(accountDiff, sd, updatedAccountAction)
109+
110+
updatedAccountRows = append(updatedAccountRows, formattedAccountData)
111+
}
112+
113+
return updatedAccountRows
114+
}
115+
116+
func accumulateDeletedAccountRows(sd StateDiff) [][]string {
117+
var deletedAccountRows [][]string
118+
for _, accountDiff := range sd.DeletedAccounts {
119+
formattedAccountData := formatAccountDiffEventual(accountDiff, sd, deletedAccountAction)
120+
121+
deletedAccountRows = append(deletedAccountRows, formattedAccountData)
122+
}
123+
124+
return deletedAccountRows
125+
}
126+
127+
func accumulateCreatedAccountRows(sd StateDiff) [][]string {
128+
var createdAccountRows [][]string
129+
for _, accountDiff := range sd.CreatedAccounts {
130+
formattedAccountData := formatAccountDiffEventual(accountDiff, sd, createdAccountAction)
131+
132+
createdAccountRows = append(createdAccountRows, formattedAccountData)
60133
}
61134

62-
return "", errors.New("state diff publisher: unhandled publishing mode")
63-
}
135+
return createdAccountRows
136+
}
137+
138+
func formatAccountDiffEventual(accountDiff AccountDiffEventual, sd StateDiff, accountAction string) []string {
139+
oldContractRoot := accountDiff.ContractRoot.OldValue
140+
newContractRoot := accountDiff.ContractRoot.NewValue
141+
var storageDiffPaths []string
142+
for k := range accountDiff.Storage {
143+
storageDiffPaths = append(storageDiffPaths, k)
144+
}
145+
formattedAccountData := []string{
146+
strconv.FormatInt(sd.BlockNumber, 10),
147+
sd.BlockHash.String(),
148+
accountAction,
149+
string(accountDiff.Code),
150+
accountDiff.CodeHash,
151+
strconv.FormatUint(*accountDiff.Nonce.OldValue, 10),
152+
strconv.FormatUint(*accountDiff.Nonce.NewValue, 10),
153+
accountDiff.Balance.OldValue.String(),
154+
accountDiff.Balance.NewValue.String(),
155+
*oldContractRoot,
156+
*newContractRoot,
157+
strings.Join(storageDiffPaths, ","),
158+
}
159+
return formattedAccountData
160+
}
161+
162+
func formatAccountDiffIncremental(accountDiff AccountDiffIncremental, sd StateDiff, accountAction string) []string {
163+
oldContractRoot := accountDiff.ContractRoot.OldValue
164+
newContractRoot := accountDiff.ContractRoot.NewValue
165+
var storageDiffPaths []string
166+
for k := range accountDiff.Storage {
167+
storageDiffPaths = append(storageDiffPaths, k)
168+
}
169+
formattedAccountData := []string{
170+
strconv.FormatInt(sd.BlockNumber, 10),
171+
sd.BlockHash.String(),
172+
accountAction,
173+
"",
174+
accountDiff.CodeHash,
175+
strconv.FormatUint(*accountDiff.Nonce.OldValue, 10),
176+
strconv.FormatUint(*accountDiff.Nonce.NewValue, 10),
177+
accountDiff.Balance.OldValue.String(),
178+
accountDiff.Balance.NewValue.String(),
179+
*oldContractRoot,
180+
*newContractRoot,
181+
strings.Join(storageDiffPaths, ","),
182+
}
183+
return formattedAccountData
184+
}
185+

0 commit comments

Comments
 (0)