-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add simple txid-based eligibility check with hard-coded params (#…
- Loading branch information
1 parent
1b532e8
commit 13144bc
Showing
8 changed files
with
169 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
import ./test_rpc_codec | ||
import | ||
./test_rpc_codec, | ||
./test_poc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
{.used.} | ||
|
||
import | ||
std/[options, strscans], | ||
testutils/unittests, | ||
chronicles, | ||
chronos, | ||
libp2p/crypto/crypto, | ||
web3 | ||
|
||
import | ||
waku/[node/peer_manager, waku_core], | ||
../testlib/[assertions, wakucore, testasync, futures, testutils], | ||
waku/incentivization/[rpc, rpc_codec, common, txid_proof, eligibility] | ||
|
||
# All txids from Ethereum Sepolia testnet | ||
const TxHashNonExisting* = | ||
TxHash.fromHex("0x0000000000000000000000000000000000000000000000000000000000000000") | ||
const TxHashContractCreation* = | ||
TxHash.fromHex("0xa2e39bee557144591fb7b2891ef44e1392f86c5ba1fc0afb6c0e862676ffd50f") | ||
const TxHashContractCall* = | ||
TxHash.fromHex("0x2761f066eeae9a259a0247f529133dd01b7f57bf74254a64d897433397d321cb") | ||
const TxHashSimpleTransfer* = | ||
TxHash.fromHex("0xa3985984b2ec3f1c3d473eb57a4820a56748f25dabbf9414f2b8380312b439cc") | ||
|
||
const EthClient = "https://sepolia.infura.io/v3/470c2e9a16f24057aee6660081729fb9" | ||
|
||
suite "Waku Incentivization PoC Eligibility Proofs": | ||
|
||
asyncTest "incentivization PoC: non-existent tx is not eligible": | ||
let eligibilityProof = | ||
EligibilityProof(proofOfPayment: some(@(TxHashNonExisting.bytes()))) | ||
let txIsEligible = await isEligible(eligibilityProof, EthClient) | ||
check: | ||
not txIsEligible | ||
|
||
asyncTest "incentivization PoC: contract creation tx is not eligible": | ||
let eligibilityProof = | ||
EligibilityProof(proofOfPayment: some(@(TxHashContractCreation.bytes()))) | ||
let txIsEligible = await isEligible(eligibilityProof, EthClient) | ||
check: | ||
not txIsEligible | ||
|
||
asyncTest "incentivization PoC: contract call tx is not eligible": | ||
# note: assuming payment in native currency (ETH), not a token | ||
let eligibilityProof = | ||
EligibilityProof(proofOfPayment: some(@(TxHashContractCall.bytes()))) | ||
let txIsEligible = await isEligible(eligibilityProof, EthClient) | ||
check: | ||
not txIsEligible | ||
|
||
asyncTest "incentivization PoC: simple transfer tx is eligible": | ||
let eligibilityProof = | ||
EligibilityProof(proofOfPayment: some(@(TxHashSimpleTransfer.bytes()))) | ||
let txIdExists = await isEligible(eligibilityProof, EthClient) | ||
check: | ||
txIdExists | ||
|
||
# TODO: add tests for simple transfer txs with wrong amount and wrong receiver |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,35 @@ | ||
import | ||
std/options, | ||
std/strscans, | ||
testutils/unittests, | ||
chronicles, | ||
chronos, | ||
libp2p/crypto/crypto | ||
libp2p/crypto/crypto, | ||
web3 | ||
|
||
import | ||
waku/incentivization/[ | ||
rpc, | ||
rpc_codec, | ||
common | ||
] | ||
|
||
import waku/incentivization/rpc, waku/incentivization/rpc_codec | ||
|
||
suite "Waku Incentivization Eligibility Codec": | ||
asyncTest "encode eligibility proof": | ||
var byteSequence: seq[byte] = @[1, 2, 3, 4, 5, 6, 7, 8] | ||
let epRpc = EligibilityProof(proofOfPayment: some(byteSequence)) | ||
let encoded = encode(epRpc) | ||
|
||
asyncTest "encode eligibility proof from txid": | ||
let txHash = TxHash.fromHex( | ||
"0x0000000000000000000000000000000000000000000000000000000000000000") | ||
let txHashAsBytes = @(txHash.bytes()) | ||
let eligibilityProof = EligibilityProof(proofOfPayment: some(txHashAsBytes)) | ||
let encoded = encode(eligibilityProof) | ||
let decoded = EligibilityProof.decode(encoded.buffer).get() | ||
check: | ||
epRpc == decoded | ||
|
||
eligibilityProof == decoded | ||
asyncTest "encode eligibility status": | ||
let esRpc = EligibilityStatus(statusCode: uint32(200), statusDesc: some("OK")) | ||
let encoded = encode(esRpc) | ||
let eligibilityStatus = genEligibilityStatus(true) | ||
let encoded = encode(eligibilityStatus) | ||
let decoded = EligibilityStatus.decode(encoded.buffer).get() | ||
check: | ||
esRpc == decoded | ||
eligibilityStatus == decoded | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import std/options | ||
|
||
import waku/incentivization/rpc | ||
|
||
proc genEligibilityStatus*(isEligible: bool): EligibilityStatus = | ||
if isEligible: | ||
EligibilityStatus( | ||
statusCode: uint32(200), | ||
statusDesc: some("OK")) | ||
else: | ||
EligibilityStatus( | ||
statusCode: uint32(402), | ||
statusDesc: some("Payment Required")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import std/options, chronos | ||
|
||
import waku/incentivization/[rpc, txid_proof] | ||
|
||
proc isEligible*(eligibilityProof: EligibilityProof, ethClient: string): Future[bool] {.async.} = | ||
result = await txidEligiblityCriteriaMet(eligibilityProof, ethClient) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import std/options, chronos, web3, stew/byteutils, stint, strutils | ||
|
||
import waku/incentivization/rpc | ||
|
||
|
||
# Function to convert a hex string to Address | ||
proc toAddress*(hexStr: string): Address = | ||
# Remove the "0x" prefix if it exists | ||
let cleaned = if hexStr.startsWith("0x"): hexStr[2..^1] else: hexStr | ||
|
||
# Ensure the length is exactly 40 characters (20 bytes) | ||
if cleaned.len != 40: | ||
raise newException(ValueError, "Invalid hexadecimal string length for Address") | ||
|
||
var arr: array[20, byte] | ||
for i in 0 ..< 20: | ||
let byteValue = cleaned[i * 2 ..< i * 2 + 2] # Get two hex characters | ||
arr[i] = byte(parseHexInt(byteValue)) | ||
|
||
result = Address(arr) | ||
|
||
|
||
proc checkTxIdIsEligible(txHash: TxHash, ethClient: string): Future[bool] {.async.} = | ||
let web3 = await newWeb3(ethClient) | ||
try: | ||
let tx = await web3.provider.eth_getTransactionByHash(txHash) | ||
let txReceipt = await web3.getMinedTransactionReceipt(txHash) | ||
result = true | ||
if result: | ||
# check that it is not a contract creation tx | ||
let toAddressOption = txReceipt.to | ||
let isContractCreationTx = toAddressOption.isNone | ||
if isContractCreationTx: | ||
result = false | ||
else: | ||
# check that it is a simple transfer (not a contract call) | ||
# a simple transfer uses 21000 gas | ||
let gasUsed = txReceipt.gasUsed | ||
let isSimpleTransferTx = (gasUsed == Quantity(21000)) | ||
if not isSimpleTransferTx: | ||
result = false | ||
else: | ||
# check that the amount is "as expected" (hard-coded for now) | ||
let txValue = tx.value | ||
let hasExpectedValue = (txValue == 200500000000005063.u256) | ||
# check that the to address is "as expected" (hard-coded for now) | ||
let toAddress = toAddressOption.get() | ||
let hasExpectedToAddress = (toAddress == toAddress("0x5e809a85aa182a9921edd10a4163745bb3e36284")) | ||
result = true | ||
except ValueError as e: | ||
result = false | ||
await web3.close() | ||
result | ||
|
||
proc txidEligiblityCriteriaMet*( | ||
eligibilityProof: EligibilityProof, ethClient: string | ||
): Future[bool] {.async.} = | ||
if eligibilityProof.proofOfPayment.isNone(): | ||
return false | ||
let txHash = TxHash.fromHex(byteutils.toHex(eligibilityProof.proofOfPayment.get())) | ||
let txExists = await checkTxIdIsEligible(txHash, ethClient) | ||
return txExists |