-
Notifications
You must be signed in to change notification settings - Fork 148
Reverse a ByteArray #17
Comments
Although I also would like this feature,, use case for scripthash is not clear to me. |
Back when I participated in the CoZ dApp contest I needed to reverse script_hashes before feeding them to "dynamic |
i think that we should remove this requirement of reverse the address on Neo 3.0 |
Thanks @ixje, that's exactly the issue I faced too. It had something to do with the varying endianness of the script hash, which is was represented in some places as a 160-bit uint and in others as a byte array. |
@shargon one thing that I've been trying to clarify on my scripts is exactly where things are little-endian and when they are big-endian. And one thing still bothers me, that I still don't know what is the precise endianess of the "scripthash" we use. Since all machine processing stuff are big-endian on neovm, I believe it should be big-endian inside, and little endian outside, is it not the case? |
Guys, we could reuse opcode https://github.com/neo-project/neo-vm/blob/master/src/neo-vm/OpCode.cs#L429 https://github.com/neo-project/neo-vm/blob/master/src/neo-vm/ExecutionEngine.cs#L837-L849 |
@erikzhang what is the meaning for reverse the addresses? |
Since we're in question mode on reversing data; Why do we reverse the data of |
In fact this last one is easier @ixje, Neo represents big endian bytearrays with "0x" on front... thats on website documentation. So I guess its a little endian becoming big endian. And I think that also solves my eternal mistery, because Neo compiler puts 0x in front of scripthash, meaning its big endian (that explains the reverse on Address, @shargon) |
This is a possible solution to the issue raised at neo-vm page: neo-project#17
This is how they present the data, I'm interested in why it was chosen to represent it like that. It even conflicts with the documentation which states
Anything deriving from Then to elaborate on |
@ixje Ok, let's try to clarify everything here :) This is the reference to "0x": http://docs.neo.org/en-us/exchange/v2.7.4.html UIntBase works as little endian (at least it looks like), and the ToString method appends 0x and reverses it (to display as "big endian"). This part is fine to me. But even their example is crazy if it's not big endian: // The example displays the following output:
// Positive value: 15,777,216
// C0 BD F0 00 using System;
using System.Numerics;
public class Test {
public static void Main() {
byte[] b = new byte[]{0x00, 0x01};
BigInteger bi = new BigInteger(b);
Console.Write(bi); // 256. How can it be little endian??
}
} Shouldn't little endian store the last elements as the smallest? Isn't the decimal value 01 in this example? |
Without taking into account what some document says how they differentiate between little- and big-endian, why would it be fine to change the representation of a bytearray that is internally one endianness and then only when represented as a string becomes another? That makes zero sense in my opinion. I'm going to comment on the BigInteger just once because it deviates from the topic if you ask me. >>> int.from_bytes(bytes.fromhex("C0BDF000"),byteorder='little')
15777216 To quote MS from your link:
I still agree with them on that >>> int.from_bytes(bytes.fromhex("C0BDF0FF"),byteorder='little')
4293967296 I believe this is the crucial part for your Biginteger question
|
I would just like to chime in that regardless of the script hash discussion this functionality will be very useful! There's been many times where I wished I could reverse a byte array. I should note as well that as currently implemented, it will also be able to reverse strings! |
@ixje thanks for pointing out this python example... now I'm sure I was understand everything upside down xD hahahah I'll need some time to recover, and to update all my scripts again ;) And now that you explained me this and I'm convinced BigInteger is little endian, I give you an answer to:
I think it makes full sense for me, because numbers are only represented internally as little endians, but for "public" representation they are seen as big endians (that's why I believe this "0x" prefix is quite important to make sure of the big endianess on @shargon In the end, the "reverse" on Address makes a lot of sense, because the ToAddress function takes as parameter a little-endian UInt160: Suppose we take an AVM, we apply HASH160 (Sha256 + Ripemd160) and get |
@ixje I hope this documentation helps clarifying UInt160 for all of us: neo-project/neo#405 |
@igormcoelho your description only explains that the code is functional. I wasn't doubting that part, but functional != logical. If you look closely at the following text you'll see we do useless back and forth manipulation of the data in the bytearray.
If we would not do the bold quoted text, then we would have gotten the same results. That's the point I'm trying to make. It just adds unnecessary overhead, has no added value and it's actually confusing as proven by the fact that we're discussing it. Let me ask you this
Can you tell the endianness of this hash? Do you think a user cares what endianness it is? How about this: public static string ByteArrayToString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
public static void Main(string[] args)
{
byte[] internal_data = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
UInt160 script_hash = new UInt160(internal_data);
Console.WriteLine(ByteArrayToString(script_hash.ToArray()));
Console.WriteLine(script_hash.ToString());
// Output
// 0000000000000000000000000000000000000001
//0x0100000000000000000000000000000000000000
} Saying the above makes sense is like saying that you can represent the decimal number |
No @ixje, that makes sense, it's just that we learned that in a bad way, but people who learn that right now "correctly" will see it actually makes sense.
So, answering to your question:
No, users don't care, and I don't want to care either. I just needed to go deeper in just to clarify the precise endianess of everything, to be able to explain that no "extra reverse" is being done. In fact, I believe we should start presenting ScriptHash in little-endian, so no reverse will ever be needed. That's what I'm proposing for neon-js team, and every others that use this notation. In my opinion, ScriptHash should never be exposed to users, we have base-58 Address for that, which is legible and safe. Even Neon Wallet presents scripthash, that's strange, I'll open an issue about it. So even when invoking contracts, we should seriously think on adopting Address for this, because it's much safer and 100% clear (with checksum and other protective stuff). What do we need to change to accomplish that? Nothing. Because Neo was well designed to put this heavenly-sent "0x" in front of big-endian numbers, so we just abolish this 0x on ScriptHash, we can just use little-endian on our frontends and do not worry to do any reverse. And I'm pretty sure that if C# BigInteger was big-endian we wouldn't be having this conversation, but since we cannot change that, at least we need to know it. |
@igormcoelho if you want to discuss it further DM me on Discord. We reason from 2 different perspectives. I reason from a generic computer science perspective and point to unexpected behavior/handling in the NEO implementation. You reason from the NEO implementation perspective. |
This problem is currently solved on C# (in PR neo-project/neo-devpack-dotnet#37), you can use Reverse() method. public static byte[] Main(byte[] v)
{
return v.Reverse();
} In order to work, you need to have latest C# compiler, after this commit: https://github.com/neo-project/neo-compiler/commit/d6e18710a43b1fbd83452f6a3e3f8e8bb5b7fa98 |
Guys, we are in 2022 and big endian and little endian in Neo still confuses me. ❤️ Especially the decision to add "0x" as the prefix to represent big endian not being a standard in the software industry....... 🤣 😄 |
Each time we have some issue with endianness I link neo-project/neo#938. The list of links grows with time. But I don't know how can we fix it now, N3 is out and it works the way it works. |
Like CAT, SUBSTR and LEFT, it would be nice to have an opcode for reversing a byte array. Useful for script hashes.
The text was updated successfully, but these errors were encountered: