Skip to content
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

AsByteArray() isn't able to convert BigInteger to ByteArray #195

Closed
superboyiii opened this issue Mar 4, 2020 · 4 comments · Fixed by #196
Closed

AsByteArray() isn't able to convert BigInteger to ByteArray #195

superboyiii opened this issue Mar 4, 2020 · 4 comments · Fixed by #196

Comments

@superboyiii
Copy link
Member

superboyiii commented Mar 4, 2020

When I test nep5 sc, I'd like to put 0 into account storage when balanceOf return null, so I write as below:

        [DisplayName("BalanceOf")]
        public static BigInteger BalanceOf(byte[] account)
        {
            if (account.Length != 20)
                throw new InvalidOperationException("The parameter account SHOULD be 20-byte addresses");
            var balance = Storage.Get(Storage.CurrentContext, account);
            BigInteger zero = 0;
            byte[] byteZero = zero.AsByteArray();
            if (balance is null)
            {
                Storage.Put(Storage.CurrentContext, account, byteZero);
            }
            return Storage.Get(Storage.CurrentContext, account).AsBigInteger();
        }

Then I found this byteZero is not a byteArray but still return BigInteger 0 which cause RPC getBalance return 0 if one of addresses in a wallet doesn't have balance.
Then I tried another style, it works well. This means AsByteArray() here isn't work normally.
image
Then I found AsByteArray() isn't able to conver BigInteger to ByteArray but just transfer it to VM. This makes me a little confused. Since native C# conversion method ToByteArray() isn't able to be used in sc.framework, we don't have a method support BigInteger to ByteArray on sc framework.
@erikzhang @lightszero @shargon

@Tommo-L
Copy link
Contributor

Tommo-L commented Mar 4, 2020

Currently, the AsByteArray is an empty script.

/// <summary>
/// Converts BigInteger to byte[]. No guarantees are assumed regarding BigInteger working range.
/// Examples: 10 -> [0x0a]; 10 -> [0x0a00]; -128 -> [0x80]; -128 -> [0x80ff]; 0 -> []; 0 -> [0x00]; 255 -> [0xff00]
/// </summary>
[Script]
public extern static byte[] AsByteArray(this BigInteger source);

I think there are two options:
option1: Add a new opcode Cast for converting.
option2: Add a new method AsByteArray in StackItem.

@shargon
Copy link
Member

shargon commented Mar 4, 2020

we have the CONVERT opcode, we can use it

@lightszero
Copy link
Member

lightszero commented Mar 4, 2020

'CONVERT', that's new for me.sounds it fit this issue. I will working on it.

lightszero added a commit that referenced this issue Mar 5, 2020
@lightszero
Copy link
Member

I had create a unittest, it worked.

    class Contract_TypeConvert : SmartContract.Framework.SmartContract
    {
        //Integer = 0x21,
        //ByteArray = 0x28,
        [OpCode(SmartContract.Framework.OpCode.CONVERT, "0x28")]
        public extern static byte[] ConvertToByteArray(object from);


        [OpCode(SmartContract.Framework.OpCode.CONVERT, "0x21")]
        public extern static BigInteger ConvertToInteger(byte[] from);




        public static object testType()
        {
            BigInteger int0 = 0;
            var bts0 = ConvertToByteArray(int0);
            BigInteger int1 = 2;
            var bts1 = ConvertToByteArray(int1);

            var bts2=new byte[1] { 3 };
            var int2 = ConvertToInteger(bts2);

            var bts3 = ConvertToByteArray(new byte[0]) ;
            var int3 = ConvertToInteger(bts3);

            var arrobj = new object[8];
            arrobj[0] = int0;
            arrobj[1] = bts0;
            arrobj[2] = int1;
            arrobj[3] = bts1;
            arrobj[4] = bts2;
            arrobj[5] = int2;
            arrobj[6] = bts3;
            arrobj[7] = int3;
            return arrobj;
        }


    }

lightszero added a commit that referenced this issue Mar 11, 2020
* this unittest for
#195

* Clean code

* 區分push
pushNumber
pushBoolean
pushDataArray

過去合約中所有的數值是統一的Push
小於等於16的數字 和 byte[0] 和  true false 是Integer
>16的數字 和 byte[n>0] 是 ByteArray

現在在合約中使用數值將直接得到正確的類型

new byte[0] 是ByteArray
true        是Boolean
17          是Integer

* 1.修改了unittest null
因爲現在會返回integer類型了,不再是DataArray

2.修改了TypeConvert
應該現在 new byte[0] 直接是ByteArray類型了

* 1.Use Helper.AsByteArray() to convert to ByteArray
2.Use Helper.AsBigInteger() to convert to BigInteger
3.fix unittest

* fix one small fault.

* add value equal test

* Clean code

* Clean code

* fix format

Co-authored-by: Shargon <shargon@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants