gRPC API metadata, authentication

I did that and now the path exists and looks like this - I’m not sure that it is correct syntax but I have tried a few different things and none of them seem to have any effect.

Environment='CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING=true'
Environment='CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_NAME=postgres'
Environment='CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_HOST=127.0.0.1'
Environment='CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_PORT=5432'
Environment='CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_USERNAME=postgres'
Environment='CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_PASSWORD=***********'

The service starts, but I still don’t see any session from the service in the pgAdmin.

Is this in a [Service] section in the file? Otherwise, have you tried without the ''?

The file didn’t exist, so I only added what the article mentioned, so no [Service] section.
I will try both.

For the record, this syntax seemed to work.

[Service]
Environment=CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING=true
Environment=CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_NAME=postgres
Environment=CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_HOST=127.0.0.1
Environment=CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_PORT=5432
Environment=CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_USERNAME=postgres
Environment=CONCORDIUM_NODE_TRANSACTION_OUTCOME_LOGGING_PASSWORD=***********

However I don’t get any records back when I try to get a summery, after I just instantiated a new piggy bank, which I would assume I would?

SELECT summaries.block, summaries.timestamp, summaries.summary
FROM ati JOIN summaries ON ati.summary = summaries.id
WHERE ati.account = '<my account address or ID>'
ORDER BY ati.id DESC LIMIT 30;

If I try to query the latest 30 rows without the account criteria while adding ati.account to the requested columns, I can see that this column is binary data.
Could it be that me adding a string (my account address/ID/hash or whatever we should call it) to my where clause, never will match this binary data column?

Yes, in the database, the account addresses are represented as binary rather than the textual base58checked encoding (at least for the ati.account column). Entries in the cti table are by the contract index and subindex, which is more straightforward to get, at least.

So, the sample SQL statement from the article which I tried, doesn’t really make any sense is what I understand from what you’re saying then?

How is the account table queried? - I mean how is the account used in a query clause if it is binary data in the database?

The textual representation of addresses is in base58check with the bitcoin alphabet and version byte 1. The index in the database uses the binary representation of the address, which consists of 32 bytes.

The address is always 32 bytes and it is encoded by prepending the version byte and then encoding with base58 check.

To convert the base58 address back to bytes you need to reverse those steps.

In python you can easily do this with the base58 · PyPI library as

import base58
base58.b58decode_check('4oM1reP5hVqT8Krvb9c1bJffoWW4ChTYDZVmbJwGtfGpGcDo5v')[1:]

(the [1:] at the end is to remove the version byte, in a proper decoding you would check that it is indeed 1).

I’m sure you can find similar libraries for C#/.NET.

My wish in this regard is not to work with the values in C# per say. First of all I’d like to be able to query the logging database and be able to use the account as a criteria.

Example:

SELECT 
   encode(A.account, 'hex') AS encoded_account,
   encode(S.block, 'hex') AS encoded_block, 
   S.timestamp, 
   S.summary  
FROM ati A 
   JOIN summaries S ON A.summary = S.id 
WHERE (encode(A.account, 'hex') = '3PHLj6j6YyqHVF3hXjqg5zeKHzZVQgCuaAZSaGo4TN5EXpaFUJ' AND 
S.timestamp >= <some timestamp value>);

I’m aware that the encode function may not give me the result I need, but here it is just used an an example.

I am not aware of base58 encoding function in postgres, so you will need to do the encoding/decoding outside of SQL (e.g., with that python example I showed).

Hmm… That brings me back to the sample query from the article.

SELECT summaries.block, summaries.timestamp, summaries.summary
FROM ati JOIN summaries ON ati.summary = summaries.id
WHERE ati.account = $1
ORDER BY ati.id DESC LIMIT $2

I can easily replace $2 in the above statement with something, but what would I replace $1 with in order to actually be able to use this sample query for anything?

You replace it with the result of this

import base58
base58.b58decode_check('4oM1reP5hVqT8Krvb9c1bJffoWW4ChTYDZVmbJwGtfGpGcDo5v')[1:]

for an address 4oM1reP5hVqT8Krvb9c1bJffoWW4ChTYDZVmbJwGtfGpGcDo5v, modifying the address as you need.

If you can’t use python then use some other language and library to do base58 encoding.

Could you show me an example of how you would add your result of your decode into a SQL statement?

You can convert the output to hex, for instance:

>>> base58.b58decode_check('4oM1reP5hVqT8Krvb9c1bJffoWW4ChTYDZVmbJwGtfGpGcDo5v')[1:].hex()
'f45209f18bc7d4b748023be25ea8e71affd4f8834e437c69aa22dccbd1e6d54c'

Then in the SQL statement you can use

...
WHERE ati.account = x'f45209f18bc7d4b748023be25ea8e71affd4f8834e437c69aa22dccbd1e6d54c'

Wouldn’t it have to be:

WHERE (encode(ati.account, 'hex') = 'f45209f18bc7d4b748023be25ea8e71affd4f8834e437c69aa22dccbd1e6d54c')

Since ati.account is binary data in the database and not a hex out of the box?

I am trying with account 3PHLj6j6YyqHVF3hXjqg5zeKHzZVQgCuaAZSaGo4TN5EXpaFUJ which becomes 0139fc4ea5015885d50c7730852b4a9b2249aaf54f0abb8a8ec44b78776668 when I base58check.decode it, remove the last byte and make a hex from it.

Can you verify that you get the same value if you do the same?

I think I was mistaken about the representation of binary literals. I think the following should work:

WHERE ati.account = '\xf45209f18bc7d4b748023be25ea8e71affd4f8834e437c69aa22dccbd1e6d54c'

(i.e. format it as '\x<hex string>'.)

Applying encode to ati.account will likely be less performant than this, or alternatively using decode on the hexadecimal string, as in:

WHERE ati.account = decode('f45209f18bc7d4b748023be25ea8e71affd4f8834e437c69aa22dccbd1e6d54c','hex')
1 Like

It is probably me who is misunderstanding something, but as I see it the data in ati.account is binary and needs to be converted (encoded) into something that can be compared to something else in order to use it in the query.
If the way to use the account address in a SQL statement is to represent it as a hex string, then I would assume that I would have to compare it to a hex encoded version of ati.account in the database in order to be able to compare these 2… or… what am I missing here?

Therefore I don’t understand the statement ati.account = ‘hex string’… Isn’t that like comparing apples to oranges (binary data to hex string)?

I still have had no luck getting any rows when I query for summaries with my account as criteria. Maybe there are no rows to be found, which would be very odd or maybe I’m just not providing the correct value to search for, which I find more plausible.

I have tried the following (to test both).

The first I would think was apples to apples (hex to hex):

SELECT A.id AS a_id, encode(A.account,'hex') AS a_hex,  
	S.id AS s_id, S.timestamp AS s_timestamp, S.summary AS s_summary  
FROM ati A  
	JOIN summaries S ON A.summary = S.id  
WHERE (encode(A.account,'hex') = '\x0139fc4ea5015885d50c7730852b4a9b2249aaf54f0abb8a8ec44b78776668') 
ORDER BY S.timestamp DESC LIMIT 10;

And the second I would think was apples to oranges (binary to hex).

SELECT A.id AS a_id, encode(A.account,'hex') AS a_hex,  
	S.id AS s_id, S.timestamp AS s_timestamp, S.summary AS s_summary  
FROM ati A  
	JOIN summaries S ON A.summary = S.id  
WHERE (A.account = '\x0139fc4ea5015885d50c7730852b4a9b2249aaf54f0abb8a8ec44b78776668') 
ORDER BY S.timestamp DESC LIMIT 10;

Again I will ask if you can confirm that the account address 3PHLj6j6YyqHVF3hXjqg5zeKHzZVQgCuaAZSaGo4TN5EXpaFUJ becomes the hex string 0139fc4ea5015885d50c7730852b4a9b2249aaf54f0abb8a8ec44b78776668 if you try to do you Python thing to it?
I would be silly spending a lot of time trying to find a value that isn’t there because it is incorrect.

Hi petlan,

I checked the account address and your conversion is incorrect.
I created this small python script, which you can run directly in the browser and get the correct hex value:

As for your conjectures, let’s get back to them if using the correct hex value doesn’t solve the problem :blush:

/ Kasper

The value still doesn’t give any result in the database.
Have you removed at last byte (the version byte) from the result as abizjak mentioned?

Yes, the first byte has been removed. You can view the code by clicking on the Show files button :blush:.
Perhaps @td202 can help resolve this issue, as I am not too familiar with the transaction database.

/ Kasper

Hmm the first byte… According to the description by abizjak further up in this thread, it is the last byte that has to be removed, so that’s what I did.

Is it in fact the first byte that should be removed? - if so, no wonder I’m getting a wrong value for comparison to the value in the database… However, as mentioned, the value your code returned was also not found in the database.

I still can’t be 100% sure that it even exists in the ati table in the database since I have no way to verify this, but transactions I make in regard to my smart contract does exist in the cti table in the database, so I would assume that since it has to do with my account, that there would be some record in the ati table as well.