Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions subgraph/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type RailgunProtocolStats @entity(immutable: false) {

shield: RailgunOperationStats!
unshield: RailgunOperationStats!
transact: RailgunOperationStats!
}

type RailgunShieldTokenStats @entity(immutable: false) {
Expand Down Expand Up @@ -76,18 +77,6 @@ type RailgunShieldCiphertext @entity(immutable: true) {
shieldKey: Bytes!
}

type RailgunNullified @entity(immutable: true) {
id: ID!
treeNumber: Int!

nullifiers: [Bytes!]!

blockNumber: BigInt!
timestamp: BigInt!
txHash: Bytes!
gasUsed: BigInt!
}

type RailgunUnshield @entity(immutable: true) {
id: ID!
to: Bytes!
Expand Down Expand Up @@ -118,6 +107,7 @@ type RailgunTransact @entity(immutable: true) {
timestamp: BigInt!
txHash: Bytes!
gasUsed: BigInt!
gasPrice: BigInt!
}

type RailgunTransactCiphertext @entity(immutable: true) {
Expand Down
87 changes: 80 additions & 7 deletions subgraph/src/railgun-smart-wallet.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { BigInt, Bytes } from "@graphprotocol/graph-ts";

import { Shield as ShieldEvent, Unshield as UnshieldEvent } from "../generated/RailgunSmartWallet/RailgunSmartWallet";
import {
Shield as ShieldEvent,
Unshield as UnshieldEvent,
Transact as TransactEvent,
} from "../generated/RailgunSmartWallet/RailgunSmartWallet";
import {
RailgunShield,
RailgunCommitment,
Expand All @@ -10,6 +14,8 @@ import {
RailgunShieldTokenStats,
RailgunUnshieldTokenStats,
RailgunUnshield,
RailgunTransact,
RailgunTransactCiphertext,
} from "../generated/schema";

function createOrLoadProtocolStats(): RailgunProtocolStats {
Expand All @@ -23,6 +29,7 @@ function createOrLoadProtocolStats(): RailgunProtocolStats {

const shieldStats = new RailgunOperationStats(`${id}-shield`);
const unshieldStats = new RailgunOperationStats(`${id}-unshield`);
const transactStats = new RailgunOperationStats(`${id}-transact`);

stats.shield = shieldStats.id;
shieldStats.totalCount = BigInt.fromI32(0);
Expand All @@ -32,9 +39,14 @@ function createOrLoadProtocolStats(): RailgunProtocolStats {
unshieldStats.totalCount = BigInt.fromI32(0);
unshieldStats.totalGasUsed = BigInt.fromI32(0);

stats.transact = transactStats.id;
Comment thread
NicoSerranoP marked this conversation as resolved.
transactStats.totalCount = BigInt.fromI32(0);
transactStats.totalGasUsed = BigInt.fromI32(0);

stats.save();
shieldStats.save();
unshieldStats.save();
transactStats.save();
}

return stats;
Expand Down Expand Up @@ -82,7 +94,7 @@ export function handleShield(event: ShieldEvent): void {
const shield = new RailgunShield(id);
const stats = createOrLoadProtocolStats();

stats.totalTxCount = stats.totalTxCount.plus(BigInt.fromI32(1));
stats.totalTxCount = stats.totalTxCount.plus(BigInt.fromI32(event.params.commitments.length));

if (event.receipt !== null) {
stats.totalGasUsed = stats.totalGasUsed.plus(event.receipt!.gasUsed);
Expand All @@ -91,12 +103,10 @@ export function handleShield(event: ShieldEvent): void {
const shieldStats = RailgunOperationStats.load(stats.shield);

if (shieldStats !== null) {
shieldStats.totalCount = shieldStats.totalCount.plus(BigInt.fromI32(1));
shieldStats.totalCount = shieldStats.totalCount.plus(BigInt.fromI32(event.params.commitments.length));

if (event.receipt !== null) {
shieldStats.totalGasUsed = shieldStats.totalGasUsed.plus(event.receipt!.gasUsed);
} else {
shieldStats.totalGasUsed = shieldStats.totalGasUsed.plus(BigInt.fromI32(0));
}

shieldStats.save();
Expand Down Expand Up @@ -189,8 +199,6 @@ export function handleUnshield(event: UnshieldEvent): void {

if (event.receipt !== null) {
unshieldStats.totalGasUsed = unshieldStats.totalGasUsed.plus(event.receipt!.gasUsed);
} else {
unshieldStats.totalGasUsed = unshieldStats.totalGasUsed.plus(BigInt.fromI32(0));
}

unshieldStats.save();
Expand Down Expand Up @@ -233,3 +241,68 @@ export function handleUnshield(event: UnshieldEvent): void {

unshield.save();
}

export function handleTransact(event: TransactEvent): void {
const id = `${event.transaction.hash.toHex()}-${event.logIndex.toString()}`;

const transact = new RailgunTransact(id);
const stats = createOrLoadProtocolStats();

stats.totalTxCount = stats.totalTxCount.plus(BigInt.fromI32(1));

if (event.receipt !== null) {
stats.totalGasUsed = stats.totalGasUsed.plus(event.receipt!.gasUsed);
}

const transactStats = RailgunOperationStats.load(stats.transact);

if (transactStats !== null) {
transactStats.totalCount = transactStats.totalCount.plus(BigInt.fromI32(event.params.hash.length));

if (event.receipt !== null) {
transactStats.totalGasUsed = transactStats.totalGasUsed.plus(event.receipt!.gasUsed);
Comment thread
NicoSerranoP marked this conversation as resolved.
}

transactStats.save();
}

stats.save();

transact.treeNumber = event.params.treeNumber;
transact.startPosition = event.params.startPosition;
transact.hash = event.params.hash;

transact.blockNumber = event.block.number;
transact.timestamp = event.block.timestamp;
transact.txHash = event.transaction.hash;

if (event.receipt !== null) {
transact.gasUsed = event.receipt!.gasUsed;
}

transact.gasPrice = event.transaction.gasPrice;

const ciphertexts = event.params.ciphertext;

for (let index = 0; index < ciphertexts.length; index += 1) {
const ctId = `${id}-ct-${index.toString()}`;
const cipher = new RailgunTransactCiphertext(ctId);

cipher.transact = id;

const bundle = ciphertexts[index].ciphertext;
cipher.ciphertext0 = bundle[0];
cipher.ciphertext1 = bundle[1];
cipher.ciphertext2 = bundle[2];
cipher.ciphertext3 = bundle[3];

cipher.blindedReceiverViewingKey = ciphertexts[index].blindedReceiverViewingKey;
cipher.blindedSenderViewingKey = ciphertexts[index].blindedSenderViewingKey;
cipher.annotationData = ciphertexts[index].annotationData;
cipher.memo = ciphertexts[index].memo;

cipher.save();
}

transact.save();
}
8 changes: 3 additions & 5 deletions subgraph/subgraph.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ dataSources:
language: wasm/assemblyscript
entities:
- Shield
- Nullified
- Unshield
- Transact
abis:
Expand All @@ -30,8 +29,7 @@ dataSources:
- event: Unshield(address,(uint8,address,uint256),uint256,uint256)
handler: handleUnshield
receipt: true
# - event: Nullified(uint16,bytes32[])
# handler: handleNullified
# - event: Transact(uint256,uint256,bytes32[],(bytes32[4],bytes32,bytes32,bytes,bytes)[])
# handler: handleTransact
- event: Transact(uint256,uint256,bytes32[],(bytes32[4],bytes32,bytes32,bytes,bytes)[])
handler: handleTransact
receipt: true
file: ./src/railgun-smart-wallet.ts
65 changes: 65 additions & 0 deletions subgraph/tests/railgun-smart-wallet-transact.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { BigInt, Bytes } from "@graphprotocol/graph-ts";
import { assert, describe, test, clearStore, beforeAll, afterAll } from "matchstick-as/assembly/index";

import { handleTransact } from "../src/railgun-smart-wallet";

import { createTransactEvent, createTransactCiphertextTuple } from "./railgun-smart-wallet-utils";

describe("Transact event tests", () => {
beforeAll(() => {
const ciphertextTuple = createTransactCiphertextTuple(
[
Bytes.fromHexString("0x01"),
Bytes.fromHexString("0x02"),
Bytes.fromHexString("0x03"),
Bytes.fromHexString("0x04"),
],
Bytes.fromHexString("0x10"),
Bytes.fromHexString("0x20"),
Bytes.fromHexString("0xaa"),
Bytes.fromHexString("0xbb"),
);

const event = createTransactEvent(
BigInt.fromI32(1),
BigInt.fromI32(0),
[Bytes.fromHexString("0x1234")],
[ciphertextTuple],
);

handleTransact(event);
});

afterAll(() => {
clearStore();
});

test("RailgunTransact created", () => {
assert.entityCount("RailgunTransact", 1);
});

test("Ciphertext entity created", () => {
assert.entityCount("RailgunTransactCiphertext", 1);
});

test("Ciphertext fields stored correctly", () => {
const id = "0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1-ct-0";

assert.fieldEquals("RailgunTransactCiphertext", id, "ciphertext0", "0x01");
assert.fieldEquals("RailgunTransactCiphertext", id, "ciphertext1", "0x02");
assert.fieldEquals("RailgunTransactCiphertext", id, "ciphertext2", "0x03");
assert.fieldEquals("RailgunTransactCiphertext", id, "ciphertext3", "0x04");

assert.fieldEquals("RailgunTransactCiphertext", id, "blindedSenderViewingKey", "0x10");

assert.fieldEquals("RailgunTransactCiphertext", id, "blindedReceiverViewingKey", "0x20");
});

test("Protocol stats updated", () => {
assert.fieldEquals("RailgunProtocolStats", "railgun-protocol-stats", "totalTxCount", "1");
});

test("Operation stats updated (transact)", () => {
assert.fieldEquals("RailgunOperationStats", "railgun-protocol-stats-transact", "totalCount", "1");
});
});
37 changes: 36 additions & 1 deletion subgraph/tests/railgun-smart-wallet-utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ethereum, BigInt, Address, Bytes } from "@graphprotocol/graph-ts";
import { newMockEvent } from "matchstick-as";

import { Shield, Unshield } from "../generated/RailgunSmartWallet/RailgunSmartWallet";
import { Shield, Transact, Unshield } from "../generated/RailgunSmartWallet/RailgunSmartWallet";

export function createShieldEvent(
treeNumber: BigInt,
Expand Down Expand Up @@ -88,3 +88,38 @@ export function createUnshieldEvent(

return event;
}

export function createTransactCiphertextTuple(
ciphertext: Bytes[],
blindedSenderViewingKey: Bytes,
blindedReceiverViewingKey: Bytes,
annotationData: Bytes,
memo: Bytes,
): ethereum.Tuple {
const tuple = new ethereum.Tuple();

tuple.push(ethereum.Value.fromFixedBytesArray(ciphertext));
tuple.push(ethereum.Value.fromFixedBytes(blindedSenderViewingKey));
tuple.push(ethereum.Value.fromFixedBytes(blindedReceiverViewingKey));
tuple.push(ethereum.Value.fromBytes(annotationData));
tuple.push(ethereum.Value.fromBytes(memo));

return tuple;
}

export function createTransactEvent(
treeNumber: BigInt,
startPosition: BigInt,
hashes: Bytes[],
ciphertexts: ethereum.Tuple[],
): Transact {
const event = changetype<Transact>(newMockEvent());
event.parameters = [];

event.parameters.push(new ethereum.EventParam("treeNumber", ethereum.Value.fromUnsignedBigInt(treeNumber)));
event.parameters.push(new ethereum.EventParam("startPosition", ethereum.Value.fromUnsignedBigInt(startPosition)));
event.parameters.push(new ethereum.EventParam("hash", ethereum.Value.fromFixedBytesArray(hashes)));
event.parameters.push(new ethereum.EventParam("ciphertext", ethereum.Value.fromTupleArray(ciphertexts)));

return event;
}
Loading