Skip to content

Instantly share code, notes, and snippets.

@bas-vk
Created January 3, 2017 11:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bas-vk/299f4a686b66a22cf87302c561ee5866 to your computer and use it in GitHub Desktop.
Save bas-vk/299f4a686b66a22cf87302c561ee5866 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"fmt"
"math/big"
"strings"
"time"
"encoding/json"
set "github.com/deckarep/golang-set"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethclient"
)
var (
ENSTEmporaryHashRegistryABI = `[{"constant":false,"inputs":[{"name":"_hash","type":"bytes32"}],"name":"releaseDeed","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"unhashedName","type":"string"}],"name":"invalidateName","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"bytes32"},{"name":"owner","type":"address"},{"name":"value","type":"uint256"},{"name":"salt","type":"bytes32"}],"name":"shaBid","outputs":[{"name":"sealedBid","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"entries","outputs":[{"name":"status","type":"uint8"},{"name":"deed","type":"address"},{"name":"registrationDate","type":"uint256"},{"name":"value","type":"uint256"},{"name":"highestBid","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"ens","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_hash","type":"bytes32"}],"name":"transferRegistrars","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"sealedBids","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_hash","type":"bytes32"},{"name":"newOwner","type":"address"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_hash","type":"bytes32"}],"name":"finalizeAuction","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_hash","type":"bytes32"},{"name":"_owner","type":"address"},{"name":"_value","type":"uint256"},{"name":"_salt","type":"bytes32"}],"name":"unsealBid","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"registryCreated","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"sealedBid","type":"bytes32"}],"name":"newBid","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"seal","type":"bytes32"}],"name":"cancelBid","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_hashes","type":"bytes32[]"}],"name":"startAuctions","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_hash","type":"bytes32"}],"name":"startAuction","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"rootNode","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"inputs":[{"name":"_ens","type":"address"},{"name":"_rootNode","type":"bytes32"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"bytes32"},{"indexed":false,"name":"auctionExpiryDate","type":"uint256"}],"name":"AuctionStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"bytes32"},{"indexed":false,"name":"deposit","type":"uint256"}],"name":"NewBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"status","type":"uint8"}],"name":"BidRevealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"now","type":"uint256"}],"name":"HashRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"bytes32"},{"indexed":false,"name":"value","type":"uint256"}],"name":"HashReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"hash","type":"bytes32"},{"indexed":true,"name":"name","type":"string"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"now","type":"uint256"}],"name":"HashInvalidated","type":"event"}]`
ENSContractAddress = common.HexToAddress("c68de5b43c3d980b0c110a77a5f78d3c4c4d63b4")
rpcTimeout = 60 * time.Second
)
// Helper type that makes logs from the AuctionStarted event comparable.
// event AuctionStarted(bytes32 indexed hash, uint auctionExpiryDate);
type AuctionStartedLog struct {
Address common.Address
Topics [2]common.Hash
Data [32]byte
BlockNumber uint64
TxHash common.Hash
TxIndex uint
BlockHash common.Hash
Index uint
Removed bool
}
func (l AuctionStartedLog) MarshalJSON() ([]byte, error) {
fields := make(map[string]interface{})
fields["address"] = l.Address
fields["topics"] = l.Topics
fields["data"] = hexutil.Encode(l.Data[:])
fields["txIndex"] = l.TxIndex
fields["txHash"] = l.TxHash
fields["index"] = l.Index
fields["removed"] = l.Removed
if (l.BlockHash != common.Hash{}) {
fields["blockHash"] = l.BlockHash
fields["blockNumber"] = l.BlockNumber
}
return json.Marshal(fields)
}
func convert(vmlogs []vm.Log) []interface{} {
logs := make([]interface{}, len(vmlogs))
for i, log := range vmlogs {
if len(log.Topics) != 2 {
panic("Invalid number of topics")
}
l := AuctionStartedLog{
Address: log.Address,
BlockNumber: log.BlockNumber,
TxHash: log.TxHash,
TxIndex: log.TxIndex,
BlockHash: log.BlockHash,
Index: log.Index,
Removed: log.Removed,
}
l.Topics[0], l.Topics[1] = log.Topics[0], log.Topics[1]
copy(l.Data[:], log.Data)
logs[i] = l
}
return logs
}
func fetchLogs(client *ethclient.Client, fromBlock, toBlock *big.Int) []interface{} {
ensABI, err := abi.JSON(strings.NewReader(ENSTEmporaryHashRegistryABI))
if err != nil {
panic(err)
}
eventTopicId := ensABI.Events["AuctionStarted"].Id()
q := ethereum.FilterQuery{
FromBlock: fromBlock,
ToBlock: toBlock,
Addresses: []common.Address{ENSContractAddress},
Topics: [][]common.Hash{[]common.Hash{eventTopicId}},
}
ctx, _ := context.WithTimeout(context.Background(), rpcTimeout)
vmlogs, err := client.FilterLogs(ctx, q)
if err != nil {
panic(err)
}
return convert(vmlogs)
}
func main() {
client, err := ethclient.Dial("http://localhost:8545")
if err != nil {
panic(err)
}
fromBlock, toBlock := big.NewInt(25461), big.NewInt(275836)
// geth --testnet --rpc
gethLogs := set.NewSetFromSlice(fetchLogs(client, fromBlock, toBlock))
//parity --testnet --port 31313 --jsonrpc-port 8546
client, err = ethclient.Dial("http://localhost:8546")
if err != nil {
panic(err)
}
parityLogs := set.NewSetFromSlice(fetchLogs(client, fromBlock, toBlock))
inBoth := gethLogs.Intersect(parityLogs)
gethUnique := gethLogs.Difference(inBoth)
parityUnique := parityLogs.Difference(inBoth)
fmt.Printf(" geth logs: %d\n", gethLogs.Cardinality())
fmt.Printf(" parity logs: %d\n", parityLogs.Cardinality())
fmt.Printf(" unique geth logs: %d\n", gethUnique.Cardinality())
fmt.Printf("unique parity logs: %d\n", parityUnique.Cardinality())
fmt.Println("Unique Geth logs:")
it := gethUnique.Iterator()
for elem := range it.C {
serialized, _ := json.Marshal(elem)
fmt.Printf("%s\n", serialized)
}
fmt.Println()
fmt.Println("Unique Parity logs:")
it = parityUnique.Iterator()
for elem := range it.C {
serialized, _ := json.Marshal(elem)
fmt.Printf("%s\n", serialized)
}
fmt.Println()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment