diff --git a/cmd/parseStorageDiffs.go b/cmd/parseStorageDiffs.go index 753603f1..5fa9dc7c 100644 --- a/cmd/parseStorageDiffs.go +++ b/cmd/parseStorageDiffs.go @@ -57,7 +57,10 @@ func parseStorageDiffs() { // TODO: configure transformers watcher := shared.NewStorageWatcher(tailer, db) - watcher.AddTransformers([]storage.TransformerInitializer{transformers.GetPitStorageTransformer().NewTransformer}) + watcher.AddTransformers([]storage.TransformerInitializer{ + transformers.GetPitStorageTransformer().NewTransformer, + transformers.GetVatStorageTransformer().NewTransformer, + }) err = watcher.Execute() if err != nil { diff --git a/db/migrations/00073_create_vat_contract_storage_tables.sql b/db/migrations/00073_create_vat_contract_storage_tables.sql new file mode 100644 index 00000000..a7ba7da9 --- /dev/null +++ b/db/migrations/00073_create_vat_contract_storage_tables.sql @@ -0,0 +1,102 @@ +-- +goose Up +CREATE TABLE maker.vat_debt ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + debt NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_vice ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + vice NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_ilk_art ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + ilk TEXT, + art NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_ilk_ink ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + ilk TEXT, + ink NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_ilk_rate ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + ilk TEXT, + rate NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_ilk_take ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + ilk TEXT, + take NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_urn_art ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + ilk TEXT, + urn TEXT, + art TEXT +); + +CREATE TABLE maker.vat_urn_ink ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + ilk TEXT, + urn TEXT, + ink NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_gem ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + ilk TEXT, + guy TEXT, + gem NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_dai ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + guy TEXT, + dai NUMERIC NOT NULL +); + +CREATE TABLE maker.vat_sin ( + id SERIAL PRIMARY KEY, + block_number BIGINT, + block_hash TEXT, + guy TEXT, + sin NUMERIC NOT NULL +); + +-- +goose Down +DROP TABLE maker.vat_debt; +DROP TABLE maker.vat_vice; +DROP TABLE maker.vat_ilk_art; +DROP TABLE maker.vat_ilk_ink; +DROP TABLE maker.vat_ilk_rate; +DROP TABLE maker.vat_ilk_take; +DROP TABLE maker.vat_urn_art; +DROP TABLE maker.vat_urn_ink; +DROP TABLE maker.vat_gem; +DROP TABLE maker.vat_dai; +DROP TABLE maker.vat_sin; \ No newline at end of file diff --git a/db/schema.sql b/db/schema.sql index 628fb901..223a84d2 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -912,6 +912,71 @@ CREATE SEQUENCE maker.tend_id_seq ALTER SEQUENCE maker.tend_id_seq OWNED BY maker.tend.id; +-- +-- Name: vat_dai; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_dai ( + id integer NOT NULL, + block_number bigint, + block_hash text, + guy text, + dai numeric NOT NULL +); + + +-- +-- Name: vat_dai_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_dai_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_dai_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_dai_id_seq OWNED BY maker.vat_dai.id; + + +-- +-- Name: vat_debt; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_debt ( + id integer NOT NULL, + block_number bigint, + block_hash text, + debt numeric NOT NULL +); + + +-- +-- Name: vat_debt_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_debt_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_debt_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_debt_id_seq OWNED BY maker.vat_debt.id; + + -- -- Name: vat_flux; Type: TABLE; Schema: maker; Owner: - -- @@ -985,6 +1050,40 @@ CREATE SEQUENCE maker.vat_fold_id_seq ALTER SEQUENCE maker.vat_fold_id_seq OWNED BY maker.vat_fold.id; +-- +-- Name: vat_gem; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_gem ( + id integer NOT NULL, + block_number bigint, + block_hash text, + ilk text, + guy text, + gem numeric NOT NULL +); + + +-- +-- Name: vat_gem_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_gem_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_gem_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_gem_id_seq OWNED BY maker.vat_gem.id; + + -- -- Name: vat_grab; Type: TABLE; Schema: maker; Owner: - -- @@ -1060,6 +1159,138 @@ CREATE SEQUENCE maker.vat_heal_id_seq ALTER SEQUENCE maker.vat_heal_id_seq OWNED BY maker.vat_heal.id; +-- +-- Name: vat_ilk_art; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_ilk_art ( + id integer NOT NULL, + block_number bigint, + block_hash text, + ilk text, + art numeric NOT NULL +); + + +-- +-- Name: vat_ilk_art_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_ilk_art_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_ilk_art_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_ilk_art_id_seq OWNED BY maker.vat_ilk_art.id; + + +-- +-- Name: vat_ilk_ink; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_ilk_ink ( + id integer NOT NULL, + block_number bigint, + block_hash text, + ilk text, + ink numeric NOT NULL +); + + +-- +-- Name: vat_ilk_ink_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_ilk_ink_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_ilk_ink_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_ilk_ink_id_seq OWNED BY maker.vat_ilk_ink.id; + + +-- +-- Name: vat_ilk_rate; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_ilk_rate ( + id integer NOT NULL, + block_number bigint, + block_hash text, + ilk text, + rate numeric NOT NULL +); + + +-- +-- Name: vat_ilk_rate_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_ilk_rate_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_ilk_rate_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_ilk_rate_id_seq OWNED BY maker.vat_ilk_rate.id; + + +-- +-- Name: vat_ilk_take; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_ilk_take ( + id integer NOT NULL, + block_number bigint, + block_hash text, + ilk text, + take numeric NOT NULL +); + + +-- +-- Name: vat_ilk_take_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_ilk_take_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_ilk_take_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_ilk_take_id_seq OWNED BY maker.vat_ilk_take.id; + + -- -- Name: vat_init; Type: TABLE; Schema: maker; Owner: - -- @@ -1130,6 +1361,39 @@ CREATE SEQUENCE maker.vat_move_id_seq ALTER SEQUENCE maker.vat_move_id_seq OWNED BY maker.vat_move.id; +-- +-- Name: vat_sin; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_sin ( + id integer NOT NULL, + block_number bigint, + block_hash text, + guy text, + sin numeric NOT NULL +); + + +-- +-- Name: vat_sin_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_sin_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_sin_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_sin_id_seq OWNED BY maker.vat_sin.id; + + -- -- Name: vat_slip; Type: TABLE; Schema: maker; Owner: - -- @@ -1241,6 +1505,106 @@ CREATE SEQUENCE maker.vat_tune_id_seq ALTER SEQUENCE maker.vat_tune_id_seq OWNED BY maker.vat_tune.id; +-- +-- Name: vat_urn_art; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_urn_art ( + id integer NOT NULL, + block_number bigint, + block_hash text, + ilk text, + urn text, + art text +); + + +-- +-- Name: vat_urn_art_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_urn_art_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_urn_art_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_urn_art_id_seq OWNED BY maker.vat_urn_art.id; + + +-- +-- Name: vat_urn_ink; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_urn_ink ( + id integer NOT NULL, + block_number bigint, + block_hash text, + ilk text, + urn text, + ink numeric NOT NULL +); + + +-- +-- Name: vat_urn_ink_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_urn_ink_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_urn_ink_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_urn_ink_id_seq OWNED BY maker.vat_urn_ink.id; + + +-- +-- Name: vat_vice; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.vat_vice ( + id integer NOT NULL, + block_number bigint, + block_hash text, + vice numeric NOT NULL +); + + +-- +-- Name: vat_vice_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.vat_vice_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: vat_vice_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.vat_vice_id_seq OWNED BY maker.vat_vice.id; + + -- -- Name: vow_flog; Type: TABLE; Schema: maker; Owner: - -- @@ -1896,6 +2260,20 @@ ALTER TABLE ONLY maker.price_feeds ALTER COLUMN id SET DEFAULT nextval('maker.pr ALTER TABLE ONLY maker.tend ALTER COLUMN id SET DEFAULT nextval('maker.tend_id_seq'::regclass); +-- +-- Name: vat_dai id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_dai ALTER COLUMN id SET DEFAULT nextval('maker.vat_dai_id_seq'::regclass); + + +-- +-- Name: vat_debt id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_debt ALTER COLUMN id SET DEFAULT nextval('maker.vat_debt_id_seq'::regclass); + + -- -- Name: vat_flux id; Type: DEFAULT; Schema: maker; Owner: - -- @@ -1910,6 +2288,13 @@ ALTER TABLE ONLY maker.vat_flux ALTER COLUMN id SET DEFAULT nextval('maker.vat_f ALTER TABLE ONLY maker.vat_fold ALTER COLUMN id SET DEFAULT nextval('maker.vat_fold_id_seq'::regclass); +-- +-- Name: vat_gem id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_gem ALTER COLUMN id SET DEFAULT nextval('maker.vat_gem_id_seq'::regclass); + + -- -- Name: vat_grab id; Type: DEFAULT; Schema: maker; Owner: - -- @@ -1924,6 +2309,34 @@ ALTER TABLE ONLY maker.vat_grab ALTER COLUMN id SET DEFAULT nextval('maker.vat_g ALTER TABLE ONLY maker.vat_heal ALTER COLUMN id SET DEFAULT nextval('maker.vat_heal_id_seq'::regclass); +-- +-- Name: vat_ilk_art id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_ilk_art ALTER COLUMN id SET DEFAULT nextval('maker.vat_ilk_art_id_seq'::regclass); + + +-- +-- Name: vat_ilk_ink id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_ilk_ink ALTER COLUMN id SET DEFAULT nextval('maker.vat_ilk_ink_id_seq'::regclass); + + +-- +-- Name: vat_ilk_rate id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_ilk_rate ALTER COLUMN id SET DEFAULT nextval('maker.vat_ilk_rate_id_seq'::regclass); + + +-- +-- Name: vat_ilk_take id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_ilk_take ALTER COLUMN id SET DEFAULT nextval('maker.vat_ilk_take_id_seq'::regclass); + + -- -- Name: vat_init id; Type: DEFAULT; Schema: maker; Owner: - -- @@ -1938,6 +2351,13 @@ ALTER TABLE ONLY maker.vat_init ALTER COLUMN id SET DEFAULT nextval('maker.vat_i ALTER TABLE ONLY maker.vat_move ALTER COLUMN id SET DEFAULT nextval('maker.vat_move_id_seq'::regclass); +-- +-- Name: vat_sin id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_sin ALTER COLUMN id SET DEFAULT nextval('maker.vat_sin_id_seq'::regclass); + + -- -- Name: vat_slip id; Type: DEFAULT; Schema: maker; Owner: - -- @@ -1959,6 +2379,27 @@ ALTER TABLE ONLY maker.vat_toll ALTER COLUMN id SET DEFAULT nextval('maker.vat_t ALTER TABLE ONLY maker.vat_tune ALTER COLUMN id SET DEFAULT nextval('maker.vat_tune_id_seq'::regclass); +-- +-- Name: vat_urn_art id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_urn_art ALTER COLUMN id SET DEFAULT nextval('maker.vat_urn_art_id_seq'::regclass); + + +-- +-- Name: vat_urn_ink id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_urn_ink ALTER COLUMN id SET DEFAULT nextval('maker.vat_urn_ink_id_seq'::regclass); + + +-- +-- Name: vat_vice id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_vice ALTER COLUMN id SET DEFAULT nextval('maker.vat_vice_id_seq'::regclass); + + -- -- Name: vow_flog id; Type: DEFAULT; Schema: maker; Owner: - -- @@ -2379,6 +2820,22 @@ ALTER TABLE ONLY maker.tend ADD CONSTRAINT tend_pkey PRIMARY KEY (id); +-- +-- Name: vat_dai vat_dai_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_dai + ADD CONSTRAINT vat_dai_pkey PRIMARY KEY (id); + + +-- +-- Name: vat_debt vat_debt_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_debt + ADD CONSTRAINT vat_debt_pkey PRIMARY KEY (id); + + -- -- Name: vat_flux vat_flux_header_id_tx_idx_log_idx_key; Type: CONSTRAINT; Schema: maker; Owner: - -- @@ -2411,6 +2868,14 @@ ALTER TABLE ONLY maker.vat_fold ADD CONSTRAINT vat_fold_pkey PRIMARY KEY (id); +-- +-- Name: vat_gem vat_gem_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_gem + ADD CONSTRAINT vat_gem_pkey PRIMARY KEY (id); + + -- -- Name: vat_grab vat_grab_header_id_tx_idx_log_idx_key; Type: CONSTRAINT; Schema: maker; Owner: - -- @@ -2443,6 +2908,38 @@ ALTER TABLE ONLY maker.vat_heal ADD CONSTRAINT vat_heal_pkey PRIMARY KEY (id); +-- +-- Name: vat_ilk_art vat_ilk_art_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_ilk_art + ADD CONSTRAINT vat_ilk_art_pkey PRIMARY KEY (id); + + +-- +-- Name: vat_ilk_ink vat_ilk_ink_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_ilk_ink + ADD CONSTRAINT vat_ilk_ink_pkey PRIMARY KEY (id); + + +-- +-- Name: vat_ilk_rate vat_ilk_rate_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_ilk_rate + ADD CONSTRAINT vat_ilk_rate_pkey PRIMARY KEY (id); + + +-- +-- Name: vat_ilk_take vat_ilk_take_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_ilk_take + ADD CONSTRAINT vat_ilk_take_pkey PRIMARY KEY (id); + + -- -- Name: vat_init vat_init_header_id_tx_idx_log_idx_key; Type: CONSTRAINT; Schema: maker; Owner: - -- @@ -2475,6 +2972,14 @@ ALTER TABLE ONLY maker.vat_move ADD CONSTRAINT vat_move_pkey PRIMARY KEY (id); +-- +-- Name: vat_sin vat_sin_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_sin + ADD CONSTRAINT vat_sin_pkey PRIMARY KEY (id); + + -- -- Name: vat_slip vat_slip_header_id_tx_idx_log_idx_key; Type: CONSTRAINT; Schema: maker; Owner: - -- @@ -2523,6 +3028,30 @@ ALTER TABLE ONLY maker.vat_tune ADD CONSTRAINT vat_tune_pkey PRIMARY KEY (id); +-- +-- Name: vat_urn_art vat_urn_art_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_urn_art + ADD CONSTRAINT vat_urn_art_pkey PRIMARY KEY (id); + + +-- +-- Name: vat_urn_ink vat_urn_ink_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_urn_ink + ADD CONSTRAINT vat_urn_ink_pkey PRIMARY KEY (id); + + +-- +-- Name: vat_vice vat_vice_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.vat_vice + ADD CONSTRAINT vat_vice_pkey PRIMARY KEY (id); + + -- -- Name: vow_flog vow_flog_header_id_tx_idx_log_idx_key; Type: CONSTRAINT; Schema: maker; Owner: - -- diff --git a/pkg/transformers/storage_diffs/maker/maker_storage_repository.go b/pkg/transformers/storage_diffs/maker/maker_storage_repository.go index 5f6cf6ae..44ff4998 100644 --- a/pkg/transformers/storage_diffs/maker/maker_storage_repository.go +++ b/pkg/transformers/storage_diffs/maker/maker_storage_repository.go @@ -18,8 +18,17 @@ package maker import "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" +type Urn struct { + Ilk string + Guy string +} + type IMakerStorageRepository interface { + GetDaiKeys() ([]string, error) + GetGemKeys() ([]Urn, error) GetIlks() ([]string, error) + GetSinKeys() ([]string, error) + GetUrns() ([]Urn, error) SetDB(db *postgres.DB) } @@ -27,8 +36,29 @@ type MakerStorageRepository struct { db *postgres.DB } -func (repository *MakerStorageRepository) SetDB(db *postgres.DB) { - repository.db = db +func (repository *MakerStorageRepository) GetDaiKeys() ([]string, error) { + var daiKeys []string + err := repository.db.Select(&daiKeys, ` + SELECT DISTINCT src FROM maker.vat_move UNION + SELECT DISTINCT dst FROM maker.vat_move UNION + SELECT DISTINCT w FROM maker.vat_tune UNION + SELECT DISTINCT v FROM maker.vat_heal UNION + SELECT DISTINCT urn FROM maker.vat_fold + `) + return daiKeys, err +} + +func (repository *MakerStorageRepository) GetGemKeys() ([]Urn, error) { + var gems []Urn + err := repository.db.Select(&gems, ` + SELECT DISTINCT ilk, guy FROM maker.vat_slip UNION + SELECT DISTINCT ilk, src AS guy FROM maker.vat_flux UNION + SELECT DISTINCT ilk, dst AS guy FROM maker.vat_flux UNION + SELECT DISTINCT ilk, v AS guy FROM maker.vat_tune UNION + SELECT DISTINCT ilk, v AS guy FROM maker.vat_grab UNION + SELECT DISTINCT ilk, urn AS guy FROM maker.vat_toll + `) + return gems, err } func (repository MakerStorageRepository) GetIlks() ([]string, error) { @@ -36,3 +66,21 @@ func (repository MakerStorageRepository) GetIlks() ([]string, error) { err := repository.db.Select(&ilks, `SELECT DISTINCT ilk FROM maker.vat_init`) return ilks, err } + +func (repository *MakerStorageRepository) GetSinKeys() ([]string, error) { + var sinKeys []string + err := repository.db.Select(&sinKeys, `SELECT DISTINCT w FROM maker.vat_grab UNION + SELECT DISTINCT urn FROM maker.vat_heal`) + return sinKeys, err +} + +func (repository *MakerStorageRepository) GetUrns() ([]Urn, error) { + var urns []Urn + err := repository.db.Select(&urns, `SELECT DISTINCT ilk, urn AS guy FROM maker.vat_tune UNION + SELECT DISTINCT ilk, urn AS guy FROM maker.vat_grab`) + return urns, err +} + +func (repository *MakerStorageRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/storage_diffs/maker/maker_storage_repository_test.go b/pkg/transformers/storage_diffs/maker/maker_storage_repository_test.go index 262b12b1..013007dc 100644 --- a/pkg/transformers/storage_diffs/maker/maker_storage_repository_test.go +++ b/pkg/transformers/storage_diffs/maker/maker_storage_repository_test.go @@ -27,31 +27,368 @@ import ( ) var _ = Describe("Maker storage repository", func() { - It("fetches unique ilks from vat init events", func() { - db := test_config.NewTestDB(test_config.NewTestNode()) + var ( + db *postgres.DB + repository maker.IMakerStorageRepository + ilk1 = "ilk1" + ilk2 = "ilk2" + guy1 = "guy1" + guy2 = "guy2" + guy3 = "guy3" + ) + + BeforeEach(func() { + db = test_config.NewTestDB(test_config.NewTestNode()) test_config.CleanTestDB(db) - insertVatInit("ilk1", 1, db) - insertVatInit("ilk2", 2, db) - insertVatInit("ilk2", 3, db) - repository := maker.MakerStorageRepository{} + repository = &maker.MakerStorageRepository{} repository.SetDB(db) + }) - ilks, err := repository.GetIlks() + Describe("getting dai keys", func() { + It("fetches guy from both src and dst field on vat_move", func() { + insertVatMove(guy1, guy2, 1, db) - Expect(err).NotTo(HaveOccurred()) - Expect(len(ilks)).To(Equal(2)) - Expect(ilks).To(ConsistOf("ilk1", "ilk2")) + keys, err := repository.GetDaiKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(keys)).To(Equal(2)) + Expect(keys).To(ConsistOf(guy1, guy2)) + }) + + It("fetches guy from w field on vat_tune", func() { + insertVatTune(guy1, guy1, guy1, guy2, 1, db) + + keys, err := repository.GetDaiKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(keys)).To(Equal(1)) + Expect(keys).To(ConsistOf(guy2)) + }) + + It("fetches guy from v field on vat_heal", func() { + insertVatHeal(guy2, guy1, 1, db) + + keys, err := repository.GetDaiKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(keys)).To(Equal(1)) + Expect(keys).To(ConsistOf(guy1)) + }) + + It("fetches unique guys from vat_move + vat_tune + vat_heal + vat_fold", func() { + guy4 := "guy4" + guy5 := "guy5" + guy6 := "guy6" + insertVatMove(guy1, guy2, 1, db) + insertVatTune(guy1, guy1, guy1, guy3, 2, db) + insertVatHeal(guy6, guy4, 3, db) + insertVatFold(guy5, 4, db) + // duplicates + insertVatMove(guy3, guy1, 5, db) + insertVatTune(guy2, guy2, guy2, guy5, 6, db) + insertVatHeal(guy6, guy2, 7, db) + insertVatFold(guy4, 8, db) + + keys, err := repository.GetDaiKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(keys)).To(Equal(5)) + Expect(keys).To(ConsistOf(guy1, guy2, guy3, guy4, guy5)) + }) + + It("does not return error if no matching rows", func() { + daiKeys, err := repository.GetDaiKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(daiKeys)).To(BeZero()) + }) + }) + + Describe("getting gem keys", func() { + It("fetches guy from both src and dst field on vat_flux", func() { + insertVatFlux(ilk1, guy1, guy2, 1, db) + + gems, err := repository.GetGemKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(gems)).To(Equal(2)) + Expect(gems).To(ConsistOf([]maker.Urn{{ + Ilk: ilk1, + Guy: guy1, + }, { + Ilk: ilk1, + Guy: guy2, + }})) + }) + + It("fetches guy from v field on vat_tune + vat_grab", func() { + insertVatTune(ilk1, guy1, guy2, guy1, 1, db) + insertVatGrab(ilk1, guy1, guy3, guy1, 2, db) + + gems, err := repository.GetGemKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(gems)).To(Equal(2)) + Expect(gems).To(ConsistOf([]maker.Urn{{ + Ilk: ilk1, + Guy: guy2, + }, { + Ilk: ilk1, + Guy: guy3, + }})) + }) + + It("fetches unique urns from vat_slip + vat_flux + vat_tune + vat_grab + vat_toll events", func() { + insertVatSlip(ilk1, guy1, 1, db) + insertVatFlux(ilk1, guy2, guy3, 2, db) + insertVatTune(ilk2, guy1, guy1, guy1, 3, db) + insertVatGrab(ilk2, guy1, guy2, guy1, 4, db) + insertVatToll(ilk2, guy3, 5, db) + // duplicates + insertVatSlip(ilk1, guy2, 6, db) + insertVatFlux(ilk2, guy2, guy3, 7, db) + insertVatTune(ilk2, guy1, guy1, guy1, 8, db) + insertVatGrab(ilk1, guy1, guy1, guy1, 9, db) + insertVatToll(ilk1, guy3, 10, db) + + gems, err := repository.GetGemKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(gems)).To(Equal(6)) + Expect(gems).To(ConsistOf([]maker.Urn{{ + Ilk: ilk1, + Guy: guy1, + }, { + Ilk: ilk1, + Guy: guy2, + }, { + Ilk: ilk1, + Guy: guy3, + }, { + Ilk: ilk2, + Guy: guy1, + }, { + Ilk: ilk2, + Guy: guy2, + }, { + Ilk: ilk2, + Guy: guy3, + }})) + }) + + It("does not return error if no matching rows", func() { + gemKeys, err := repository.GetGemKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(gemKeys)).To(BeZero()) + }) + }) + + Describe("getting ilks", func() { + It("fetches unique ilks from vat init events", func() { + insertVatInit(ilk1, 1, db) + insertVatInit(ilk2, 2, db) + insertVatInit(ilk2, 3, db) + + ilks, err := repository.GetIlks() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(ilks)).To(Equal(2)) + Expect(ilks).To(ConsistOf(ilk1, ilk2)) + }) + + It("does not return error if no matching rows", func() { + ilks, err := repository.GetIlks() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(ilks)).To(BeZero()) + }) + }) + + Describe("getting sin keys", func() { + It("fetches guy from w field of vat grab", func() { + insertVatGrab(guy1, guy1, guy1, guy2, 1, db) + + sinKeys, err := repository.GetSinKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(sinKeys)).To(Equal(1)) + Expect(sinKeys).To(ConsistOf(guy2)) + }) + + It("fetches guy from u field of vat heal", func() { + insertVatHeal(guy1, guy2, 1, db) + + sinKeys, err := repository.GetSinKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(sinKeys)).To(Equal(1)) + Expect(sinKeys).To(ConsistOf(guy1)) + }) + + It("fetches unique sin keys from vat_grab + vat_heal", func() { + insertVatGrab(guy3, guy3, guy3, guy1, 1, db) + insertVatHeal(guy2, guy3, 2, db) + // duplicates + insertVatGrab(guy2, guy2, guy2, guy2, 3, db) + insertVatHeal(guy1, guy2, 4, db) + + sinKeys, err := repository.GetSinKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(sinKeys)).To(Equal(2)) + Expect(sinKeys).To(ConsistOf(guy1, guy2)) + }) + + It("does not return error if no matching rows", func() { + sinKeys, err := repository.GetSinKeys() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(sinKeys)).To(BeZero()) + }) + }) + + Describe("getting urns", func() { + It("fetches unique urns from vat_tune + vat_grab events", func() { + insertVatTune(ilk1, guy1, guy1, guy1, 1, db) + insertVatTune(ilk1, guy2, guy1, guy1, 2, db) + insertVatTune(ilk2, guy1, guy1, guy1, 3, db) + insertVatTune(ilk1, guy1, guy1, guy1, 4, db) + insertVatGrab(ilk1, guy1, guy1, guy1, 5, db) + insertVatGrab(ilk1, guy3, guy1, guy1, 6, db) + + urns, err := repository.GetUrns() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(urns)).To(Equal(4)) + Expect(urns).To(ConsistOf([]maker.Urn{{ + Ilk: ilk1, + Guy: guy1, + }, { + Ilk: ilk1, + Guy: guy2, + }, { + Ilk: ilk2, + Guy: guy1, + }, { + Ilk: ilk1, + Guy: guy3, + }})) + }) + + It("does not return error if no matching rows", func() { + urns, err := repository.GetUrns() + + Expect(err).NotTo(HaveOccurred()) + Expect(len(urns)).To(BeZero()) + }) }) }) +func insertVatFold(urn string, blockNumber int64, db *postgres.DB) { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) + Expect(err).NotTo(HaveOccurred()) + _, execErr := db.Exec( + `INSERT INTO maker.vat_fold (header_id, urn, log_idx, tx_idx) + VALUES($1, $2, $3, $4)`, + headerID, urn, 0, 0, + ) + Expect(execErr).NotTo(HaveOccurred()) +} + +func insertVatFlux(ilk, src, dst string, blockNumber int64, db *postgres.DB) { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) + Expect(err).NotTo(HaveOccurred()) + _, execErr := db.Exec( + `INSERT INTO maker.vat_flux (header_id, ilk, src, dst, log_idx, tx_idx) + VALUES($1, $2, $3, $4, $5, $6)`, + headerID, ilk, src, dst, 0, 0, + ) + Expect(execErr).NotTo(HaveOccurred()) +} + +func insertVatGrab(ilk, urn, v, w string, blockNumber int64, db *postgres.DB) { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) + Expect(err).NotTo(HaveOccurred()) + _, execErr := db.Exec( + `INSERT INTO maker.vat_grab (header_id, ilk, urn, v, w, log_idx, tx_idx) + VALUES($1, $2, $3, $4, $5, $6, $7)`, + headerID, ilk, urn, v, w, 0, 0, + ) + Expect(execErr).NotTo(HaveOccurred()) +} + +func insertVatHeal(urn, v string, blockNumber int64, db *postgres.DB) { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) + Expect(err).NotTo(HaveOccurred()) + _, execErr := db.Exec( + `INSERT INTO maker.vat_heal (header_id, urn, v, log_idx, tx_idx) + VALUES($1, $2, $3, $4, $5)`, + headerID, urn, v, 0, 0, + ) + Expect(execErr).NotTo(HaveOccurred()) +} + func insertVatInit(ilk string, blockNumber int64, db *postgres.DB) { headerRepository := repositories.NewHeaderRepository(db) headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) Expect(err).NotTo(HaveOccurred()) _, execErr := db.Exec( - `INSERT INTO maker.vat_init (header_id, ilk, log_idx, tx_idx, raw_log) - VALUES($1, $2, $3, $4, $5)`, - headerID, ilk, 0, 0, "[]", + `INSERT INTO maker.vat_init (header_id, ilk, log_idx, tx_idx) + VALUES($1, $2, $3, $4)`, + headerID, ilk, 0, 0, + ) + Expect(execErr).NotTo(HaveOccurred()) +} + +func insertVatMove(src, dst string, blockNumber int64, db *postgres.DB) { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) + Expect(err).NotTo(HaveOccurred()) + _, execErr := db.Exec( + `INSERT INTO maker.vat_move (header_id, src, dst, rad, log_idx, tx_idx) + VALUES($1, $2, $3, $4, $5, $6)`, + headerID, src, dst, 0, 0, 0, + ) + Expect(execErr).NotTo(HaveOccurred()) +} + +func insertVatSlip(ilk, guy string, blockNumber int64, db *postgres.DB) { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) + Expect(err).NotTo(HaveOccurred()) + _, execErr := db.Exec( + `INSERT INTO maker.vat_slip (header_id, ilk, guy, log_idx, tx_idx) + VALUES($1, $2, $3, $4, $5)`, + headerID, ilk, guy, 0, 0, + ) + Expect(execErr).NotTo(HaveOccurred()) +} + +func insertVatToll(ilk, urn string, blockNumber int64, db *postgres.DB) { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) + Expect(err).NotTo(HaveOccurred()) + _, execErr := db.Exec( + `INSERT INTO maker.vat_toll (header_id, ilk, urn, log_idx, tx_idx) + VALUES($1, $2, $3, $4, $5)`, + headerID, ilk, urn, 0, 0, + ) + Expect(execErr).NotTo(HaveOccurred()) +} + +func insertVatTune(ilk, urn, v, w string, blockNumber int64, db *postgres.DB) { + headerRepository := repositories.NewHeaderRepository(db) + headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber)) + Expect(err).NotTo(HaveOccurred()) + _, execErr := db.Exec( + `INSERT INTO maker.vat_tune (header_id, ilk, urn, v, w, log_idx, tx_idx) + VALUES($1, $2, $3, $4, $5, $6, $7)`, + headerID, ilk, urn, v, w, 0, 0, ) Expect(execErr).NotTo(HaveOccurred()) } diff --git a/pkg/transformers/storage_diffs/maker/pit/mappings.go b/pkg/transformers/storage_diffs/maker/pit/mappings.go index 2533077f..46e5938c 100644 --- a/pkg/transformers/storage_diffs/maker/pit/mappings.go +++ b/pkg/transformers/storage_diffs/maker/pit/mappings.go @@ -18,12 +18,10 @@ package pit import ( "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs" "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker" "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/shared" - "math/big" ) const ( @@ -118,29 +116,19 @@ func getStaticMappings() map[common.Hash]shared.StorageValueMetadata { } func getSpotKey(ilk string) common.Hash { - keyBytes := common.FromHex("0x" + ilk + IlkSpotIndex) - encoded := crypto.Keccak256(keyBytes) - return common.BytesToHash(encoded) + return storage_diffs.GetMapping(IlkSpotIndex, ilk) } func getSpotMetadata(ilk string) shared.StorageValueMetadata { - return shared.StorageValueMetadata{ - Name: IlkSpot, - Keys: map[shared.Key]string{shared.Ilk: ilk}, - Type: shared.Uint256, - } + keys := map[shared.Key]string{shared.Ilk: ilk} + return shared.GetStorageValueMetadata(IlkSpot, keys, shared.Uint256) } func getLineKey(ilk string) common.Hash { - spotMappingAsInt := big.NewInt(0).SetBytes(getSpotKey(ilk).Bytes()) - incrementedByOne := big.NewInt(0).Add(spotMappingAsInt, big.NewInt(1)) - return common.BytesToHash(incrementedByOne.Bytes()) + return storage_diffs.GetIncrementedKey(getSpotKey(ilk), 1) } func getLineMetadata(ilk string) shared.StorageValueMetadata { - return shared.StorageValueMetadata{ - Name: IlkLine, - Keys: map[shared.Key]string{shared.Ilk: ilk}, - Type: shared.Uint256, - } + keys := map[shared.Key]string{shared.Ilk: ilk} + return shared.GetStorageValueMetadata(IlkLine, keys, shared.Uint256) } diff --git a/pkg/transformers/storage_diffs/maker/pit/mappings_test.go b/pkg/transformers/storage_diffs/maker/pit/mappings_test.go index 72331b58..7097a029 100644 --- a/pkg/transformers/storage_diffs/maker/pit/mappings_test.go +++ b/pkg/transformers/storage_diffs/maker/pit/mappings_test.go @@ -47,7 +47,7 @@ var _ = Describe("Pit storage mappings", func() { It("returns value metadata for spot when ilk in the DB", func() { storageRepository := &test_helpers.MockMakerStorageRepository{} fakeIlk := "fakeIlk" - storageRepository.SetIlks([]string{fakeIlk}) + storageRepository.Ilks = []string{fakeIlk} mappings := pit.PitMappings{StorageRepository: storageRepository} ilkSpotKey := common.BytesToHash(crypto.Keccak256(common.FromHex("0x" + fakeIlk + pit.IlkSpotIndex))) expectedMetadata := shared.StorageValueMetadata{ @@ -62,7 +62,7 @@ var _ = Describe("Pit storage mappings", func() { It("returns value metadata for line when ilk in the DB", func() { storageRepository := &test_helpers.MockMakerStorageRepository{} fakeIlk := "fakeIlk" - storageRepository.SetIlks([]string{fakeIlk}) + storageRepository.Ilks = []string{fakeIlk} mappings := pit.PitMappings{StorageRepository: storageRepository} ilkSpotKeyBytes := crypto.Keccak256(common.FromHex("0x" + fakeIlk + pit.IlkSpotIndex)) ilkSpotAsInt := big.NewInt(0).SetBytes(ilkSpotKeyBytes) diff --git a/pkg/transformers/storage_diffs/maker/pit/repository.go b/pkg/transformers/storage_diffs/maker/pit/repository.go index cedb5663..c11212cb 100644 --- a/pkg/transformers/storage_diffs/maker/pit/repository.go +++ b/pkg/transformers/storage_diffs/maker/pit/repository.go @@ -17,6 +17,7 @@ package pit import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/shared" ) @@ -44,7 +45,7 @@ func (repository PitStorageRepository) Create(blockNumber int, blockHash string, case PitVat: return repository.insertPitVat(blockNumber, blockHash, value.(string)) default: - panic("unrecognized storage metadata name") + panic(fmt.Sprintf("unrecognized pit contract storage name: %s", metadata.Name)) } } diff --git a/pkg/transformers/storage_diffs/maker/test_helpers/maker_storage_repository.go b/pkg/transformers/storage_diffs/maker/test_helpers/maker_storage_repository.go index 6f259df3..161cac53 100644 --- a/pkg/transformers/storage_diffs/maker/test_helpers/maker_storage_repository.go +++ b/pkg/transformers/storage_diffs/maker/test_helpers/maker_storage_repository.go @@ -1,19 +1,51 @@ package test_helpers -import "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" +import ( + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker" +) type MockMakerStorageRepository struct { - GetIlksCalled bool - ilks []string + DaiKeys []string + GemKeys []maker.Urn + GetDaiKeysCalled bool + GetDaiKeysError error + GetGemKeysCalled bool + GetGemKeysError error + GetIlksCalled bool + GetIlksError error + GetSinKeysCalled bool + GetSinKeysError error + GetUrnsCalled bool + GetUrnsError error + Ilks []string + SinKeys []string + Urns []maker.Urn +} + +func (repository *MockMakerStorageRepository) GetDaiKeys() ([]string, error) { + repository.GetDaiKeysCalled = true + return repository.DaiKeys, repository.GetDaiKeysError +} + +func (repository *MockMakerStorageRepository) GetGemKeys() ([]maker.Urn, error) { + repository.GetGemKeysCalled = true + return repository.GemKeys, repository.GetGemKeysError } func (repository *MockMakerStorageRepository) GetIlks() ([]string, error) { repository.GetIlksCalled = true - return repository.ilks, nil + return repository.Ilks, repository.GetIlksError +} + +func (repository *MockMakerStorageRepository) GetSinKeys() ([]string, error) { + repository.GetSinKeysCalled = true + return repository.SinKeys, repository.GetSinKeysError +} + +func (repository *MockMakerStorageRepository) GetUrns() ([]maker.Urn, error) { + repository.GetUrnsCalled = true + return repository.Urns, repository.GetUrnsError } func (repository *MockMakerStorageRepository) SetDB(db *postgres.DB) {} - -func (repository *MockMakerStorageRepository) SetIlks(ilks []string) { - repository.ilks = ilks -} diff --git a/pkg/transformers/storage_diffs/maker/vat/mappings.go b/pkg/transformers/storage_diffs/maker/vat/mappings.go new file mode 100644 index 00000000..58e2bf6a --- /dev/null +++ b/pkg/transformers/storage_diffs/maker/vat/mappings.go @@ -0,0 +1,241 @@ +package vat + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/shared" +) + +const ( + Dai = "dai" + Gem = "gem" + IlkArt = "Art" + IlkInk = "Ink" + IlkRate = "rate" + IlkTake = "take" + Sin = "sin" + UrnArt = "art" + UrnInk = "ink" + VatDebt = "debt" + VatVice = "vice" +) + +var ( + DebtKey = common.HexToHash(storage_diffs.IndexSix) + DebtMetadata = shared.StorageValueMetadata{ + Name: VatDebt, + Keys: nil, + Type: 0, + } + + IlksMappingIndex = storage_diffs.IndexOne + UrnsMappingIndex = storage_diffs.IndexTwo + GemsMappingIndex = storage_diffs.IndexThree + DaiMappingIndex = storage_diffs.IndexFour + SinMappingIndex = storage_diffs.IndexFive + + ViceKey = common.HexToHash(storage_diffs.IndexSeven) + ViceMetadata = shared.StorageValueMetadata{ + Name: VatVice, + Keys: nil, + Type: 0, + } +) + +type VatMappings struct { + StorageRepository maker.IMakerStorageRepository + mappings map[common.Hash]shared.StorageValueMetadata +} + +func (mappings VatMappings) Lookup(key common.Hash) (shared.StorageValueMetadata, error) { + metadata, ok := mappings.mappings[key] + if !ok { + err := mappings.loadMappings() + if err != nil { + return metadata, err + } + metadata, ok = mappings.mappings[key] + if !ok { + return metadata, shared.ErrStorageKeyNotFound{Key: key.Hex()} + } + } + return metadata, nil +} + +func (mappings *VatMappings) SetDB(db *postgres.DB) { + mappings.StorageRepository.SetDB(db) +} + +func (mappings *VatMappings) loadMappings() error { + mappings.mappings = loadStaticMappings() + daiErr := mappings.loadDaiKeys() + if daiErr != nil { + return daiErr + } + gemErr := mappings.loadGemKeys() + if gemErr != nil { + return gemErr + } + ilkErr := mappings.loadIlkKeys() + if ilkErr != nil { + return ilkErr + } + sinErr := mappings.loadSinKeys() + if sinErr != nil { + return sinErr + } + urnErr := mappings.loadUrnKeys() + if urnErr != nil { + return urnErr + } + return nil +} + +func loadStaticMappings() map[common.Hash]shared.StorageValueMetadata { + mappings := make(map[common.Hash]shared.StorageValueMetadata) + mappings[DebtKey] = DebtMetadata + mappings[ViceKey] = ViceMetadata + return mappings +} + +func (mappings *VatMappings) loadDaiKeys() error { + daiKeys, err := mappings.StorageRepository.GetDaiKeys() + if err != nil { + return err + } + for _, d := range daiKeys { + mappings.mappings[getDaiKey(d)] = getDaiMetadata(d) + } + return nil +} + +func (mappings *VatMappings) loadGemKeys() error { + gemKeys, err := mappings.StorageRepository.GetGemKeys() + if err != nil { + return err + } + for _, gem := range gemKeys { + mappings.mappings[getGemKey(gem.Ilk, gem.Guy)] = getGemMetadata(gem.Ilk, gem.Guy) + } + return nil +} + +func (mappings *VatMappings) loadIlkKeys() error { + ilks, err := mappings.StorageRepository.GetIlks() + if err != nil { + return err + } + for _, ilk := range ilks { + mappings.mappings[getIlkTakeKey(ilk)] = getIlkTakeMetadata(ilk) + mappings.mappings[getIlkRateKey(ilk)] = getIlkRateMetadata(ilk) + mappings.mappings[getIlkInkKey(ilk)] = getIlkInkMetadata(ilk) + mappings.mappings[getIlkArtKey(ilk)] = getIlkArtMetadata(ilk) + } + return nil +} + +func (mappings *VatMappings) loadSinKeys() error { + sinKeys, err := mappings.StorageRepository.GetSinKeys() + if err != nil { + return err + } + for _, s := range sinKeys { + mappings.mappings[getSinKey(s)] = getSinMetadata(s) + } + return nil +} + +func (mappings *VatMappings) loadUrnKeys() error { + urns, err := mappings.StorageRepository.GetUrns() + if err != nil { + return err + } + for _, urn := range urns { + mappings.mappings[getUrnInkKey(urn.Ilk, urn.Guy)] = getUrnInkMetadata(urn.Ilk, urn.Guy) + mappings.mappings[getUrnArtKey(urn.Ilk, urn.Guy)] = getUrnArtMetadata(urn.Ilk, urn.Guy) + } + return nil +} + +func getIlkTakeKey(ilk string) common.Hash { + return storage_diffs.GetMapping(IlksMappingIndex, ilk) +} + +func getIlkTakeMetadata(ilk string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Ilk: ilk} + return shared.GetStorageValueMetadata(IlkTake, keys, shared.Uint256) +} + +func getIlkRateKey(ilk string) common.Hash { + return storage_diffs.GetIncrementedKey(getIlkTakeKey(ilk), 1) +} + +func getIlkRateMetadata(ilk string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Ilk: ilk} + return shared.GetStorageValueMetadata(IlkRate, keys, shared.Uint256) +} + +func getIlkInkKey(ilk string) common.Hash { + return storage_diffs.GetIncrementedKey(getIlkTakeKey(ilk), 2) +} + +func getIlkInkMetadata(ilk string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Ilk: ilk} + return shared.GetStorageValueMetadata(IlkInk, keys, shared.Uint256) +} + +func getIlkArtKey(ilk string) common.Hash { + return storage_diffs.GetIncrementedKey(getIlkTakeKey(ilk), 3) +} + +func getIlkArtMetadata(ilk string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Ilk: ilk} + return shared.GetStorageValueMetadata(IlkArt, keys, shared.Uint256) +} + +func getUrnInkKey(ilk, guy string) common.Hash { + return storage_diffs.GetNestedMapping(UrnsMappingIndex, ilk, guy) +} + +func getUrnInkMetadata(ilk, guy string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Ilk: ilk, shared.Guy: guy} + return shared.GetStorageValueMetadata(UrnInk, keys, shared.Uint256) +} + +func getUrnArtKey(ilk, guy string) common.Hash { + return storage_diffs.GetIncrementedKey(getUrnInkKey(ilk, guy), 1) +} + +func getUrnArtMetadata(ilk, guy string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Ilk: ilk, shared.Guy: guy} + return shared.GetStorageValueMetadata(UrnArt, keys, shared.Uint256) +} + +func getGemKey(ilk, guy string) common.Hash { + return storage_diffs.GetNestedMapping(GemsMappingIndex, ilk, guy) +} + +func getGemMetadata(ilk, guy string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Ilk: ilk, shared.Guy: guy} + return shared.GetStorageValueMetadata(Gem, keys, shared.Uint256) +} + +func getDaiKey(guy string) common.Hash { + return storage_diffs.GetMapping(DaiMappingIndex, guy) +} + +func getDaiMetadata(guy string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Guy: guy} + return shared.GetStorageValueMetadata(Dai, keys, shared.Uint256) +} + +func getSinKey(guy string) common.Hash { + return storage_diffs.GetMapping(SinMappingIndex, guy) +} + +func getSinMetadata(guy string) shared.StorageValueMetadata { + keys := map[shared.Key]string{shared.Guy: guy} + return shared.GetStorageValueMetadata(Sin, keys, shared.Uint256) +} diff --git a/pkg/transformers/storage_diffs/maker/vat/mappings_test.go b/pkg/transformers/storage_diffs/maker/vat/mappings_test.go new file mode 100644 index 00000000..06f7a052 --- /dev/null +++ b/pkg/transformers/storage_diffs/maker/vat/mappings_test.go @@ -0,0 +1,233 @@ +package vat_test + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/fakes" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker/test_helpers" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker/vat" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/shared" + "math/big" +) + +var _ = Describe("Vat storage mappings", func() { + var ( + fakeIlk = "fakeIlk" + fakeGuy = "fakeGuy" + storageRepository *test_helpers.MockMakerStorageRepository + mappings vat.VatMappings + ) + + BeforeEach(func() { + storageRepository = &test_helpers.MockMakerStorageRepository{} + mappings = vat.VatMappings{StorageRepository: storageRepository} + }) + + Describe("looking up static keys", func() { + It("returns value metadata if key exists", func() { + Expect(mappings.Lookup(vat.DebtKey)).To(Equal(vat.DebtMetadata)) + Expect(mappings.Lookup(vat.ViceKey)).To(Equal(vat.ViceMetadata)) + }) + + It("returns error if key does not exist", func() { + _, err := mappings.Lookup(common.HexToHash(fakes.FakeHash.Hex())) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrStorageKeyNotFound{Key: fakes.FakeHash.Hex()})) + }) + }) + + Describe("looking up dynamic keys", func() { + It("refreshes mappings from repository if key not found", func() { + mappings.Lookup(fakes.FakeHash) + + Expect(storageRepository.GetDaiKeysCalled).To(BeTrue()) + Expect(storageRepository.GetGemKeysCalled).To(BeTrue()) + Expect(storageRepository.GetIlksCalled).To(BeTrue()) + Expect(storageRepository.GetSinKeysCalled).To(BeTrue()) + Expect(storageRepository.GetUrnsCalled).To(BeTrue()) + }) + + It("returns error if dai keys lookup fails", func() { + storageRepository.GetDaiKeysError = fakes.FakeError + + _, err := mappings.Lookup(fakes.FakeHash) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(fakes.FakeError)) + }) + + It("returns error if gem keys lookup fails", func() { + storageRepository.GetGemKeysError = fakes.FakeError + + _, err := mappings.Lookup(fakes.FakeHash) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(fakes.FakeError)) + }) + + It("returns error if ilks lookup fails", func() { + storageRepository.GetIlksError = fakes.FakeError + + _, err := mappings.Lookup(fakes.FakeHash) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(fakes.FakeError)) + }) + + It("returns error if sin keys lookup fails", func() { + storageRepository.GetSinKeysError = fakes.FakeError + + _, err := mappings.Lookup(fakes.FakeHash) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(fakes.FakeError)) + }) + + It("returns error if urns lookup fails", func() { + storageRepository.GetUrnsError = fakes.FakeError + + _, err := mappings.Lookup(fakes.FakeHash) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(fakes.FakeError)) + }) + + Describe("ilk", func() { + It("returns value metadata for ilk take", func() { + storageRepository.Ilks = []string{fakeIlk} + ilkTakeKey := common.BytesToHash(crypto.Keccak256(common.FromHex("0x" + fakeIlk + vat.IlksMappingIndex))) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.IlkTake, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(ilkTakeKey)).To(Equal(expectedMetadata)) + }) + + It("returns value metadata for ilk rate", func() { + storageRepository.Ilks = []string{fakeIlk} + ilkTakeBytes := crypto.Keccak256(common.FromHex("0x" + fakeIlk + vat.IlksMappingIndex)) + ilkTakeAsInt := big.NewInt(0).SetBytes(ilkTakeBytes) + incrementedIlkTake := big.NewInt(0).Add(ilkTakeAsInt, big.NewInt(1)) + ilkRateKey := common.BytesToHash(incrementedIlkTake.Bytes()) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.IlkRate, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(ilkRateKey)).To(Equal(expectedMetadata)) + }) + + It("returns value metadata for ilk Ink", func() { + storageRepository.Ilks = []string{fakeIlk} + ilkTakeBytes := crypto.Keccak256(common.FromHex("0x" + fakeIlk + vat.IlksMappingIndex)) + ilkTakeAsInt := big.NewInt(0).SetBytes(ilkTakeBytes) + doubleIncrementedIlkTake := big.NewInt(0).Add(ilkTakeAsInt, big.NewInt(2)) + ilkInkKey := common.BytesToHash(doubleIncrementedIlkTake.Bytes()) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.IlkInk, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(ilkInkKey)).To(Equal(expectedMetadata)) + }) + + It("returns value metadata for ilk Art", func() { + storageRepository.Ilks = []string{fakeIlk} + ilkTakeBytes := crypto.Keccak256(common.FromHex("0x" + fakeIlk + vat.IlksMappingIndex)) + ilkTakeAsInt := big.NewInt(0).SetBytes(ilkTakeBytes) + tripleIncrementedIlkTake := big.NewInt(0).Add(ilkTakeAsInt, big.NewInt(3)) + ilkArtKey := common.BytesToHash(tripleIncrementedIlkTake.Bytes()) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.IlkArt, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(ilkArtKey)).To(Equal(expectedMetadata)) + }) + }) + + Describe("urn", func() { + It("returns value metadata for urn ink", func() { + storageRepository.Urns = []maker.Urn{{Ilk: fakeIlk, Guy: fakeGuy}} + encodedPrimaryMapIndex := crypto.Keccak256(common.FromHex("0x" + fakeIlk + vat.UrnsMappingIndex)) + encodedSecondaryMapIndex := crypto.Keccak256(common.FromHex(fakeGuy), encodedPrimaryMapIndex) + urnInkKey := common.BytesToHash(encodedSecondaryMapIndex) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.UrnInk, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk, shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(urnInkKey)).To(Equal(expectedMetadata)) + }) + + It("returns value metadata for urn art", func() { + storageRepository.Urns = []maker.Urn{{Ilk: fakeIlk, Guy: fakeGuy}} + encodedPrimaryMapIndex := crypto.Keccak256(common.FromHex("0x" + fakeIlk + vat.UrnsMappingIndex)) + urnInkAsInt := big.NewInt(0).SetBytes(crypto.Keccak256(common.FromHex(fakeGuy), encodedPrimaryMapIndex)) + incrementedUrnInk := big.NewInt(0).Add(urnInkAsInt, big.NewInt(1)) + urnArtKey := common.BytesToHash(incrementedUrnInk.Bytes()) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.UrnArt, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk, shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(urnArtKey)).To(Equal(expectedMetadata)) + }) + }) + + Describe("gem", func() { + It("returns value metadata for gem", func() { + storageRepository.GemKeys = []maker.Urn{{Ilk: fakeIlk, Guy: fakeGuy}} + encodedPrimaryMapIndex := crypto.Keccak256(common.FromHex("0x" + fakeIlk + vat.GemsMappingIndex)) + encodedSecondaryMapIndex := crypto.Keccak256(common.FromHex(fakeGuy), encodedPrimaryMapIndex) + gemKey := common.BytesToHash(encodedSecondaryMapIndex) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.Gem, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk, shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(gemKey)).To(Equal(expectedMetadata)) + }) + }) + + Describe("dai", func() { + It("returns value metadata for dai", func() { + storageRepository.DaiKeys = []string{fakeGuy} + daiKey := common.BytesToHash(crypto.Keccak256(common.FromHex("0x" + fakeGuy + vat.DaiMappingIndex))) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.Dai, + Keys: map[shared.Key]string{shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(daiKey)).To(Equal(expectedMetadata)) + }) + }) + + Describe("when sin key exists in the db", func() { + It("returns value metadata for sin", func() { + storageRepository.SinKeys = []string{fakeGuy} + sinKey := common.BytesToHash(crypto.Keccak256(common.FromHex("0x" + fakeGuy + vat.SinMappingIndex))) + expectedMetadata := shared.StorageValueMetadata{ + Name: vat.Sin, + Keys: map[shared.Key]string{shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + Expect(mappings.Lookup(sinKey)).To(Equal(expectedMetadata)) + }) + }) + }) +}) diff --git a/pkg/transformers/storage_diffs/maker/vat/repository.go b/pkg/transformers/storage_diffs/maker/vat/repository.go new file mode 100644 index 00000000..d237b352 --- /dev/null +++ b/pkg/transformers/storage_diffs/maker/vat/repository.go @@ -0,0 +1,163 @@ +package vat + +import ( + "fmt" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/shared" +) + +type VatStorageRepository struct { + db *postgres.DB +} + +func (repository *VatStorageRepository) Create(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, value interface{}) error { + switch metadata.Name { + case Dai: + return repository.insertDai(blockNumber, blockHash, metadata, value.(string)) + case Gem: + return repository.insertGem(blockNumber, blockHash, metadata, value.(string)) + case IlkArt: + return repository.insertIlkArt(blockNumber, blockHash, metadata, value.(string)) + case IlkInk: + return repository.insertIlkInk(blockNumber, blockHash, metadata, value.(string)) + case IlkRate: + return repository.insertIlkRate(blockNumber, blockHash, metadata, value.(string)) + case IlkTake: + return repository.insertIlkTake(blockNumber, blockHash, metadata, value.(string)) + case Sin: + return repository.insertSin(blockNumber, blockHash, metadata, value.(string)) + case UrnArt: + return repository.insertUrnArt(blockNumber, blockHash, metadata, value.(string)) + case UrnInk: + return repository.insertUrnInk(blockNumber, blockHash, metadata, value.(string)) + case VatDebt: + return repository.insertVatDebt(blockNumber, blockHash, value.(string)) + case VatVice: + return repository.insertVatVice(blockNumber, blockHash, value.(string)) + default: + panic(fmt.Sprintf("unrecognized vat contract storage name: %s", metadata.Name)) + } +} + +func (repository *VatStorageRepository) SetDB(db *postgres.DB) { + repository.db = db +} + +func (repository *VatStorageRepository) insertDai(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, dai string) error { + guy, err := getGuy(metadata.Keys) + if err != nil { + return err + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_dai (block_number, block_hash, guy, dai) VALUES ($1, $2, $3, $4)`, blockNumber, blockHash, guy, dai) + return writeErr +} + +func (repository *VatStorageRepository) insertGem(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, gem string) error { + ilk, ilkErr := getIlk(metadata.Keys) + if ilkErr != nil { + return ilkErr + } + guy, guyErr := getGuy(metadata.Keys) + if guyErr != nil { + return guyErr + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_gem (block_number, block_hash, ilk, guy, gem) VALUES ($1, $2, $3, $4, $5)`, blockNumber, blockHash, ilk, guy, gem) + return writeErr +} + +func (repository *VatStorageRepository) insertIlkArt(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, art string) error { + ilk, err := getIlk(metadata.Keys) + if err != nil { + return err + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_ilk_art (block_number, block_hash, ilk, art) VALUES ($1, $2, $3, $4)`, blockNumber, blockHash, ilk, art) + return writeErr +} + +func (repository *VatStorageRepository) insertIlkInk(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, ink string) error { + ilk, err := getIlk(metadata.Keys) + if err != nil { + return err + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_ilk_ink (block_number, block_hash, ilk, ink) VALUES ($1, $2, $3, $4)`, blockNumber, blockHash, ilk, ink) + return writeErr +} + +func (repository *VatStorageRepository) insertIlkRate(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, rate string) error { + ilk, err := getIlk(metadata.Keys) + if err != nil { + return err + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_ilk_rate (block_number, block_hash, ilk, rate) VALUES ($1, $2, $3, $4)`, blockNumber, blockHash, ilk, rate) + return writeErr +} + +func (repository *VatStorageRepository) insertIlkTake(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, take string) error { + ilk, err := getIlk(metadata.Keys) + if err != nil { + return err + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_ilk_take (block_number, block_hash, ilk, take) VALUES ($1, $2, $3, $4)`, blockNumber, blockHash, ilk, take) + return writeErr +} + +func (repository *VatStorageRepository) insertSin(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, sin string) error { + guy, err := getGuy(metadata.Keys) + if err != nil { + return err + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_sin (block_number, block_hash, guy, sin) VALUES ($1, $2, $3, $4)`, blockNumber, blockHash, guy, sin) + return writeErr +} + +func (repository *VatStorageRepository) insertUrnArt(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, art string) error { + ilk, ilkErr := getIlk(metadata.Keys) + if ilkErr != nil { + return ilkErr + } + guy, guyErr := getGuy(metadata.Keys) + if guyErr != nil { + return guyErr + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_urn_art (block_number, block_hash, ilk, urn, art) VALUES ($1, $2, $3, $4, $5)`, blockNumber, blockHash, ilk, guy, art) + return writeErr +} + +func (repository *VatStorageRepository) insertUrnInk(blockNumber int, blockHash string, metadata shared.StorageValueMetadata, ink string) error { + ilk, ilkErr := getIlk(metadata.Keys) + if ilkErr != nil { + return ilkErr + } + guy, guyErr := getGuy(metadata.Keys) + if guyErr != nil { + return guyErr + } + _, writeErr := repository.db.Exec(`INSERT INTO maker.vat_urn_ink (block_number, block_hash, ilk, urn, ink) VALUES ($1, $2, $3, $4, $5)`, blockNumber, blockHash, ilk, guy, ink) + return writeErr +} + +func (repository *VatStorageRepository) insertVatDebt(blockNumber int, blockHash, debt string) error { + _, err := repository.db.Exec(`INSERT INTO maker.vat_debt (block_number, block_hash, debt) VALUES ($1, $2, $3)`, blockNumber, blockHash, debt) + return err +} + +func (repository *VatStorageRepository) insertVatVice(blockNumber int, blockHash, vice string) error { + _, err := repository.db.Exec(`INSERT INTO maker.vat_vice (block_number, block_hash, vice) VALUES ($1, $2, $3)`, blockNumber, blockHash, vice) + return err +} + +func getGuy(keys map[shared.Key]string) (string, error) { + guy, ok := keys[shared.Guy] + if !ok { + return "", shared.ErrMetadataMalformed{MissingData: shared.Guy} + } + return guy, nil +} + +func getIlk(keys map[shared.Key]string) (string, error) { + ilk, ok := keys[shared.Ilk] + if !ok { + return "", shared.ErrMetadataMalformed{MissingData: shared.Ilk} + } + return ilk, nil +} diff --git a/pkg/transformers/storage_diffs/maker/vat/repository_test.go b/pkg/transformers/storage_diffs/maker/vat/repository_test.go new file mode 100644 index 00000000..fcee9e08 --- /dev/null +++ b/pkg/transformers/storage_diffs/maker/vat/repository_test.go @@ -0,0 +1,474 @@ +package vat_test + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker/vat" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/shared" + "github.com/vulcanize/vulcanizedb/test_config" +) + +var _ = Describe("Vat storage repository", func() { + var ( + db *postgres.DB + repo vat.VatStorageRepository + fakeBlockNumber = 123 + fakeBlockHash = "expected_block_hash" + fakeIlk = "fake_ilk" + fakeGuy = "fake_urn" + fakeUint256 = "12345" + ) + + BeforeEach(func() { + db = test_config.NewTestDB(test_config.NewTestNode()) + test_config.CleanTestDB(db) + repo = vat.VatStorageRepository{} + repo.SetDB(db) + }) + + Describe("dai", func() { + It("writes a row", func() { + daiMetadata := shared.StorageValueMetadata{ + Name: vat.Dai, + Keys: map[shared.Key]string{shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, daiMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type Dai struct { + BlockMetadata + Guy string + Dai string + } + var result Dai + err = db.Get(&result, `SELECT block_number, block_hash, guy, dai FROM maker.vat_dai`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Guy).To(Equal(fakeGuy)) + Expect(result.Dai).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing guy", func() { + malformedDaiMetadata := shared.StorageValueMetadata{ + Name: vat.Dai, + Keys: nil, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedDaiMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Guy})) + }) + }) + + Describe("gem", func() { + It("writes row", func() { + gemMetadata := shared.StorageValueMetadata{ + Name: vat.Gem, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk, shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, gemMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type Gem struct { + BlockMetadata + Ilk string + Guy string + Gem string + } + var result Gem + err = db.Get(&result, `SELECT block_number, block_hash, ilk, guy, gem FROM maker.vat_gem`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Ilk).To(Equal(fakeIlk)) + Expect(result.Guy).To(Equal(fakeGuy)) + Expect(result.Gem).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing ilk", func() { + malformedGemMetadata := shared.StorageValueMetadata{ + Name: vat.Gem, + Keys: map[shared.Key]string{shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedGemMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Ilk})) + }) + + It("returns error if metadata missing guy", func() { + malformedGemMetadata := shared.StorageValueMetadata{ + Name: vat.Gem, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedGemMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Guy})) + }) + }) + + Describe("ilk Art", func() { + It("writes row", func() { + ilkArtMetadata := shared.StorageValueMetadata{ + Name: vat.IlkArt, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, ilkArtMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type IlkArt struct { + BlockMetadata + Ilk string + Art string + } + var result IlkArt + err = db.Get(&result, `SELECT block_number, block_hash, ilk, art FROM maker.vat_ilk_art`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Ilk).To(Equal(fakeIlk)) + Expect(result.Art).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing ilk", func() { + malformedIlkArtMetadata := shared.StorageValueMetadata{ + Name: vat.IlkArt, + Keys: nil, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedIlkArtMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Ilk})) + }) + }) + + Describe("ilk Ink", func() { + It("writes row", func() { + ilkInkMetadata := shared.StorageValueMetadata{ + Name: vat.IlkInk, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, ilkInkMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type IlkInk struct { + BlockMetadata + Ilk string + Ink string + } + var result IlkInk + err = db.Get(&result, `SELECT block_number, block_hash, ilk, ink FROM maker.vat_ilk_ink`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Ilk).To(Equal(fakeIlk)) + Expect(result.Ink).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing ilk", func() { + malformedIlkInkMetadata := shared.StorageValueMetadata{ + Name: vat.IlkInk, + Keys: nil, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedIlkInkMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Ilk})) + }) + }) + + Describe("ilk rate", func() { + It("writes row", func() { + ilkRateMetadata := shared.StorageValueMetadata{ + Name: vat.IlkRate, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, ilkRateMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type IlkRate struct { + BlockMetadata + Ilk string + Rate string + } + var result IlkRate + err = db.Get(&result, `SELECT block_number, block_hash, ilk, rate FROM maker.vat_ilk_rate`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Ilk).To(Equal(fakeIlk)) + Expect(result.Rate).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing ilk", func() { + malformedIlkRateMetadata := shared.StorageValueMetadata{ + Name: vat.IlkRate, + Keys: nil, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedIlkRateMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Ilk})) + }) + }) + + Describe("ilk take", func() { + It("writes row", func() { + ilkTakeMetadata := shared.StorageValueMetadata{ + Name: vat.IlkTake, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, ilkTakeMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type IlkTake struct { + BlockMetadata + Ilk string + Take string + } + var result IlkTake + err = db.Get(&result, `SELECT block_number, block_hash, ilk, take FROM maker.vat_ilk_take`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Ilk).To(Equal(fakeIlk)) + Expect(result.Take).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing ilk", func() { + malformedIlkTakeMetadata := shared.StorageValueMetadata{ + Name: vat.IlkTake, + Keys: nil, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedIlkTakeMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Ilk})) + }) + }) + + Describe("sin", func() { + It("writes a row", func() { + sinMetadata := shared.StorageValueMetadata{ + Name: vat.Sin, + Keys: map[shared.Key]string{shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, sinMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type Sin struct { + BlockMetadata + Guy string + Sin string + } + var result Sin + err = db.Get(&result, `SELECT block_number, block_hash, guy, sin FROM maker.vat_sin`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Guy).To(Equal(fakeGuy)) + Expect(result.Sin).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing guy", func() { + malformedSinMetadata := shared.StorageValueMetadata{ + Name: vat.Sin, + Keys: nil, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedSinMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Guy})) + }) + }) + + Describe("urn art", func() { + It("writes row", func() { + urnArtMetadata := shared.StorageValueMetadata{ + Name: vat.UrnArt, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk, shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, urnArtMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type UrnArt struct { + BlockMetadata + Ilk string + Urn string + Art string + } + var result UrnArt + err = db.Get(&result, `SELECT block_number, block_hash, ilk, urn, art FROM maker.vat_urn_art`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Ilk).To(Equal(fakeIlk)) + Expect(result.Urn).To(Equal(fakeGuy)) + Expect(result.Art).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing ilk", func() { + malformedUrnArtMetadata := shared.StorageValueMetadata{ + Name: vat.UrnArt, + Keys: map[shared.Key]string{shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedUrnArtMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Ilk})) + }) + + It("returns error if metadata missing guy", func() { + malformedUrnArtMetadata := shared.StorageValueMetadata{ + Name: vat.UrnArt, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedUrnArtMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Guy})) + }) + }) + + Describe("urn ink", func() { + It("writes row", func() { + urnInkMetadata := shared.StorageValueMetadata{ + Name: vat.UrnInk, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk, shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, urnInkMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type UrnInk struct { + BlockMetadata + Ilk string + Urn string + Ink string + } + var result UrnInk + err = db.Get(&result, `SELECT block_number, block_hash, ilk, urn, ink FROM maker.vat_urn_ink`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Ilk).To(Equal(fakeIlk)) + Expect(result.Urn).To(Equal(fakeGuy)) + Expect(result.Ink).To(Equal(fakeUint256)) + }) + + It("returns error if metadata missing ilk", func() { + malformedUrnInkMetadata := shared.StorageValueMetadata{ + Name: vat.UrnInk, + Keys: map[shared.Key]string{shared.Guy: fakeGuy}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedUrnInkMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Ilk})) + }) + + It("returns error if metadata missing guy", func() { + malformedUrnInkMetadata := shared.StorageValueMetadata{ + Name: vat.UrnInk, + Keys: map[shared.Key]string{shared.Ilk: fakeIlk}, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, malformedUrnInkMetadata, fakeUint256) + + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(shared.ErrMetadataMalformed{MissingData: shared.Guy})) + }) + }) + + It("persists vat debt", func() { + debtMetadata := shared.StorageValueMetadata{ + Name: vat.VatDebt, + Keys: nil, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, debtMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type Debt struct { + BlockMetadata + Debt string + } + var result Debt + err = db.Get(&result, `SELECT block_number, block_hash, debt FROM maker.vat_debt`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Debt).To(Equal(fakeUint256)) + }) + + It("persists vat vice", func() { + viceMetadata := shared.StorageValueMetadata{ + Name: vat.VatVice, + Keys: nil, + Type: shared.Uint256, + } + + err := repo.Create(fakeBlockNumber, fakeBlockHash, viceMetadata, fakeUint256) + + Expect(err).NotTo(HaveOccurred()) + type Vice struct { + BlockMetadata + Vice string + } + var result Vice + err = db.Get(&result, `SELECT block_number, block_hash, vice FROM maker.vat_vice`) + Expect(err).NotTo(HaveOccurred()) + Expect(result.BlockNumber).To(Equal(fakeBlockNumber)) + Expect(result.BlockHash).To(Equal(fakeBlockHash)) + Expect(result.Vice).To(Equal(fakeUint256)) + }) +}) + +type BlockMetadata struct { + BlockNumber int `db:"block_number"` + BlockHash string `db:"block_hash"` +} diff --git a/pkg/transformers/storage_diffs/maker/vat/vat_suite_test.go b/pkg/transformers/storage_diffs/maker/vat/vat_suite_test.go new file mode 100644 index 00000000..89b079a0 --- /dev/null +++ b/pkg/transformers/storage_diffs/maker/vat/vat_suite_test.go @@ -0,0 +1,13 @@ +package vat_test + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestVat(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Vat Suite") +} diff --git a/pkg/transformers/storage_diffs/mappings.go b/pkg/transformers/storage_diffs/mappings.go index 6f3cb028..32bbe3b8 100644 --- a/pkg/transformers/storage_diffs/mappings.go +++ b/pkg/transformers/storage_diffs/mappings.go @@ -18,8 +18,10 @@ package storage_diffs import ( "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/shared" + "math/big" ) type Mappings interface { @@ -37,3 +39,21 @@ const ( IndexSix = "0000000000000000000000000000000000000000000000000000000000000006" IndexSeven = "0000000000000000000000000000000000000000000000000000000000000007" ) + +func GetMapping(indexOnContract, key string) common.Hash { + keyBytes := common.FromHex("0x" + key + indexOnContract) + encoded := crypto.Keccak256(keyBytes) + return common.BytesToHash(encoded) +} + +func GetNestedMapping(indexOnContract, primaryKey, secondaryKey string) common.Hash { + primaryMappingIndex := crypto.Keccak256(common.FromHex(primaryKey + indexOnContract)) + secondaryMappingIndex := crypto.Keccak256(common.FromHex(secondaryKey), primaryMappingIndex) + return common.BytesToHash(secondaryMappingIndex) +} + +func GetIncrementedKey(original common.Hash, incrementBy int64) common.Hash { + originalMappingAsInt := original.Big() + incremented := big.NewInt(0).Add(originalMappingAsInt, big.NewInt(incrementBy)) + return common.BytesToHash(incremented.Bytes()) +} diff --git a/pkg/transformers/storage_diffs/shared/errors.go b/pkg/transformers/storage_diffs/shared/errors.go index 3d74d4a9..29118a63 100644 --- a/pkg/transformers/storage_diffs/shared/errors.go +++ b/pkg/transformers/storage_diffs/shared/errors.go @@ -16,7 +16,9 @@ package shared -import "fmt" +import ( + "fmt" +) type ErrContractNotFound struct { Contract string @@ -36,6 +38,14 @@ func (e ErrHeaderMismatch) Error() string { return fmt.Sprintf("header hash in row does not match db at height %d - row: %s, db: %s", e.BlockHeight, e.DbHash, e.DiffHash) } +type ErrMetadataMalformed struct { + MissingData Key +} + +func (e ErrMetadataMalformed) Error() string { + return fmt.Sprintf("storage metadata malformed: missing %s", e.MissingData) +} + type ErrRowMalformed struct { Length int } diff --git a/pkg/transformers/storage_diffs/shared/value.go b/pkg/transformers/storage_diffs/shared/value.go index 965f301f..4bc59d7f 100644 --- a/pkg/transformers/storage_diffs/shared/value.go +++ b/pkg/transformers/storage_diffs/shared/value.go @@ -24,10 +24,11 @@ const ( Address ) -type Key int +type Key string const ( - Ilk Key = iota + Ilk Key = "ilk" + Guy Key = "guy" ) type StorageValueMetadata struct { @@ -35,3 +36,11 @@ type StorageValueMetadata struct { Keys map[Key]string Type ValueType } + +func GetStorageValueMetadata(name string, keys map[Key]string, t ValueType) StorageValueMetadata { + return StorageValueMetadata{ + Name: name, + Keys: keys, + Type: t, + } +} diff --git a/pkg/transformers/storage_transformers.go b/pkg/transformers/storage_transformers.go index ee811c66..b052798e 100644 --- a/pkg/transformers/storage_transformers.go +++ b/pkg/transformers/storage_transformers.go @@ -6,6 +6,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker" "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker/pit" + "github.com/vulcanize/vulcanizedb/pkg/transformers/storage_diffs/maker/vat" ) func GetPitStorageTransformer() storage.Transformer { @@ -15,3 +16,11 @@ func GetPitStorageTransformer() storage.Transformer { Repository: &pit.PitStorageRepository{}, } } + +func GetVatStorageTransformer() storage.Transformer { + return storage.Transformer{ + Address: common.HexToAddress(constants.VatContractAddress()), + Mappings: &vat.VatMappings{StorageRepository: &maker.MakerStorageRepository{}}, + Repository: &vat.VatStorageRepository{}, + } +}