store code bytes in ipfs blockstore table

This commit is contained in:
Ian Norden 2020-07-31 00:31:34 -05:00
parent 4756f23f76
commit b8a0923250
3 changed files with 36 additions and 1 deletions

2
go.mod
View File

@ -4,6 +4,8 @@ go 1.13
require ( require (
github.com/ethereum/go-ethereum v1.9.11 github.com/ethereum/go-ethereum v1.9.11
github.com/ipfs/go-ipfs-blockstore v1.0.0
github.com/ipfs/go-ipfs-ds-help v1.0.0
github.com/multiformats/go-multihash v0.0.13 github.com/multiformats/go-multihash v0.0.13
github.com/sirupsen/logrus v1.6.0 github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v1.0.0 github.com/spf13/cobra v1.0.0

View File

@ -19,6 +19,8 @@ import (
"bytes" "bytes"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ipfs/go-ipfs-blockstore"
"github.com/ipfs/go-ipfs-ds-help"
"github.com/multiformats/go-multihash" "github.com/multiformats/go-multihash"
"github.com/vulcanize/ipfs-blockchain-watcher/pkg/ipfs/ipld" "github.com/vulcanize/ipfs-blockchain-watcher/pkg/ipfs/ipld"
@ -36,6 +38,7 @@ func NewPublisher(db *postgres.DB) *Publisher {
} }
} }
// PublishHeader writes the header to the ipfs backing pg datastore and adds secondary indexes in the header_cids table
func (p *Publisher) PublishHeader(header *types.Header) (int64, error) { func (p *Publisher) PublishHeader(header *types.Header) (int64, error) {
headerNode, err := ipld.NewEthHeader(header) headerNode, err := ipld.NewEthHeader(header)
if err != nil { if err != nil {
@ -69,6 +72,7 @@ func (p *Publisher) PublishHeader(header *types.Header) (int64, error) {
return headerID, err return headerID, err
} }
// PublishStateNode writes the state node to the ipfs backing datastore and adds secondary indexes in the state_cids table
func (p *Publisher) PublishStateNode(node Node, 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
@ -101,6 +105,7 @@ func (p *Publisher) PublishStateNode(node Node, headerID int64) (int64, error) {
return stateID, err return stateID, err
} }
// PublishStorageNode writes the storage node to the ipfs backing pg datastore and adds secondary indexes in the storage_cids table
func (p *Publisher) PublishStorageNode(node Node, stateID int64) error { func (p *Publisher) PublishStorageNode(node Node, stateID int64) error {
var storageKey string var storageKey string
if !bytes.Equal(node.Key.Bytes(), nullHash.Bytes()) { if !bytes.Equal(node.Key.Bytes(), nullHash.Bytes()) {
@ -130,3 +135,20 @@ func (p *Publisher) PublishStorageNode(node Node, stateID int64) error {
stateID, storageKey, storageCIDStr, node.Path, node.NodeType, false, mhKey) stateID, storageKey, storageCIDStr, node.Path, node.NodeType, false, mhKey)
return err return err
} }
// PublishCode writes code to the ipfs backing pg datastore
func (p *Publisher) PublishCode(code []byte) error {
// no codec for code, doesn't matter though since blockstore key is multihash-derived
return p.publishRaw(ipld.MEthStorageTrie, multihash.KECCAK_256, code)
}
func (p *Publisher) publishRaw(codec, mh uint64, raw []byte) error {
c, err := ipld.RawdataToCid(codec, raw, mh)
if err != nil {
return err
}
dbKey := dshelp.MultihashToDsKey(c.Hash())
prefixedKey := blockstore.BlockPrefix.String() + dbKey.String()
_, err = p.db.Exec(`INSERT INTO public.blocks (key, data) VALUES ($1, $2) ON CONFLICT (key) DO NOTHING`, prefixedKey, raw)
return err
}

View File

@ -35,6 +35,7 @@ import (
var ( var (
nullHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") nullHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")
emptyNode, _ = rlp.EncodeToBytes([]byte{}) emptyNode, _ = rlp.EncodeToBytes([]byte{})
emptyCodeHash = crypto.Keccak256([]byte{})
emptyContractRoot = crypto.Keccak256Hash(emptyNode) emptyContractRoot = crypto.Keccak256Hash(emptyNode)
) )
@ -136,7 +137,7 @@ func (s *Service) createSnapshot(it trie.NodeIterator, trieDB *trie.Database, he
} }
switch ty { switch ty {
case Leaf: case Leaf:
// if the node is a leaf, decode the account and if publish the associated storage trie nodes if there are any // if the node is a leaf, decode the account and publish the associated storage trie nodes if there are any
var account state.Account var account state.Account
if err := rlp.DecodeBytes(nodeElements[1].([]byte), &account); err != nil { if err := rlp.DecodeBytes(nodeElements[1].([]byte), &account); err != nil {
return fmt.Errorf("error decoding account for leaf node at path %x nerror: %v", nodePath, err) return fmt.Errorf("error decoding account for leaf node at path %x nerror: %v", nodePath, err)
@ -150,6 +151,16 @@ func (s *Service) createSnapshot(it trie.NodeIterator, trieDB *trie.Database, he
if err != nil { if err != nil {
return err return err
} }
// publish any non-nil code referenced by codehash
if !bytes.Equal(account.CodeHash, emptyCodeHash) {
codeBytes, err := s.ethDB.Get(account.CodeHash)
if err != nil {
return err
}
if err := s.ipfsPublisher.PublishCode(codeBytes); 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 storage snapshot for account %+v\r\nerror: %v", account, err) return fmt.Errorf("failed building storage snapshot for account %+v\r\nerror: %v", account, err)
} }