-
Notifications
You must be signed in to change notification settings - Fork 23
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
Authority key sorting #8
Comments
Google takes me here. Though it may be out of topic, I'd like to share my experience. In C++ Smart Contracts if you sort public_key vector directly, you will not get what you want. The following example works:
In TS, base58 representation of public key sorting works too, don't worry about it. |
For lexographic comparison of K1 and R1 keys in JS/TS, I have been using
|
Btw there is a sort() helper on the Authority type that will do the locale compare hack but will break on updates that have multiple WA keys as you pointed out |
As I was said, in C++, you need to use memcmp to sort public keys.
K1 and R1 keys are both stored in 34 bytes in C++.
If the first byte is 0, it’s a K1 key.
If the first byte is 1, it’s an R1 key.
In TS, the following method may work to sort keys combine with K1 and R1:
1. Convert base58 key to a Uint8Array variable with a length of 34
2. Sort keys in Uint8Array as the code show below
const a = new Uint8Array([3, 1, 3, 5])
const b = new Uint8Array([1, 3, 2])
function compare(a: Uint8Array, b: Uint8Array) {
let size = a.length;
if (size > b.length) {
size = b.length
}
for (let i=0; i<size; i++) {
let diff = a[i] - b[i]
if (diff == 0) {
continue
}
return diff
}
return a.length - b.length
}
let aa = [a, b]
aa.sort(compare)
… On Jan 24, 2022, at 3:07 PM, Syed Jafri ***@***.***> wrote:
For lexographic comparison of K1 and R1 keys, I have been using localeCompare so far, but it breaks with WA keys, example:
"EOS5fMyAUopVJv88Wb4szbLH2ds65jiNCjv1XWRRyvrfR6oEBdZXk",
"PUB_WA_323xpHU17pKZ6VsygcdXxq7cgosxSyRU5KGevyjUNtw4m9Y63EzPs3SEVpsf7rjeVLa7",
"PUB_WA_4B6ZbE2hxTvcrndvS8758EjGqRMQqVoV4vBTGgvqi27HNw8xyQz6viKrGLNLcaiRmhmbuyu584Hf",
"PUB_WA_4vD5irsd1GdmTEhea5G8QideW3NqU8F5zgPLyD3wKDE7MUPAwo5nELCEbJEELDafLeV4Uz7djSFJ",
"PUB_WA_5Q6G5dqajZDkqDbgEUG7a7qMpe94P6LegYdf7h8yL9efjhC6ERWuFsJM1ueygEmXzaELBokrUeH8",
"PUB_WA_6wUAAJXLFc3edKhGb5DdWb3WmoLxLwFSspdiEYHvT6DN2X7zo6opCfv6TcAifvxRQdVYwcr84zMS"
—
Reply to this email directly, view it on GitHub <#8 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AHPJSPW2C4OQA7CWZEVXPQDUXT3EZANCNFSM4WW6HIPQ>.
Triage notifications on the go with GitHub Mobile for iOS <https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675> or Android <https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you commented.
|
@learnforpractice The issue is the WA key type, your memcmp method would likely fail as well if the array contained keys of that type since the keydata contains a string that packs its own length as a varuint prefix |
Yeah, the first byte of WA key is 2, and the raw WA key size is not fixed to 34.
The following python code demonstrates how to sort keys combined with K1, R1, and WA which can easily be ported to TS I think.
import base58
pub_keys = [
"PUB_WA_323xpHU17pKZ6VsygcdXxq7cgosxSyRU5KGevyjUNtw4m9Y63EzPs3SEVpsf7rjeVLa7",
"PUB_WA_4B6ZbE2hxTvcrndvS8758EjGqRMQqVoV4vBTGgvqi27HNw8xyQz6viKrGLNLcaiRmhmbuyu584Hf",
"PUB_WA_4vD5irsd1GdmTEhea5G8QideW3NqU8F5zgPLyD3wKDE7MUPAwo5nELCEbJEELDafLeV4Uz7djSFJ",
"PUB_WA_5Q6G5dqajZDkqDbgEUG7a7qMpe94P6LegYdf7h8yL9efjhC6ERWuFsJM1ueygEmXzaELBokrUeH8",
"PUB_K1_518vvdSbDRUkPTXhMaGf2hNGN8RPvHGXdkr2YDsLPh81sS6DGm",
"EOS7RWp93PBkwDKjNRroTrA5rYV1c7RcbwbZVUXD8PBArQTQwMB9G"
]
def get_key(pub_key):
if pub_key.startswith('PUB_K1_'):
return b'\x00' + base58.b58decode(pub_key.removeprefix('PUB_K1_'))[:-4]
if pub_key.startswith('EOS'):
return b'\x00' + base58.b58decode(pub_key.removeprefix('EOS'))[:-4]
elif pub_key.startswith('PUB_R1_'):
return b'\x01' + base58.b58decode(pub_key.removeprefix('PUB_R1_'))[:-4]
elif pub_key.startswith('PUB_WA_'):
return b'\x02' + base58.b58decode(pub_key.removeprefix('PUB_WA_'))[:-4]
else:
assert False, 'unknown pubkey format'
pub_keys = sorted(pub_keys, key=get_key)
print(pub_keys)
… On Jan 24, 2022, at 4:13 PM, Johan Nordberg ***@***.***> wrote:
@learnforpractice <https://github.com/learnforpractice> The issue is the WA key type, your memcmp method would likely fail as well if the array contained keys of that type since the keydata contains a string that packs its own length as a varuint prefix
—
Reply to this email directly, view it on GitHub <#8 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AHPJSPRWXCI3G7VHC6E5J3DUXUC3RANCNFSM4WW6HIPQ>.
Triage notifications on the go with GitHub Mobile for iOS <https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675> or Android <https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you were mentioned.
|
To update an accounts permissions nodeos enforces that the keys are sorted, the sorting logic comes from the fc library and has to be re-created for every type involved. Fortunately due to a quirk of how it is implemented for 99% of cases we can get away with sorting the string representations of the types in question.
For now the Authority type will use the string sorting hack. But long-term we should add a
compare
requirement to all core types and replicate fc's sorting behavior for all of them.Attaching chat log from Telegram discussing this for posterity
The text was updated successfully, but these errors were encountered: