Add vat_move transformer (#47)

* Add vat_move transformer base

* Add vat_move migrations

* Add test data for vat_move

* Add vat_move transformer to initialisers

* Add numeric cast to psql insert of Rad

* Add new db schema

* Dependency update

* Expand abbreviation in repository

* Add test suite for vat_move

* Add header checking to transformer and mock repository

* Remove trailing zero in test data

* Fix minor mishaps

* Go fmt nitpicking

* Refactoring in tests

* Add tests covering checked headers stuff (and fix revealed bugs)

* go fmt fixes

* Implement batching behaviour of transformer

* Small fixes after review

* Go fmt
This commit is contained in:
Edvard Hübinette 2018-10-12 16:13:13 +02:00 committed by GitHub
parent 8fe92edd26
commit be58dd4ac8
23 changed files with 1163 additions and 19 deletions

155
Gopkg.lock generated
View File

@ -3,23 +3,30 @@
[[projects]]
branch = "master"
digest = "1:a313376bcbcce8ae8bddb8089a7293e0473a0f8e9e3710d6244e09e81875ccf0"
name = "github.com/aristanetworks/goarista"
packages = ["monotime"]
pruneopts = ""
revision = "ff33da284e760fcdb03c33d37a719e5ed30ba844"
[[projects]]
branch = "master"
digest = "1:c6bf1ac7bbc0fe51637bf54d5a88ff79b171b3b42dbc665dec98303c862d8662"
name = "github.com/btcsuite/btcd"
packages = ["btcec"]
pruneopts = ""
revision = "cff30e1d23fc9e800b2b5b4b41ef1817dda07e9f"
[[projects]]
digest = "1:aaeffbff5bd24654cb4c190ed75d6c7b57b4f5d6741914c1a7a6bb7447e756c5"
name = "github.com/deckarep/golang-set"
packages = ["."]
pruneopts = ""
revision = "cbaa98ba5575e67703b32b4b19f73c91f3c4159e"
version = "v1.7.1"
[[projects]]
digest = "1:8acdd83e35b407d026e546bf4d18cc778e9604433d03d468eccca62b9c51c718"
name = "github.com/ethereum/go-ethereum"
packages = [
".",
@ -50,42 +57,54 @@
"params",
"rlp",
"rpc",
"trie"
"trie",
]
pruneopts = ""
revision = "89451f7c382ad2185987ee369f16416f89c28a7d"
version = "v1.8.15"
[[projects]]
digest = "1:eb53021a8aa3f599d29c7102e65026242bdedce998a54837dc67f14b6a97c5fd"
name = "github.com/fsnotify/fsnotify"
packages = ["."]
pruneopts = ""
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
version = "v1.4.7"
[[projects]]
digest = "1:a01080d20c45c031c13f3828c56e58f4f51d926a482ad10cc0316225097eb7ea"
name = "github.com/go-stack/stack"
packages = ["."]
pruneopts = ""
revision = "2fee6af1a9795aafbe0253a0cfbdf668e1fb8a9a"
version = "v1.8.0"
[[projects]]
digest = "1:3dd078fda7500c341bc26cfbc6c6a34614f295a2457149fc1045cab767cbcf18"
name = "github.com/golang/protobuf"
packages = ["proto"]
pruneopts = ""
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:2a5888946cdbc8aa360fd43301f9fc7869d663f60d5eedae7d4e6e5e4f06f2bf"
name = "github.com/golang/snappy"
packages = ["."]
pruneopts = ""
revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a"
[[projects]]
digest = "1:5247b135b5492aa232a731acdcb52b08f32b874cb398f21ab460396eadbe866b"
name = "github.com/google/uuid"
packages = ["."]
pruneopts = ""
revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494"
version = "v1.0.0"
[[projects]]
digest = "1:d14365c51dd1d34d5c79833ec91413bfbb166be978724f15701e17080dc06dec"
name = "github.com/hashicorp/hcl"
packages = [
".",
@ -97,25 +116,29 @@
"hcl/token",
"json/parser",
"json/scanner",
"json/token"
"json/token",
]
pruneopts = ""
revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241"
version = "v1.0.0"
[[projects]]
digest = "1:b3c5b95e56c06f5aa72cb2500e6ee5f44fcd122872d4fec2023a488e561218bc"
name = "github.com/hpcloud/tail"
packages = [
".",
"ratelimiter",
"util",
"watch",
"winfile"
"winfile",
]
pruneopts = ""
revision = "a30252cb686a21eb2d0b98132633053ec2f7f1e5"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:b6e4cc26365c004808649862e22069de09594a9222143399a7a04904e9f7018c"
name = "github.com/huin/goupnp"
packages = [
".",
@ -124,59 +147,75 @@
"httpu",
"scpd",
"soap",
"ssdp"
"ssdp",
]
pruneopts = ""
revision = "1395d1447324cbea88d249fbfcfd70ea878fdfca"
[[projects]]
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
pruneopts = ""
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
digest = "1:76f836364ae83ed811c415aa92e1209ce49de9f62aad85b85fca749a8b96a110"
name = "github.com/jackpal/go-nat-pmp"
packages = ["."]
pruneopts = ""
revision = "c9cfead9f2a36ddf3daa40ba269aa7f4bbba6b62"
version = "v1.0.1"
[[projects]]
branch = "master"
digest = "1:617ee2434b77e911fa26b678730be9a617f75243b194eadc8201c8ac860844aa"
name = "github.com/jmoiron/sqlx"
packages = [
".",
"reflectx"
"reflectx",
]
pruneopts = ""
revision = "0dae4fefe7c0e190f7b5a78dac28a1c82cc8d849"
[[projects]]
branch = "master"
digest = "1:29145d7af4adafd72a79df5e41456ac9e232d5a28c1cd4dacf3ff008a217fc10"
name = "github.com/lib/pq"
packages = [
".",
"oid"
"oid",
]
pruneopts = ""
revision = "4ded0e9383f75c197b3a2aaa6d590ac52df6fd79"
version = "v1.0.0"
[[projects]]
digest = "1:961dc3b1d11f969370533390fdf203813162980c858e1dabe827b60940c909a5"
name = "github.com/magiconair/properties"
packages = ["."]
pruneopts = ""
revision = "c2353362d570a7bfa228149c62842019201cfb71"
version = "v1.8.0"
[[projects]]
digest = "1:096a8a9182648da3d00ff243b88407838902b6703fc12657f76890e08d1899bf"
name = "github.com/mitchellh/go-homedir"
packages = ["."]
pruneopts = ""
revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4"
version = "v1.0.0"
[[projects]]
digest = "1:5219b4506253ccc598f9340677162a42d6a78f340a4cc6df2d62db4d0593c4e9"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
pruneopts = ""
revision = "fa473d140ef3c6adf42d6b391fe76707f1f243c8"
version = "v1.0.0"
[[projects]]
digest = "1:a7fd918fb5bd2188436785c0424f8a50b4addfedf37a2b14d796be2a927b8007"
name = "github.com/onsi/ginkgo"
packages = [
".",
@ -196,12 +235,14 @@
"reporters/stenographer",
"reporters/stenographer/support/go-colorable",
"reporters/stenographer/support/go-isatty",
"types"
"types",
]
pruneopts = ""
revision = "3774a09d95489ccaa16032e0770d08ea77ba6184"
version = "v1.6.0"
[[projects]]
digest = "1:3ecd0a37c4a90c12a97e31c398cdbc173824351aa891898ee178120bfe71c478"
name = "github.com/onsi/gomega"
packages = [
".",
@ -216,82 +257,106 @@
"matchers/support/goraph/edge",
"matchers/support/goraph/node",
"matchers/support/goraph/util",
"types"
"types",
]
pruneopts = ""
revision = "7615b9433f86a8bdf29709bf288bc4fd0636a369"
version = "v1.4.2"
[[projects]]
digest = "1:a5484d4fa43127138ae6e7b2299a6a52ae006c7f803d98d717f60abf3e97192e"
name = "github.com/pborman/uuid"
packages = ["."]
pruneopts = ""
revision = "adf5a7427709b9deb95d29d3fa8a2bf9cfd388f1"
version = "v1.2"
[[projects]]
digest = "1:894aef961c056b6d85d12bac890bf60c44e99b46292888bfa66caf529f804457"
name = "github.com/pelletier/go-toml"
packages = ["."]
pruneopts = ""
revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194"
version = "v1.2.0"
[[projects]]
digest = "1:210286d0cb60ffe28f1ca00b664029e8943009f95d06d8f8c336301b28e1aee5"
name = "github.com/philhofer/fwd"
packages = ["."]
pruneopts = ""
revision = "bb6d471dc95d4fe11e432687f8b70ff496cf3136"
version = "v1.0.0"
[[projects]]
digest = "1:7143292549152d009ca9e9c493b74736a2ebd93f921bea8a4b308d7cc5edc6b3"
name = "github.com/rjeczalik/notify"
packages = ["."]
pruneopts = ""
revision = "0f065fa99b48b842c3fd3e2c8b194c6f2b69f6b8"
version = "v0.9.1"
[[projects]]
digest = "1:78c9cf43ddeacd0e472f412082227a0fac2ae107ee60e9112156f9371f9912cf"
name = "github.com/rs/cors"
packages = ["."]
pruneopts = ""
revision = "3fb1b69b103a84de38a19c3c6ec073dd6caa4d3f"
version = "v1.5.0"
[[projects]]
digest = "1:d0431c2fd72e39ee43ea7742322abbc200c3e704c9102c5c3c2e2e667095b0ca"
name = "github.com/spf13/afero"
packages = [
".",
"mem"
"mem",
]
pruneopts = ""
revision = "d40851caa0d747393da1ffb28f7f9d8b4eeffebd"
version = "v1.1.2"
[[projects]]
digest = "1:d0b38ba6da419a6d4380700218eeec8623841d44a856bb57369c172fbf692ab4"
name = "github.com/spf13/cast"
packages = ["."]
pruneopts = ""
revision = "8965335b8c7107321228e3e3702cab9832751bac"
version = "v1.2.0"
[[projects]]
digest = "1:a1403cc8a94b8d7956ee5e9694badef0e7b051af289caad1cf668331e3ffa4f6"
name = "github.com/spf13/cobra"
packages = ["."]
pruneopts = ""
revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385"
version = "v0.0.3"
[[projects]]
digest = "1:9ceffa4ab5f7195ecf18b3a7fff90c837a9ed5e22e66d18069e4bccfe1f52aa0"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
pruneopts = ""
revision = "4a4406e478ca629068e7768fc33f3f044173c0a6"
version = "v1.0.0"
[[projects]]
digest = "1:0a52bcb568386d98f4894575d53ce3e456f56471de6897bb8b9de13c33d9340e"
name = "github.com/spf13/pflag"
packages = ["."]
pruneopts = ""
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
version = "v1.0.2"
[[projects]]
digest = "1:ac25ea6cc1156aca9611411274b4a0bdd83a623845df6985aab508253955cc66"
name = "github.com/spf13/viper"
packages = ["."]
pruneopts = ""
revision = "8fb642006536c8d3760c99d4fa2389f5e2205631"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:ce5194e5afac308cc34e500cab45b4ce88a0742d689e3cf7e37b607ad76bed2f"
name = "github.com/syndtr/goleveldb"
packages = [
"leveldb",
@ -305,53 +370,65 @@
"leveldb/opt",
"leveldb/storage",
"leveldb/table",
"leveldb/util"
"leveldb/util",
]
pruneopts = ""
revision = "ae2bd5eed72d46b28834ec3f60db3a3ebedd8dbd"
[[projects]]
digest = "1:cae65c1f3471b1f456a9d8a160440f4824ad50c718a15da4144490fbc3b12e49"
name = "github.com/tinylib/msgp"
packages = ["msgp"]
pruneopts = ""
revision = "b2b6a672cf1e5b90748f79b8b81fc8c5cf0571a1"
version = "1.0.2"
[[projects]]
branch = "master"
digest = "1:61a86f0be8b466d6e3fbdabb155aaa4006137cb5e3fd3b949329d103fa0ceb0f"
name = "golang.org/x/crypto"
packages = [
"pbkdf2",
"scrypt"
"scrypt",
]
pruneopts = ""
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c"
[[projects]]
branch = "master"
digest = "1:fbdbb6cf8db3278412c9425ad78b26bb8eb788181f26a3ffb3e4f216b314f86a"
name = "golang.org/x/net"
packages = [
"context",
"html",
"html/atom",
"html/charset",
"websocket"
"websocket",
]
pruneopts = ""
revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2"
[[projects]]
branch = "master"
digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1"
name = "golang.org/x/sync"
packages = ["errgroup"]
pruneopts = ""
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
[[projects]]
branch = "master"
digest = "1:70d519d5cddeb60ceda2db88c24c340b1b2d7efb25ab54bacb38f57ea1998df7"
name = "golang.org/x/sys"
packages = [
"unix",
"windows"
"windows",
]
pruneopts = ""
revision = "d641721ec2dead6fe5ca284096fe4b1fcd49e427"
[[projects]]
digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4"
name = "golang.org/x/text"
packages = [
"encoding",
@ -373,66 +450,108 @@
"runes",
"transform",
"unicode/cldr",
"unicode/norm"
"unicode/norm",
]
pruneopts = ""
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
branch = "master"
digest = "1:88401f863a34cfd82173ef2ad015652c2c47c866affc424bfdd4d5fafad1dd53"
name = "golang.org/x/tools"
packages = [
"go/ast/astutil",
"imports",
"internal/fastwalk"
"internal/fastwalk",
]
pruneopts = ""
revision = "90fa682c2a6e6a37b3a1364ce2fe1d5e41af9d6d"
[[projects]]
digest = "1:be560af8c72c59788a6748eae60b8e1fe136fefdf049b7dfb6f5b591ea337984"
name = "gopkg.in/DataDog/dd-trace-go.v1"
packages = [
"ddtrace",
"ddtrace/ext",
"ddtrace/internal",
"ddtrace/tracer"
"ddtrace/tracer",
]
pruneopts = ""
revision = "bcd20367df871708a36549e7fe36183ee5b4fc55"
version = "v1.3.0"
[[projects]]
digest = "1:eb53021a8aa3f599d29c7102e65026242bdedce998a54837dc67f14b6a97c5fd"
name = "gopkg.in/fsnotify.v1"
packages = ["."]
pruneopts = ""
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
source = "gopkg.in/fsnotify/fsnotify.v1"
version = "v1.4.7"
[[projects]]
branch = "v2"
digest = "1:a585c075875ab9c344f7840a927f09f3285563f7318e761a1d61d642316f2217"
name = "gopkg.in/karalabe/cookiejar.v2"
packages = ["collections/prque"]
pruneopts = ""
revision = "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57"
[[projects]]
branch = "v2"
digest = "1:4f830ee018eb8c56d0def653ad7c9a1d2a053f0cef2ac6b2200f73b98fa6a681"
name = "gopkg.in/natefinch/npipe.v2"
packages = ["."]
pruneopts = ""
revision = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6"
[[projects]]
branch = "v1"
digest = "1:a96d16bd088460f2e0685d46c39bcf1208ba46e0a977be2df49864ec7da447dd"
name = "gopkg.in/tomb.v1"
packages = ["."]
pruneopts = ""
revision = "dd632973f1e7218eb1089048e0798ec9ae7dceb8"
[[projects]]
digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = ""
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "fe44a35c252e3af131cb6073e683761afa0f3aa0f2d49d468520bfd6e453c5f8"
input-imports = [
"github.com/ethereum/go-ethereum",
"github.com/ethereum/go-ethereum/accounts/abi",
"github.com/ethereum/go-ethereum/accounts/abi/bind",
"github.com/ethereum/go-ethereum/common",
"github.com/ethereum/go-ethereum/common/hexutil",
"github.com/ethereum/go-ethereum/core/rawdb",
"github.com/ethereum/go-ethereum/core/types",
"github.com/ethereum/go-ethereum/crypto",
"github.com/ethereum/go-ethereum/ethclient",
"github.com/ethereum/go-ethereum/ethdb",
"github.com/ethereum/go-ethereum/p2p",
"github.com/ethereum/go-ethereum/p2p/discover",
"github.com/ethereum/go-ethereum/params",
"github.com/ethereum/go-ethereum/rlp",
"github.com/ethereum/go-ethereum/rpc",
"github.com/jmoiron/sqlx",
"github.com/lib/pq",
"github.com/mitchellh/go-homedir",
"github.com/onsi/ginkgo",
"github.com/onsi/gomega",
"github.com/onsi/gomega/ghttp",
"github.com/spf13/cobra",
"github.com/spf13/viper",
"golang.org/x/net/context",
"golang.org/x/sync/errgroup",
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -106,6 +106,7 @@ func buildTransformerInitializerMap() map[string]shared2.TransformerInitializer
transformerInitializerMap["tend"] = transformers.TendTransformerInitializer
transformerInitializerMap["vatGrab"] = transformers.VatGrabTransformerInitializer
transformerInitializerMap["vatInit"] = transformers.VatInitTransformerInitializer
transformerInitializerMap["vatMove"] = transformers.VatMoveTransformerInitializer
transformerInitializerMap["vatHeal"] = transformers.VatHealTransformerInitializer
transformerInitializerMap["vatFold"] = transformers.VatFoldTransformerInitializer
transformerInitializerMap["vatToll"] = transformers.VatTollTransformerInitializer

View File

@ -0,0 +1,3 @@
DROP TABLE maker.vat_move;
ALTER TABLE public.checked_headers
DROP COLUMN vat_move_checked;

View File

@ -0,0 +1,13 @@
CREATE TABLE maker.vat_move (
id SERIAL PRIMARY KEY,
header_id INTEGER NOT NULL REFERENCES headers (id) ON DELETE CASCADE,
src TEXT NOT NULL,
dst TEXT NOT NULL,
rad NUMERIC NOT NULL,
tx_idx INTEGER NOT NULL,
raw_log JSONB,
UNIQUE (header_id, tx_idx)
);
ALTER TABLE public.checked_headers
ADD COLUMN vat_move_checked BOOLEAN NOT NULL DEFAULT FALSE;

View File

@ -838,6 +838,41 @@ CREATE SEQUENCE maker.vat_init_id_seq
ALTER SEQUENCE maker.vat_init_id_seq OWNED BY maker.vat_init.id;
--
-- Name: vat_move; Type: TABLE; Schema: maker; Owner: -
--
CREATE TABLE maker.vat_move (
id integer NOT NULL,
header_id integer NOT NULL,
src text NOT NULL,
dst text NOT NULL,
rad numeric NOT NULL,
tx_idx integer NOT NULL,
raw_log jsonb
);
--
-- Name: vat_move_id_seq; Type: SEQUENCE; Schema: maker; Owner: -
--
CREATE SEQUENCE maker.vat_move_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: vat_move_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: -
--
ALTER SEQUENCE maker.vat_move_id_seq OWNED BY maker.vat_move.id;
--
-- Name: vat_toll; Type: TABLE; Schema: maker; Owner: -
--
@ -1012,6 +1047,7 @@ CREATE TABLE public.checked_headers (
pit_file_ilk_checked boolean DEFAULT false NOT NULL,
pit_file_stability_fee_checked boolean DEFAULT false NOT NULL,
vat_init_checked boolean DEFAULT false NOT NULL,
vat_move_checked boolean DEFAULT false NOT NULL,
vat_fold_checked boolean DEFAULT false NOT NULL,
vat_heal_checked boolean DEFAULT false NOT NULL,
vat_toll_checked boolean DEFAULT false NOT NULL,
@ -1491,6 +1527,13 @@ ALTER TABLE ONLY maker.vat_heal ALTER COLUMN id SET DEFAULT nextval('maker.vat_h
ALTER TABLE ONLY maker.vat_init ALTER COLUMN id SET DEFAULT nextval('maker.vat_init_id_seq'::regclass);
--
-- Name: vat_move id; Type: DEFAULT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.vat_move ALTER COLUMN id SET DEFAULT nextval('maker.vat_move_id_seq'::regclass);
--
-- Name: vat_toll id; Type: DEFAULT; Schema: maker; Owner: -
--
@ -1927,6 +1970,22 @@ ALTER TABLE ONLY maker.vat_init
ADD CONSTRAINT vat_init_pkey PRIMARY KEY (id);
--
-- Name: vat_move vat_move_header_id_tx_idx_key; Type: CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.vat_move
ADD CONSTRAINT vat_move_header_id_tx_idx_key UNIQUE (header_id, tx_idx);
--
-- Name: vat_move vat_move_pkey; Type: CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.vat_move
ADD CONSTRAINT vat_move_pkey PRIMARY KEY (id);
--
-- Name: vat_toll vat_toll_header_id_tx_idx_key; Type: CONSTRAINT; Schema: maker; Owner: -
--
@ -2289,6 +2348,14 @@ ALTER TABLE ONLY maker.vat_init
ADD CONSTRAINT vat_init_header_id_fkey FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE;
--
-- Name: vat_move vat_move_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.vat_move
ADD CONSTRAINT vat_move_header_id_fkey FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE;
--
-- Name: vat_toll vat_toll_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: -
--

View File

@ -58,6 +58,7 @@ var (
vatHealMethod = GetSolidityMethodSignature(VatABI, "heal")
vatGrabMethod = GetSolidityMethodSignature(VatABI, "grab")
vatInitMethod = GetSolidityMethodSignature(VatABI, "init")
vatMoveMethod = GetSolidityMethodSignature(VatABI, "move")
vatFoldMethod = GetSolidityMethodSignature(VatABI, "fold")
vatTollMethod = GetSolidityMethodSignature(VatABI, "toll")
vatTuneMethod = GetSolidityMethodSignature(VatABI, "tune")
@ -83,6 +84,7 @@ var (
VatHealSignature = GetLogNoteSignature(vatHealMethod)
VatGrabSignature = GetLogNoteSignature(vatGrabMethod)
VatInitSignature = GetLogNoteSignature(vatInitMethod)
VatMoveSignature = GetLogNoteSignature(vatMoveMethod)
VatFoldSignature = GetLogNoteSignature(vatFoldMethod)
VatTollSignature = GetLogNoteSignature(vatTollMethod)
VatTuneSignature = GetLogNoteSignature(vatTuneMethod)

View File

@ -146,6 +146,13 @@ var _ = Describe("Event signature generator", func() {
Expect(expected).To(Equal(actual))
})
It("gets the vat move method signature", func() {
expected := "move(bytes32,bytes32,int256)"
actual := shared.GetSolidityMethodSignature(shared.VatABI, "move")
Expect(expected).To(Equal(actual))
})
})
Describe("it handles events", func() {

View File

@ -58,4 +58,4 @@ func hexStringsToAddresses(hexStrings []string) []common.Address {
}
return addresses
}
}

View File

@ -0,0 +1,35 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move
import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move"
)
type MockVatMoveConverter struct {
converterError error
PassedLogs []types.Log
}
func (converter *MockVatMoveConverter) ToModels(ethLogs []types.Log) ([]vat_move.VatMoveModel, error) {
converter.PassedLogs = ethLogs
return []vat_move.VatMoveModel{test_data.VatMoveModel}, converter.converterError
}
func (converter *MockVatMoveConverter) SetConverterError(e error) {
converter.converterError = e
}

View File

@ -0,0 +1,65 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move"
)
type MockVatMoveRepository struct {
createError error
missingHeaders []core.Header
missingHeadersError error
PassedStartingBlockNumber int64
PassedEndingBlockNumber int64
PassedHeaderID int64
PassedModels []vat_move.VatMoveModel
CheckedHeaderIDs []int64
CheckedHeaderError error
}
func (repository *MockVatMoveRepository) Create(headerID int64, models []vat_move.VatMoveModel) error {
repository.PassedHeaderID = headerID
repository.PassedModels = models
return repository.createError
}
func (repository *MockVatMoveRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
repository.PassedStartingBlockNumber = startingBlockNumber
repository.PassedEndingBlockNumber = endingBlockNumber
return repository.missingHeaders, repository.missingHeadersError
}
func (repository *MockVatMoveRepository) SetMissingHeadersError(e error) {
repository.missingHeadersError = e
}
func (repository *MockVatMoveRepository) SetMissingHeaders(headers []core.Header) {
repository.missingHeaders = headers
}
func (repository *MockVatMoveRepository) SetCreateError(e error) {
repository.createError = e
}
func (repository *MockVatMoveRepository) MarkHeaderChecked(headerId int64) error {
repository.CheckedHeaderIDs = append(repository.CheckedHeaderIDs, headerId)
return repository.CheckedHeaderError
}
func (repository *MockVatMoveRepository) SetCheckedHeaderError(e error) {
repository.CheckedHeaderError = e
}

View File

@ -0,0 +1,52 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package test_data
import (
"encoding/json"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
)
var EthVatMoveLog = types.Log{
Address: common.HexToAddress(shared.VatContractAddress),
Topics: []common.Hash{
common.HexToHash("0x78f1947000000000000000000000000000000000000000000000000000000000"),
common.HexToHash("0xa730d1ff8b6bc74a26d54c20a9dda539909bab0e000000000000000000000000"),
common.HexToHash("0xb730d1ff8b6bc74a26d54c20a9dda539909bab0e000000000000000000000000"),
common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"),
},
Data: hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006478f19470a730d1ff8b6bc74a26d54c20a9dda539909bab0e000000000000000000000000b730d1ff8b6bc74a26d54c20a9dda539909bab0e000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a"),
BlockNumber: 10,
TxHash: common.HexToHash("0xe8f39fbb7fea3621f543868f19b1114e305aff6a063a30d32835ff1012526f91"),
TxIndex: 7,
BlockHash: common.HexToHash("0xe3dd2e05bd8b92833e20ed83e2171bbc06a9ec823232eca1730a807bd8f5edc0"),
Index: 0,
Removed: false,
}
var rawVatMoveLog, _ = json.Marshal(EthVatMoveLog)
var VatMoveModel = vat_move.VatMoveModel{
Src: "0xA730d1FF8B6Bc74a26d54c20a9dda539909BaB0e",
Dst: "0xB730D1fF8b6BC74a26D54c20a9ddA539909BAb0e",
Rad: "42",
TransactionIndex: EthVatMoveLog.TxIndex,
Raw: rawVatMoveLog,
}

View File

@ -41,6 +41,7 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_grab"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_heal"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_init"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_toll"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_tune"
)
@ -69,6 +70,7 @@ var (
TendTransformerInitializer = tend.TendTransformerInitializer{Config: tend.TendConfig}.NewTendTransformer
VatGrabTransformerInitializer = vat_grab.VatGrabTransformerInitializer{Config: vat_grab.VatGrabConfig}.NewVatGrabTransformer
VatInitTransformerInitializer = vat_init.VatInitTransformerInitializer{Config: vat_init.VatInitConfig}.NewVatInitTransformer
VatMoveTransformerInitializer = vat_move.VatMoveTransformerInitializer{Config: vat_move.VatMoveConfig}.NewVatMoveTransformer
VatHealTransformerInitializer = vat_heal.VatHealTransformerInitializer{Config: vat_heal.VatHealConfig}.NewVatHealTransformer
VatFoldTransformerInitializer = vat_fold.VatFoldTransformerInitializer{Config: vat_fold.VatFoldConfig}.NewVatFoldTransformer
VatTollTransformerInitializer = vat_toll.VatTollTransformerInitializer{Config: vat_toll.VatTollConfig}.NewVatTollTransformer
@ -97,6 +99,7 @@ func TransformerInitializers() []shared.TransformerInitializer {
TendTransformerInitializer,
VatGrabTransformerInitializer,
VatInitTransformerInitializer,
VatMoveTransformerInitializer,
VatHealTransformerInitializer,
VatFoldTransformerInitializer,
VatTollTransformerInitializer,

View File

@ -0,0 +1,27 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move
import (
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
)
var VatMoveConfig = shared.TransformerConfig{
ContractAddresses: []string{shared.VatContractAddress},
ContractAbi: shared.VatABI,
Topics: []string{shared.VatMoveSignature},
StartingBlockNumber: 0,
EndingBlockNumber: 10000000,
}

View File

@ -0,0 +1,66 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move
import (
"encoding/json"
"errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type Converter interface {
ToModels(ethLog []types.Log) ([]VatMoveModel, error)
}
type VatMoveConverter struct{}
func (VatMoveConverter) ToModels(ethLogs []types.Log) ([]VatMoveModel, error) {
var models []VatMoveModel
for _, ethLog := range ethLogs {
err := verifyLog(ethLog)
if err != nil {
return []VatMoveModel{}, err
}
src := common.BytesToAddress(ethLog.Topics[1].Bytes()[:common.AddressLength])
dst := common.BytesToAddress(ethLog.Topics[2].Bytes()[:common.AddressLength])
rad := ethLog.Topics[3].Big()
raw, err := json.Marshal(ethLog)
if err != nil {
return []VatMoveModel{}, err
}
models = append(models, VatMoveModel{
Src: src.String(),
Dst: dst.String(),
Rad: rad.String(),
TransactionIndex: ethLog.TxIndex,
Raw: raw,
})
}
return models, nil
}
func verifyLog(ethLog types.Log) error {
if len(ethLog.Data) <= 0 {
return errors.New("log data is empty")
}
if len(ethLog.Topics) < 4 {
return errors.New("log missing topics")
}
return nil
}

View File

@ -0,0 +1,44 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move_test
import (
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move"
)
var _ = Describe("Vat move converter", func() {
It("returns err if logs are missing topics", func() {
converter := vat_move.VatMoveConverter{}
badLog := types.Log{}
_, err := converter.ToModels([]types.Log{badLog})
Expect(err).To(HaveOccurred())
})
It("converts a log to a model", func() {
converter := vat_move.VatMoveConverter{}
models, err := converter.ToModels([]types.Log{test_data.EthVatMoveLog})
Expect(err).NotTo(HaveOccurred())
Expect(models[0]).To(Equal(test_data.VatMoveModel))
})
})

View File

@ -0,0 +1,23 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move
type VatMoveModel struct {
Src string
Dst string
Rad string
TransactionIndex uint `db:"tx_idx"`
Raw []byte `db:"raw_log"`
}

View File

@ -0,0 +1,96 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type Repository interface {
Create(headerID int64, models []VatMoveModel) error
MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error)
MarkHeaderChecked(headerID int64) error
}
type VatMoveRepository struct {
db *postgres.DB
}
func NewVatMoveRepository(db *postgres.DB) VatMoveRepository {
return VatMoveRepository{
db: db,
}
}
func (repository VatMoveRepository) Create(headerID int64, models []VatMoveModel) error {
tx, err := repository.db.Begin()
if err != nil {
return err
}
for _, vatMove := range models {
_, err = tx.Exec(
`INSERT INTO maker.vat_move (header_id, src, dst, rad, tx_idx, raw_log)
VALUES ($1, $2, $3, $4::NUMERIC, $5, $6)`,
headerID, vatMove.Src, vatMove.Dst, vatMove.Rad, vatMove.TransactionIndex, vatMove.Raw,
)
if err != nil {
tx.Rollback()
return err
}
}
_, err = tx.Exec(
`INSERT INTO public.checked_headers (header_id, vat_move_checked)
VALUES ($1, $2)
ON CONFLICT (header_id) DO
UPDATE SET vat_move_checked = $2`,
headerID, true)
if err != nil {
tx.Rollback()
return err
}
return tx.Commit()
}
func (repository VatMoveRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
var result []core.Header
err := repository.db.Select(
&result,
`SELECT headers.id, headers.block_number FROM headers
LEFT JOIN checked_headers on headers.id = header_id
WHERE (header_id ISNULL OR vat_move_checked IS FALSE)
AND headers.block_number >= $1
AND headers.block_number <= $2
AND headers.eth_node_fingerprint = $3`,
startingBlockNumber,
endingBlockNumber,
repository.db.Node.ID,
)
return result, err
}
func (repository VatMoveRepository) MarkHeaderChecked(headerID int64) error {
_, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, vat_move_checked)
VALUES ($1, $2)
ON CONFLICT (header_id) DO
UPDATE SET vat_move_checked = $2`, headerID, true)
return err
}

View File

@ -0,0 +1,192 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move_test
import (
"database/sql"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move"
"github.com/vulcanize/vulcanizedb/test_config"
"math/rand"
)
var _ = Describe("Vat Move", func() {
var db *postgres.DB
var headerRepository repositories.HeaderRepository
var vatMoveRepository vat_move.VatMoveRepository
BeforeEach(func() {
db = test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository = repositories.NewHeaderRepository(db)
vatMoveRepository = vat_move.NewVatMoveRepository(db)
})
Describe("Create", func() {
var headerID int64
var err error
BeforeEach(func() {
headerID, err = headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
err = vatMoveRepository.Create(headerID, []vat_move.VatMoveModel{test_data.VatMoveModel})
Expect(err).NotTo(HaveOccurred())
})
It("adds a vat move event", func() {
var dbVatMove vat_move.VatMoveModel
err = db.Get(&dbVatMove, `SELECT src, dst, rad, tx_idx, raw_log FROM maker.vat_move WHERE header_id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
Expect(dbVatMove.Src).To(Equal(test_data.VatMoveModel.Src))
Expect(dbVatMove.Dst).To(Equal(test_data.VatMoveModel.Dst))
Expect(dbVatMove.Rad).To(Equal(test_data.VatMoveModel.Rad))
Expect(dbVatMove.TransactionIndex).To(Equal(test_data.VatMoveModel.TransactionIndex))
Expect(dbVatMove.Raw).To(MatchJSON(test_data.VatMoveModel.Raw))
})
It("marks header id as checked for vat move logs", func() {
var headerChecked bool
err = db.Get(&headerChecked, `SELECT vat_move_checked FROM public.checked_headers WHERE header_id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
Expect(headerChecked).To(BeTrue())
})
It("returns an error if insertion fails", func() {
err = vatMoveRepository.Create(headerID, []vat_move.VatMoveModel{test_data.VatMoveModel})
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint"))
})
It("removes vat move event if corresponding header is deleted", func() {
_, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
var dbVatMove vat_move.VatMoveModel
err = db.Get(&dbVatMove, `SELECT src, dst, rad, tx_idx, raw_log FROM maker.vat_move WHERE header_id = $1`, headerID)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(sql.ErrNoRows))
})
})
Describe("MissingHeaders", func() {
var eventBlockNumber = rand.Int63()
var startingBlockNumber = eventBlockNumber - 1
var endingBlockNumber = eventBlockNumber + 1
var outOfRangeBlockNumber = eventBlockNumber + 2
It("returns headers haven't been checked", func() {
var headerIds []int64
for _, number := range []int64{startingBlockNumber, eventBlockNumber, endingBlockNumber, outOfRangeBlockNumber} {
headerId, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: number})
Expect(err).NotTo(HaveOccurred())
headerIds = append(headerIds, headerId)
}
err := vatMoveRepository.MarkHeaderChecked(headerIds[1])
Expect(err).NotTo(HaveOccurred())
headers, err := vatMoveRepository.MissingHeaders(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
Expect(len(headers)).To(Equal(2))
Expect(headers[0].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber)))
Expect(headers[1].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber)))
})
It("only treats headers as checked if vat_move has been checked", func() {
var headerIds []int64
for _, number := range []int64{startingBlockNumber, eventBlockNumber, endingBlockNumber, outOfRangeBlockNumber} {
headerId, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: number})
Expect(err).NotTo(HaveOccurred())
headerIds = append(headerIds, headerId)
}
// Just creates row, doesn't set this header as checked
_, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerIds[1])
Expect(err).NotTo(HaveOccurred())
headers, err := vatMoveRepository.MissingHeaders(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
Expect(len(headers)).To(Equal(3))
Expect(headers[0].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber), Equal(eventBlockNumber)))
Expect(headers[1].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber), Equal(eventBlockNumber)))
Expect(headers[2].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber), Equal(eventBlockNumber)))
})
It("only returns headers associated with the current node", func() {
blockNumbers := []int64{1, 2, 3}
dbTwo := test_config.NewTestDB(core.Node{ID: "second"})
headerRepositoryTwo := repositories.NewHeaderRepository(dbTwo)
var headerIDs []int64
for _, n := range blockNumbers {
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: n})
Expect(err).NotTo(HaveOccurred())
headerIDs = append(headerIDs, headerID)
_, err = headerRepositoryTwo.CreateOrUpdateHeader(core.Header{BlockNumber: n})
Expect(err).NotTo(HaveOccurred())
}
vatMoveRepositoryTwo := vat_move.NewVatMoveRepository(dbTwo)
err := vatMoveRepository.Create(headerIDs[0], []vat_move.VatMoveModel{test_data.VatMoveModel})
Expect(err).NotTo(HaveOccurred())
nodeOneMissingHeaders, err := vatMoveRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1])
Expect(err).NotTo(HaveOccurred())
Expect(len(nodeOneMissingHeaders)).To(Equal(len(blockNumbers) - 1))
nodeTwoMissingHeaders, err := vatMoveRepositoryTwo.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1])
Expect(err).NotTo(HaveOccurred())
Expect(len(nodeTwoMissingHeaders)).To(Equal(len(blockNumbers)))
})
})
Describe("MarkHeaderChecked", func() {
var headerID int64
var err error
BeforeEach(func() {
headerID, err = headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
})
It("creates a new row for a new headerID", func() {
err = vatMoveRepository.MarkHeaderChecked(headerID)
Expect(err).NotTo(HaveOccurred())
var headerChecked bool
err = db.Get(&headerChecked, `SELECT vat_move_checked FROM public.checked_headers WHERE header_id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
Expect(headerChecked).To(BeTrue())
})
It("updates row when headerId already exists", func() {
_, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerID)
Expect(err).NotTo(HaveOccurred())
err = vatMoveRepository.MarkHeaderChecked(headerID)
Expect(err).NotTo(HaveOccurred())
var headerChecked bool
err = db.Get(&headerChecked, `SELECT vat_move_checked FROM public.checked_headers WHERE header_id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
Expect(headerChecked).To(BeTrue())
})
})
})

View File

@ -0,0 +1,83 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move
import (
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
)
type VatMoveTransformerInitializer struct {
Config shared.TransformerConfig
}
func (initializer VatMoveTransformerInitializer) NewVatMoveTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer {
converter := VatMoveConverter{}
fetcher := shared.NewFetcher(blockChain)
repository := NewVatMoveRepository(db)
return VatMoveTransformer{
Config: initializer.Config,
Converter: converter,
Fetcher: fetcher,
Repository: repository,
}
}
type VatMoveTransformer struct {
Config shared.TransformerConfig
Converter Converter
Fetcher shared.LogFetcher
Repository Repository
}
func (transformer VatMoveTransformer) Execute() error {
missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber)
if err != nil {
return err
}
log.Printf("Fetching vat move event logs for %d headers \n", len(missingHeaders))
for _, header := range missingHeaders {
topics := [][]common.Hash{{common.HexToHash(shared.VatMoveSignature)}}
matchingLogs, err := transformer.Fetcher.FetchLogs(VatMoveConfig.ContractAddresses, topics, header.BlockNumber)
if err != nil {
return err
}
if len(matchingLogs) < 1 {
err := transformer.Repository.MarkHeaderChecked(header.Id)
if err != nil {
return err
}
continue
}
models, err := transformer.Converter.ToModels(matchingLogs)
if err != nil {
return err
}
err = transformer.Repository.Create(header.Id, models)
if err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,212 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move_test
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks"
vat_move_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/vat_move"
"github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move"
)
var _ = Describe("Vat move transformer", func() {
var fetcher mocks.MockLogFetcher
var converter vat_move_mocks.MockVatMoveConverter
var repository vat_move_mocks.MockVatMoveRepository
var config = vat_move.VatMoveConfig
var headerOne core.Header
var headerTwo core.Header
BeforeEach(func() {
fetcher = mocks.MockLogFetcher{}
converter = vat_move_mocks.MockVatMoveConverter{}
repository = vat_move_mocks.MockVatMoveRepository{}
headerOne = core.Header{Id: GinkgoRandomSeed(), BlockNumber: GinkgoRandomSeed()}
headerTwo = core.Header{Id: GinkgoRandomSeed(), BlockNumber: GinkgoRandomSeed()}
})
It("gets missing headers for block numbers specified in config", func() {
transformer := vat_move.VatMoveTransformer{
Config: config,
Converter: &converter,
Fetcher: &fetcher,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(repository.PassedStartingBlockNumber).To(Equal(vat_move.VatMoveConfig.StartingBlockNumber))
Expect(repository.PassedEndingBlockNumber).To(Equal(vat_move.VatMoveConfig.EndingBlockNumber))
})
It("returns error if repository returns error for missing headers", func() {
repository.SetMissingHeadersError(fakes.FakeError)
transformer := vat_move.VatMoveTransformer{
Config: config,
Converter: &converter,
Fetcher: &fetcher,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
It("fetches logs for missing headers", func() {
repository.SetMissingHeaders([]core.Header{headerOne, headerTwo})
transformer := vat_move.VatMoveTransformer{
Config: config,
Fetcher: &fetcher,
Converter: &vat_move_mocks.MockVatMoveConverter{},
Repository: &repository,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber}))
Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{
vat_move.VatMoveConfig.ContractAddresses,
vat_move.VatMoveConfig.ContractAddresses,
}))
Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.VatMoveSignature)}}))
})
It("returns error if fetcher returns error", func() {
fetcher.SetFetcherError(fakes.FakeError)
repository.SetMissingHeaders([]core.Header{headerOne})
transformer := vat_move.VatMoveTransformer{
Config: config,
Fetcher: &fetcher,
Converter: &converter,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
It("converts matching logs", func() {
fetcher.SetFetchedLogs([]types.Log{test_data.EthVatMoveLog})
repository.SetMissingHeaders([]core.Header{headerOne})
transformer := vat_move.VatMoveTransformer{
Config: config,
Fetcher: &fetcher,
Converter: &converter,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(converter.PassedLogs).To(Equal([]types.Log{test_data.EthVatMoveLog}))
})
It("returns error if converter returns error", func() {
converter.SetConverterError(fakes.FakeError)
fetcher.SetFetchedLogs([]types.Log{test_data.EthVatMoveLog})
repository.SetMissingHeaders([]core.Header{headerOne})
transformer := vat_move.VatMoveTransformer{
Config: config,
Fetcher: &fetcher,
Converter: &converter,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
It("marks header as checked even if no logs were returned", func() {
repository.SetMissingHeaders([]core.Header{headerOne, headerTwo})
fetcher.SetFetchedLogs([]types.Log{})
transformer := vat_move.VatMoveTransformer{
Config: config,
Converter: &converter,
Fetcher: &fetcher,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(repository.CheckedHeaderIDs).To(ContainElement(headerOne.Id))
Expect(repository.CheckedHeaderIDs).To(ContainElement(headerTwo.Id))
})
It("returns error if marking header checked returns err", func() {
repository.SetMissingHeaders([]core.Header{headerOne, headerTwo})
repository.SetCheckedHeaderError(fakes.FakeError)
fetcher.SetFetchedLogs([]types.Log{})
transformer := vat_move.VatMoveTransformer{
Config: config,
Converter: &converter,
Fetcher: &fetcher,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
It("persists vat move model", func() {
fetcher.SetFetchedLogs([]types.Log{test_data.EthVatMoveLog})
repository.SetMissingHeaders([]core.Header{headerOne})
transformer := vat_move.VatMoveTransformer{
Config: config,
Fetcher: &fetcher,
Converter: &converter,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(repository.PassedHeaderID).To(Equal(headerOne.Id))
Expect(repository.PassedModels).To(Equal([]vat_move.VatMoveModel{test_data.VatMoveModel}))
})
It("returns error if repository returns error for create", func() {
fetcher.SetFetchedLogs([]types.Log{test_data.EthVatMoveLog})
repository.SetMissingHeaders([]core.Header{headerOne})
repository.SetCreateError(fakes.FakeError)
transformer := vat_move.VatMoveTransformer{
Config: config,
Fetcher: &fetcher,
Converter: &converter,
Repository: &repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
})

View File

@ -0,0 +1,33 @@
// Copyright 2018 Vulcanize
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vat_move_test
import (
"io/ioutil"
"log"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestVatMove(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "VatMove Suite")
}
var _ = BeforeSuite(func() {
log.SetOutput(ioutil.Discard)
})

View File

@ -99,6 +99,7 @@ func CleanTestDB(db *postgres.DB) {
db.MustExec("DELETE FROM maker.vat_grab")
db.MustExec("DELETE FROM maker.vat_heal")
db.MustExec("DELETE FROM maker.vat_init")
db.MustExec("DELETE FROM maker.vat_move")
db.MustExec("DELETE FROM maker.vat_fold")
db.MustExec("DELETE FROM maker.vat_toll")
db.MustExec("DELETE FROM maker.vat_tune")