Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add incentivization PoC for RLNaaS in Lightpush #3166

Open
wants to merge 22 commits into
base: master
Choose a base branch
from

Conversation

s-tikhomirov
Copy link
Contributor

@s-tikhomirov s-tikhomirov commented Nov 1, 2024

Description

This WIP PR implements a PoC for light protocol incentivization as outlined in:

Changes

  • cherry-pick prior PoC work from an experimental branch
  • remove the dummy protocol (not needed anymore)
  • implement the required transaction checks (payment amount, address)
  • avoid hard-coded parameters (in the main code, not in tests)
  • track used txids server-side to avoid double spend
  • integrate with Lightpush

Some items (especially those closer to the end of this list) may be moved to later PRs to keep change sets relatively small.

@s-tikhomirov s-tikhomirov changed the title [WIP] Add incentivization PoC for RLNaaS in Lightpush [WIP] feat: Add incentivization PoC for RLNaaS in Lightpush Nov 1, 2024
@s-tikhomirov s-tikhomirov changed the title [WIP] feat: Add incentivization PoC for RLNaaS in Lightpush feat: Add incentivization PoC for RLNaaS in Lightpush Nov 1, 2024
Copy link

github-actions bot commented Nov 1, 2024

You can find the image built from this PR at

quay.io/wakuorg/nwaku-pr:3166

Built from c5f7990

@s-tikhomirov s-tikhomirov force-pushed the feat/incentivization-poc-txid-check branch from 24f9aa8 to 3bf670b Compare November 28, 2024 06:23
@Ivansete-status
Copy link
Collaborator

@s-tikhomirov - is there anything blocking this PR?

@s-tikhomirov
Copy link
Contributor Author

@s-tikhomirov - is there anything blocking this PR?

Good question.

On the one hand, there are still things to implement before this can be considered a fully-fledged PoC. For example, the properties of a transaction that is checked for "eligibility" are now simply hard-coded. In the final vision, those should be node-specific and stored in a config file or something like that (and I'd have to figure out where such files should be located, how to manage them, etc). On the other hand, the current version is more or less self-contained, and in the spirit of merging things incrementally, I could see this PR at least considered for review.

For context: the overall vision of this PoC is that a client would attach a txid as proof of payment alongside its Lightpush request, and the server would check for eligibility of that txid. By eligibility we mean that the transaction:

  • has been confirmed;
  • is not a contract creation transaction;
  • pays the expected amount;
  • pays to the expected destination;
  • hasn't been used in a previous request.

Here is what is implemented now:

  • check that the tx has been confirmed;
  • check that the tx is a simple transfer (not a contract creation and not a contract call);
  • check that the amount is "expected" (a hard-coded amount from a totally random tx used in tests);
  • check that the destination is "expected" (also hard-coded, same as with the amount).

These could be the next steps:

  • avoid hard-coded values (use server-specific expected amounts and destinations);
  • use token transfer transactions and not simple transfers (as described here; I'm using simple transfers now for simplicity);
  • account for double-spent txids;
  • avoid hard-coded Infura endpoint for querying the blockchain;
  • attach this to Lightpush (behind a feature flag).

Given this, do you think it makes sense to consider this PR for review as it stands now?

@jm-clius , WDYT?

@jm-clius
Copy link
Contributor

jm-clius commented Dec 5, 2024

Without having looked at the code itself yet, based on your description I would certainly suggest opening for review - or even selecting a smaller increment that illustrates a specific function and creating a PR for that. This way we can show the POC growing, remain clear about next steps and what is WIP, while making the turnaround from PR to merge shorter due to the easier review burden on nwaku contributors.

Copy link
Contributor

@gabrielmer gabrielmer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work! Thanks so much! 🤩

I added some questions and comments, please let me know if I'm missing anything in any of them :)

I also see that the Lint CI job is failing, please try installing the latest version of https://github.com/arnetheduck/nph/tree/latest and integrate it with your IDE (let me know if you have any issues with it, I can help out!)

waku/incentivization/common.nim Outdated Show resolved Hide resolved
waku/incentivization/rpc_codec.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
tests/incentivization/test_poc.nim Outdated Show resolved Hide resolved
Copy link
Collaborator

@Ivansete-status Ivansete-status left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for it!
I just added some nitpick comment that I hope you find useful

tests/incentivization/test_poc.nim Show resolved Hide resolved
tests/incentivization/test_poc.nim Show resolved Hide resolved
waku/incentivization/eligibility.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
Copy link
Contributor

@jm-clius jm-clius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Added a couple of initial comments to address below.

waku/incentivization/eligibility.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved

import waku/incentivization/rpc

proc genEligibilityStatus*(isEligible: bool): EligibilityStatus =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to me to be interesting only for tests? In other words, this should form part of the test files as a helper function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was, on the contrary, that this function (renamed to new in later commits) would be useful for future code that would use our eligibility logic to convert a boolean eligibility value into EligibilityStatus that will be attached to the response. Something like this:

let proof = ... # extract eligibility proof (not necessarily a txid) from the request
let isValid = isEligible(proof, ...) # check proof eligibility
let eligibilityStatus = new(EligibilityStatus, isValid)
let response = LightpushResponse(eligibilityStatus, ...) # generate response
return response # (send the response back to the client)

Does it make sense?

@s-tikhomirov s-tikhomirov force-pushed the feat/incentivization-poc-txid-check branch 2 times, most recently from b3890ca to d865b1a Compare December 13, 2024 16:57
@s-tikhomirov s-tikhomirov force-pushed the feat/incentivization-poc-txid-check branch from 35e2479 to ae9fb73 Compare December 13, 2024 18:09
@s-tikhomirov
Copy link
Contributor Author

Re-requesting reviews after addressing the suggestions (one suggestion remains unresolved, but it shouldn't be a blocker).

Copy link
Contributor

@gabrielmer gabrielmer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooh looks great! 🤩

I added comments on some last small details - overall looks amazing! Thanks so much!

lmk in case anything I proposed doesn't make sense :))

waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
waku/incentivization/txid_proof.nim Outdated Show resolved Hide resolved
@s-tikhomirov s-tikhomirov force-pushed the feat/incentivization-poc-txid-check branch from 7ac3d0e to ae9fb73 Compare December 17, 2024 18:16
@s-tikhomirov s-tikhomirov force-pushed the feat/incentivization-poc-txid-check branch from 758fe5f to af16879 Compare December 20, 2024 11:29
@gabrielmer gabrielmer self-requested a review December 20, 2024 14:52
Copy link
Contributor

@gabrielmer gabrielmer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks greatt! Thanks so much! 🤩

Copy link
Collaborator

@Ivansete-status Ivansete-status left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for it! I've added some nitpick comments that I hope you find useful
I'm happy to re-review later on :) Ping me if need any clarification 🥳


# To set up the environment variable (replace Infura with your provider if needed):
# $ export WEB3_RPC_URL="https://sepolia.infura.io/v3/YOUR_API_KEY"
const EthClient = os.getEnv("WEB3_RPC_URL")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is generally better to avoid external dependencies in tests. I suggest taking a look on how Anvil is being used in other RLN tests.

For example, tests/waku_rln_relay/test_rln_group_manager_onchain.nim and waku/waku_rln_relay/constants.nim can serve as a good reference :) ( notice EthClient* = "http://127.0.0.1:8540" is defined in constants and it deals with a local Anvil instance )

Comment on lines +12 to +19
const TxHashNonExisting* =
TxHash.fromHex("0x0000000000000000000000000000000000000000000000000000000000000000")
const TxHashContractCreation* =
TxHash.fromHex("0xa2e39bee557144591fb7b2891ef44e1392f86c5ba1fc0afb6c0e862676ffd50f")
const TxHashContractCall* =
TxHash.fromHex("0x2761f066eeae9a259a0247f529133dd01b7f57bf74254a64d897433397d321cb")
const TxHashSimpleTransfer* =
TxHash.fromHex("0xa3985984b2ec3f1c3d473eb57a4820a56748f25dabbf9414f2b8380312b439cc")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think no need to be public

Suggested change
const TxHashNonExisting* =
TxHash.fromHex("0x0000000000000000000000000000000000000000000000000000000000000000")
const TxHashContractCreation* =
TxHash.fromHex("0xa2e39bee557144591fb7b2891ef44e1392f86c5ba1fc0afb6c0e862676ffd50f")
const TxHashContractCall* =
TxHash.fromHex("0x2761f066eeae9a259a0247f529133dd01b7f57bf74254a64d897433397d321cb")
const TxHashSimpleTransfer* =
TxHash.fromHex("0xa3985984b2ec3f1c3d473eb57a4820a56748f25dabbf9414f2b8380312b439cc")
const TxHashNonExisting =
TxHash.fromHex("0x0000000000000000000000000000000000000000000000000000000000000000")
const TxHashContractCreation =
TxHash.fromHex("0xa2e39bee557144591fb7b2891ef44e1392f86c5ba1fc0afb6c0e862676ffd50f")
const TxHashContractCall =
TxHash.fromHex("0x2761f066eeae9a259a0247f529133dd01b7f57bf74254a64d897433397d321cb")
const TxHashSimpleTransfer =
TxHash.fromHex("0xa3985984b2ec3f1c3d473eb57a4820a56748f25dabbf9414f2b8380312b439cc")

Comment on lines +75 to +76
check:
isEligible.isOk()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this particular case I think is better to use the assert approach

Suggested change
check:
isEligible.isOk()
assert isEligible.isOk(), isEligible.error


import waku/incentivization/[rpc, txid_proof]

proc new*(T: type EligibilityStatus, isEligible: bool): T =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By Nim convention, the object types (stack allocated) should be created with init. The new word should be reserved for only ref objects (heap allocated.)

Suggested change
proc new*(T: type EligibilityStatus, isEligible: bool): T =
proc init*(T: type EligibilityStatus, isEligible: bool): T =

@@ -0,0 +1,9 @@
import std/options, chronos
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe not needed chronos?

Suggested change
import std/options, chronos
import std/options

return err("Eligibility proof is empty")
var web3: Web3
try:
web3 = await newWeb3(ethClient)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a new instance of web3 for every call to isEligibleTxId doesn't sound very efficient. I believe it is better to do that once, when the app starts, and only close the web3 instance at the app's end.

I'd suggest creating a new type EligibilityManager that contains the web3 instance.

return err($errorMsg)
# check that it is not a contract creation tx
let toAddressOption = txReceipt.to
if toAddressOption.isNone:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick comment: by convention, the "verbs" should always have parenthesis when using them

Suggested change
if toAddressOption.isNone:
if toAddressOption.isNone():

await allFutures(txFuture, receiptFuture)
let tx = txFuture.read()
let txReceipt = receiptFuture.read()
if txReceipt.isErr:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if txReceipt.isErr:
if txReceipt.isErr():

let tx = txFuture.read()
let txReceipt = receiptFuture.read()
if txReceipt.isErr:
return err("Cannot get tx receipt")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this particular case we can also append the error description

Suggested change
return err("Cannot get tx receipt")
return err("Cannot get tx receipt: " & txReceipt.error)

## in the context of service incentivization PoC,
## if it is confirmed and pays the expected amount to the server's address.
## See spec: https://github.com/waku-org/specs/blob/master/standards/core/incentivization.md
if eligibilityProof.proofOfPayment.isNone:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if eligibilityProof.proofOfPayment.isNone:
if eligibilityProof.proofOfPayment.isNone():

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants