finish snapshot extractor

This commit is contained in:
Ian Norden 2020-07-01 18:07:56 -05:00
parent 83d5b6491f
commit 5cb67910bd
3 changed files with 59 additions and 28 deletions

View File

@ -15,17 +15,29 @@
package snapshot package snapshot
import "fmt" import (
"fmt"
"github.com/ethereum/go-ethereum/common"
)
// Node for holding trie node information
type Node struct {
NodeType NodeType
Path []byte
Key common.Hash
Value []byte
}
// NodeType for explicitly setting type of node // NodeType for explicitly setting type of node
type NodeType string type NodeType int
const ( const (
Unknown NodeType = "Unknown" Branch NodeType = iota
Leaf NodeType = "Leaf" Extension
Extension NodeType = "Extension" Leaf
Branch NodeType = "Branch" Removed
Removed NodeType = "Removed" // used to represent pathes which have been emptied Unknown
) )
// CheckKeyType checks what type of key we have // CheckKeyType checks what type of key we have

View File

@ -16,10 +16,11 @@
package snapshot package snapshot
import ( import (
"bytes"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
"github.com/vulcanize/ipfs-blockchain-watcher/pkg/eth"
"github.com/vulcanize/ipfs-blockchain-watcher/pkg/ipfs/ipld" "github.com/vulcanize/ipfs-blockchain-watcher/pkg/ipfs/ipld"
"github.com/vulcanize/ipfs-blockchain-watcher/pkg/postgres" "github.com/vulcanize/ipfs-blockchain-watcher/pkg/postgres"
"github.com/vulcanize/ipfs-blockchain-watcher/pkg/shared" "github.com/vulcanize/ipfs-blockchain-watcher/pkg/shared"
@ -67,11 +68,11 @@ func (p *Publisher) PublishHeader(header *types.Header) (int64, error) {
return headerID, err return headerID, err
} }
func (p *Publisher) PublishStateNode(meta eth.StateNodeModel, nodeVal []byte, headerID int64) (int64, error) { func (p *Publisher) PublishStateNode(node Node, headerID int64) (int64, error) {
var stateID int64 var stateID int64
var stateKey string var stateKey string
if meta.StateKey != nullHash.String() { if !bytes.Equal(node.Key.Bytes(), nullHash.Bytes()) {
stateKey = meta.StateKey stateKey = node.Key.Hex()
} }
tx, err := p.db.Beginx() tx, err := p.db.Beginx()
if err != nil { if err != nil {
@ -87,21 +88,21 @@ func (p *Publisher) PublishStateNode(meta eth.StateNodeModel, nodeVal []byte, he
err = tx.Commit() err = tx.Commit()
} }
}() }()
stateCIDStr, err := shared.PublishRaw(tx, ipld.MEthStateTrie, multihash.KECCAK_256, nodeVal) stateCIDStr, err := shared.PublishRaw(tx, ipld.MEthStateTrie, multihash.KECCAK_256, node.Value)
if err != nil { if err != nil {
return 0, err return 0, err
} }
err = tx.QueryRowx(`INSERT INTO eth.state_cids (header_id, state_leaf_key, cid, state_path, node_type, diff) VALUES ($1, $2, $3, $4, $5, $6) err = tx.QueryRowx(`INSERT INTO eth.state_cids (header_id, state_leaf_key, cid, state_path, node_type, diff) VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (header_id, state_path, diff) DO UPDATE SET (state_leaf_key, cid, node_type) = ($2, $3, $5, $6) ON CONFLICT (header_id, state_path, diff) DO UPDATE SET (state_leaf_key, cid, node_type) = ($2, $3, $5, $6)
RETURNING id`, RETURNING id`,
headerID, stateKey, stateCIDStr, meta.Path, meta.NodeType, false).Scan(&stateID) headerID, stateKey, stateCIDStr, node.Path, node.NodeType, false).Scan(&stateID)
return stateID, err return stateID, err
} }
func (p *Publisher) PublishStorageNode(meta eth.StorageNodeModel, nodeVal []byte, stateID int64) error { func (p *Publisher) PublishStorageNode(node Node, stateID int64) error {
var storageKey string var storageKey string
if meta.StorageKey != nullHash.String() { if !bytes.Equal(node.Key.Bytes(), nullHash.Bytes()) {
storageKey = meta.StorageKey storageKey = node.Key.Hex()
} }
tx, err := p.db.Beginx() tx, err := p.db.Beginx()
if err != nil { if err != nil {
@ -117,12 +118,12 @@ func (p *Publisher) PublishStorageNode(meta eth.StorageNodeModel, nodeVal []byte
err = tx.Commit() err = tx.Commit()
} }
}() }()
storageCIDStr, err := shared.PublishRaw(tx, ipld.MEthStorageTrie, multihash.KECCAK_256, nodeVal) storageCIDStr, err := shared.PublishRaw(tx, ipld.MEthStorageTrie, multihash.KECCAK_256, node.Value)
if err != nil { if err != nil {
return err return err
} }
_, err = tx.Exec(`INSERT INTO eth.storage_cids (state_id, storage_leaf_key, cid, storage_path, node_type, diff) VALUES ($1, $2, $3, $4, $5, $6) _, err = tx.Exec(`INSERT INTO eth.storage_cids (state_id, storage_leaf_key, cid, storage_path, node_type, diff) VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (state_id, storage_path) DO UPDATE SET (storage_leaf_key, cid, node_type, diff) = ($2, $3, $5, $6)`, ON CONFLICT (state_id, storage_path) DO UPDATE SET (storage_leaf_key, cid, node_type, diff) = ($2, $3, $5, $6)`,
stateID, storageKey, storageCIDStr, meta.Path, meta.NodeType, false) stateID, storageKey, storageCIDStr, node.Path, node.NodeType, false)
return err return err
} }

View File

@ -17,6 +17,7 @@ package snapshot
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -28,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/vulcanize/ipfs-blockchain-watcher/pkg/eth"
"github.com/vulcanize/ipfs-blockchain-watcher/pkg/postgres" "github.com/vulcanize/ipfs-blockchain-watcher/pkg/postgres"
) )
@ -98,6 +98,11 @@ func (s *Service) createSnapshot(it trie.NodeIterator, trieDB *trie.Database, he
if err != nil { if err != nil {
return err return err
} }
stateNode := Node{
NodeType: ty,
Path: nodePath,
Value: node,
}
switch ty { switch ty {
case Leaf: case Leaf:
var account state.Account var account state.Account
@ -108,18 +113,24 @@ func (s *Service) createSnapshot(it trie.NodeIterator, trieDB *trie.Database, he
valueNodePath := append(nodePath, partialPath...) valueNodePath := append(nodePath, partialPath...)
encodedPath := trie.HexToCompact(valueNodePath) encodedPath := trie.HexToCompact(valueNodePath)
leafKey := encodedPath[1:] leafKey := encodedPath[1:]
// publish state node stateNode.Key = common.BytesToHash(leafKey)
stateNode := eth.StateNodeModel{} stateID, err := s.ipfsPublisher.PublishStateNode(stateNode, headerID)
if err != nil {
return err
}
if err := s.storageSnapshot(account.Root, stateID); err != nil { if err := s.storageSnapshot(account.Root, stateID); err != nil {
return fmt.Errorf("failed building eventual storage diffs for account %+v\r\nerror: %v", account, err) return fmt.Errorf("failed building eventual storage diffs for account %+v\r\nerror: %v", account, err)
} }
case Extension, Branch: case Extension, Branch:
// publish state node stateNode.Key = common.BytesToHash([]byte{})
stateNode := eth.StateNodeModel{} if _, err := s.ipfsPublisher.PublishStateNode(stateNode, headerID); err != nil {
return err
}
default: default:
return fmt.Errorf("unexpected node type %s", ty) return errors.New("unexpected node type")
} }
} }
return nil
} }
// buildStorageNodesEventual builds the storage diff node objects for a created account // buildStorageNodesEventual builds the storage diff node objects for a created account
@ -157,18 +168,25 @@ func (s *Service) storageSnapshot(sr common.Hash, stateID int64) error {
if err != nil { if err != nil {
return err return err
} }
storageNode := Node{
NodeType: ty,
Path: nodePath,
Value: node,
}
switch ty { switch ty {
case Leaf: case Leaf:
partialPath := trie.CompactToHex(nodeElements[0].([]byte)) partialPath := trie.CompactToHex(nodeElements[0].([]byte))
valueNodePath := append(nodePath, partialPath...) valueNodePath := append(nodePath, partialPath...)
encodedPath := trie.HexToCompact(valueNodePath) encodedPath := trie.HexToCompact(valueNodePath)
leafKey := encodedPath[1:] leafKey := encodedPath[1:]
storageNode := eth.StorageNodeModel{} storageNode.Key = common.BytesToHash(leafKey)
case Extension, Branch: case Extension, Branch:
storageNode := eth.StorageNodeModel{} storageNode.Key = common.BytesToHash([]byte{})
default: default:
return fmt.Errorf("unexpected node type %s", ty) return errors.New("unexpected node type")
}
if err := s.ipfsPublisher.PublishStorageNode(storageNode, stateID); err != nil {
return err
} }
} }
return nil return nil