papacarp / pooltool.io

A public repo to keep track of issues and feature requests in pooltool
76 stars 75 forks source link

Sending slots - need information and documentation #181

Closed NEVdataDyne closed 1 year ago

NEVdataDyne commented 1 year ago

I am trying to send my pool allocated slots to PoolTool without using CNCLI.

There are some scripts in this repository but...

The send_slots.sh script uses Jörmungandr and I am not even sure what that is… Some kind of legacy Cardano node? Some kind of generic node to make other blockchains? I found the IOHK official page and github but it is not clear to me. I think the same result could be achieved using the leadership-schedule query instead of using Jörmungandr but I didn’t find any documentation on the json format PoolTool wants, especially the format of the slots list to be encrypted so I am a bit stuck.

The send_slots_override.sh script makes me wonder why one would send the slot list anyway instead of the amount of slots for each epoch. If PoolTool accepts the amount of slots per epoch only instead of the whole list, I'd rather use send_slots_override.sh as an example... But I am running into issues when testing that approach. I can’t figure out what is the “userid” that is supposed to be sent. Everywhere it says something like “GET THIS FROM YOUR ACCOUNT PROFILE PAGE ON POOLTOOL WEBSITE” but on my profile page I have a nickname and no userid.

I tried to send the following data with send_slots_override.sh {“currentepoch”:“425”,“poolid”:“8dcdf33740ee8e9da6e36337d875fb9222f5c8a1a315fda36886c615”,“genesispref”:“8e4d2a343f3dcf93”,“userid”:“Cassandra”,“assigned_slots”:“2”} With userid being -My nickname -The pool api key -The Zapier API key (on my profile page) -The stake address I use to log in in both formats

I always get the following response {“message”: “Internal server error”}

And if I don’t put a userid {“success”: false, “message”: {“error”: “userid not found in json data”}}

In CNCLI, PoolTool data consist of the pool API key, pool id and pool ticker so I suppose the userid should be the pool api key…?

So my questions are

rphair commented 1 year ago

also this aroused some curiosity on the Cardano Forum... https://forum.cardano.org/t/pooltool-send-slots-without-cncli/120051

papacarp commented 1 year ago

Some of the scripts you see in the repository are from a long time ago on a previous version of the network.

We now use API keys rather than userids.

The format of sendslots is as follows

Epoch 1. -zenshows needs just a qty of blocks you will make in epoch 1. However, for validation purposes we also ask you to send us a hash of your slot list for this epoch 1 as well. Since this is your first epoch sending slots no other information is required.

Epoch 2.
-you send us a qty of blocks you will make in Epoch 2 along with a hash of your slot list for epoch 2. In addition you send us the original list of slots from epoch 1 and we run our own hash on it and compare it to the hash you sent us during epoch 1. If they match you are all good. If they do not match then we throw everything out.

Epoch 3...
-this continues just like epoch 2.

So to proceed with this process you'll need an API key that you can get by verifying your ownership of your pool rewards address on the pooltool website. I think the node can give us leaderlogs so we can experiment with how to modify the python or bash scripts to use this.

Josef3110 commented 1 year ago

Well, with that description the part for the [prevSlots] part can be saved in a json file somewhere to be used for the next epoch.

NEVdataDyne commented 1 year ago

Thank you for your answer.

Can you provide the format of the slot list before encryption so I can try to convert what is returned by the cardano-cli leadership-schedule query into that specific format?

papacarp commented 1 year ago

Great! I was just putting this together and you beat me to it. Here is what you need.

https://github.com/input-output-hk/cardano-node/blob/master/doc/stake-pool-operations/9_leadership_schedule.md

The slot list should be: a stringified json encoded array of slot numbers. Note no slots should be the string [].

to verify its valid json we parse it like this: js = JSON.parse(request.prevSlots);

the hash of the slots is done like this (on the original stringified version): console.log("verify slots") var output = new Uint8Array(32) var input = Buffer.from(request.prevSlots) var hash = blake2b(output.length).update(input).digest('hex')

papacarp commented 1 year ago

You will be posting to the /sendslots api endpoint. We lock out updates to slots outside of the epoch boundaries, but when you are ready I can setup an exception for your pool during experimenting.

You will always need to post the following:

poolId: hex pool id
apiKey: uuid api key assigned to your pool id
epoch: the epoch you are loading slots for - should be the current epoch
slotQty: the number of lots you expect to make in the epoch
hash: the blake2b hash of the stringified json array of your slots for the current epoch

If you are verifying a previous set of slots (you can only verify the previous epoch slots) the you will also provide prevSlots

prevSlots: stringified array of your slots for the previous epoch (used to verify)

PoolTool will also complain if you try to load slots multiple times in an epoch, as mentioned, when you get to the point of debugging I can work with you to open things up and make it easier to test for your pool.

papacarp commented 1 year ago

just referencing this here because its awesome: Thank you @Josef3110

https://github.com/Josef3110/stakepool_python_tools/blob/main/scripts/sendslots.py

TerminadaPool commented 1 year ago

I am somewhat philosophically opposed to turning this into an expectation for all pool operators for the reasons I stated in this post on the cardano forum.

Nevertheless, @papacarp could you please supply following:

Also, am I right in assuming that the linux tool b2sum can be used to calculate the blake2b hash?

b2sum --version

b2sum (GNU coreutils) 8.32

Josef3110 commented 1 year ago

just referencing this here because its awesome: Thank you @Josef3110

https://github.com/Josef3110/stakepool_python_tools/blob/main/scripts/sendslots.py

It is only a starting point and not (yet) the complete solution. Parsing and hashing the output from cardano-cli for current and previous epoch is missing.

NEVdataDyne commented 1 year ago

Yes very nice script, I already made some changes locally because poolID for the leadership schedule is in Bech32 format while PoolTool wants it in Hex format.

However I'd really need @papacarp to answer TerminadaPool questions :

Also, am I right in assuming that the linux tool b2sum can be used to calculate the blake2b hash?

NEVdataDyne commented 1 year ago

@papacarp Could you please you remove the restrictions for dtDn so I can test Josef3110 script? (sending slots multiple times and outside of epoch boundaries)

NEVdataDyne commented 1 year ago

@papacarp when testing Joseph3110 script, we got an error

Message sent; {"apiKey": "xxx", "poolId": "8dcdf33740ee8e9da6e36337d875fb9222f5c8a1a315fda36886c615", "epoch": 428, "slotQty": 4, "hash": "4605c2b2bc5af6664f77fb0bd7b4b2a0639b040b55c68215fe81fa156f8e632076ba4a569d33ba5119f65b7040d45e533a16f1c336b6cae8818b39a3ccf58c5c", "prevSlots": "[]"}

Response: pooltool.io response: {'statusCode': 400, 'headers': {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'}, 'body': '{"success":false,"message":"hash should be a 64 character hexadecimal string"}'}

The hash has been made in python with the following code hashlib.blake2b(slot_list_str.encode()).hexdigest() however it seems that the resulting hash in hex is always 128 characters long, even when we specify a size of 64 like this hash_obj = hashlib.blake2b(digest_size=64) ChatGPT says : _Keep in mind that the output will be a 128-character hexadecimal string (since each character in a hexadecimal representation represents 4 bits). To get 64 characters, we use digestsize=64, but the actual output will be 128 characters long. If you need exactly 64 characters and want to use a different encoding, you can use the base64 encoding to get a 64-character output Is the error message accurate? Does the hash have to be converted in base64?

Could you please confirm the format of the "stringified json array of slot numbers"? example : "['1234', '4321', '8353', '9876']"

papacarp commented 1 year ago

here is an example:

slots=[
  92648267,
  92667590,
  92694399,
  92700678,
  92703825,
  92717813,
  92726485,
  92743731,
  92749574,
  92753729,
  92762241,
  92769490,
  92783621,
  92796303,
  92817943,
  92839641,
  92843480,
  92888969,
  92902104,
  92905211,
  92918531,
  92930935,
  92934390,
  92946592,
  92949579,
  92949790,
  92955642,
  92959328,
  92966359,
  93012760,
  93031635,
  93051851
]
slotsstring=json.dumps(slots,separators=(',', ':'))
print(slotsstring)

h=hashlib.blake2b(digest_size=32)
h.update(slotsstring.encode())
hresult=h.hexdigest()

print(hresult)

this will output:

[92648267,92667590,92694399,92700678,92703825,92717813,92726485,92743731,92749574,92753729,92762241,92769490,92783621,92796303,92817943,92839641,92843480,92888969,92902104,92905211,92918531,92930935,92934390,92946592,92949579,92949790,92955642,92959328,92966359,93012760,93031635,93051851]
f71f6c056c3e5ef66a477de7852da902adb0eb4993d214edee9db9eab9088e54

And for your example specifically:

slots=[
  1234,
  4321,
  8353,
  9876
]
slotsstring=json.dumps(slots,separators=(',', ':'))
print(slotsstring)

h=hashlib.blake2b(digest_size=32)
h.update(slotsstring.encode())
hresult=h.hexdigest()

print(hresult)

will output:

[1234,4321,8353,9876]
254eb767616beb5b7d304efe1eb9330e3b957580b9ff99fdf361ede05f456b1f
papacarp commented 1 year ago

@papacarp Could you please you remove the restrictions for dtDn so I can test Josef3110 script? (sending slots multiple times and outside of epoch boundaries)

done

Josef3110 commented 1 year ago

@papacarp: Many thanks for the clarification. I'll make the changes to the script.

NEVdataDyne commented 1 year ago

Thank you very much @papacarp and @Josef3110

NEVdataDyne commented 1 year ago

@papacarp Mike, could you please confirm the timeframe when the hash of the slots list have to be sent. If I understood correctly, it must be sent during the first five minutes of an epoch. However I was wondering if it was possible to send them during the one day and a half before the epoch when they are already available from the leadership-schedule query?

Edit : Since we must send the hash and the slot list of the previous epoch at the same time, I suppose it wouldn't make much sense to send the hash before the epoch starts because it would mean that we would also send the slot list of an unfinished epoch.

NEVdataDyne commented 1 year ago

Requested information provided by papacarp