Ejemplo n.º 1
0
        //Transfer instructions will deplete a specific token (based on order of token in Input) to zero before next instructions
        //being applied to next token (based on order)
        //Metadata follows transfer instructions

        public static string _NTP1CreateTransferScript(List <NTP1Instructions> TIs, byte[] metadata)
        {
            if (TIs.Count == 0)
            {
                return("");
            }
            if (TIs.Count > 255)
            {
                return("");
            }                                           //Cannot create transaction greater than 255 instructions

            //Constants
            byte[] header             = ConvertHexStringToByteArray("4e5403"); //Represents chars NT and byte protocal version (3)
            byte   op_code            = 16;                                    //Transer transaction
            int    op_return_max_size = 4096;                                  //Maximum size of the scriptbin

            using (MemoryStream scriptbin = new MemoryStream())
            {
                //This stream will hold the byte array that will be converted to a hex string eventually
                scriptbin.Write(header, 0, header.Length);               //Write the header data to the stream
                scriptbin.WriteByte(op_code);
                scriptbin.WriteByte(Convert.ToByte(TIs.Count));          //The amount of TIs

                for (int i = 0; i < TIs.Count; i++)
                {
                    //Add the transfer instructions
                    NTP1Instructions ti = TIs[i];
                    //Skip input will always be false in our case, so first position is always 0
                    //The maximum vout position is 31 (0-31) per this method, although 255 TIs are supported
                    if (ti.vout_num > 31)
                    {
                        return("");
                    }
                    string output_binary = "000" + Convert.ToString(ti.vout_num, 2).PadLeft(5, '0');                   //Convert number to binary
                    byte   first_byte    = Convert.ToByte(output_binary, 2);
                    scriptbin.WriteByte(first_byte);

                    //Now convert the amount to byte array
                    byte[] amount_bytes = _NTP1NumToByteArray(ti.amount);
                    scriptbin.Write(amount_bytes, 0, amount_bytes.Length);
                }

                //Add metadata if present
                if (metadata != null)
                {
                    uint msize = (uint)metadata.Length;
                    if (msize > 0)
                    {
                        byte[] msize_bytes = BitConverter.GetBytes(msize);
                        if (BitConverter.IsLittleEndian == true)
                        {
                            //We must convert this to big endian as protocol requires big endian
                            Array.Reverse(msize_bytes);
                        }
                        scriptbin.Write(msize_bytes, 0, msize_bytes.Length);                 //Write the size of the metadata
                        scriptbin.Write(metadata, 0, metadata.Length);                       //Write the length of the metadata
                    }
                }
                if (scriptbin.Length > op_return_max_size)
                {
                    return("");                    //Cannot create a script larger than the max
                }
                return(ConvertByteArrayToHexString(scriptbin.ToArray()));
            }
        }
Ejemplo n.º 2
0
        public static void _NTP1ParseScript(NTP1Transactions tx)
        {
            if (tx.ntp1_opreturn.Length == 0)
            {
                return;
            }                                                     //Nothing inside
            byte[] scriptbin        = ConvertHexStringToByteArray(tx.ntp1_opreturn);
            int    protocol_version = Convert.ToInt32(scriptbin[2]);

            if (protocol_version != 3)
            {
                throw new Exception("NTP1 Protocol Version less than 3 not currently supported");
            }
            int op_code     = Convert.ToInt32(scriptbin[3]);
            int script_type = 0;

            if (op_code == 1)
            {
                script_type = 0;                 //Issue transaction
            }
            else if (op_code == 16)
            {
                script_type = 1;                 //Transfer transaction
            }
            else if (op_code == 32)
            {
                script_type = 2;                 //Burn transaction
            }
            if (script_type != 1)
            {
                throw new Exception("Can only parse NTP1 transfer scripts at this time");
            }
            tx.tx_type = 1;
            scriptbin  = ByteArrayErase(scriptbin, 4);           //Erase the first 4 bytes

            //Now obtain the size of the transfer instructions
            int numTI    = Convert.ToInt32(scriptbin[0]);          //Byte number between 0 and 255 inclusively
            int raw_size = 1;

            scriptbin = ByteArrayErase(scriptbin, 1);
            for (int i = 0; i < numTI; i++)
            {
                NTP1Instructions ti = new NTP1Instructions();
                ti.firstbyte = scriptbin[0];                             //This represents the flags
                int    size        = _CalculateAmountSize(scriptbin[1]); //This will indicate the size of the next byte sequence
                byte[] amount_byte = new byte[size];
                Array.Copy(scriptbin, 1, amount_byte, 0, size);          //Put these bytes into the amount_byte array
                size++;                                                  //Now include the flag byte
                raw_size += size;                                        //Our total instruction size added to the raw size
                scriptbin = ByteArrayErase(scriptbin, size);             //Erase transfer instructions

                //Break down the first byte which represents the location and skipinput byte
                string firstbyte_bin   = Convert.ToString(ti.firstbyte, 2).PadLeft(8, '0');             //Byte to binary string
                string outputindex_bin = firstbyte_bin.Substring(3);
                if (firstbyte_bin[7] == '1')
                {
                    ti.skipinput = true;                     //This means the byte value is 255
                }
                ti.vout_num = Convert.ToInt32(Convert.ToUInt64(outputindex_bin, 2));
                int len = amount_byte.Length;
                ti.amount = _NTP1ByteArrayToNum(amount_byte);
                tx.ntp1_instruct_list.Add(ti);
            }

            //Now extract metadata from the op_return. Max op_return size: 4096 bytes
            if (scriptbin.Length < 4)
            {
                return;                 //No metadata or not enough data remaining to extract
            }

            //Get the metadata size int32
            byte[] metadata_size_bytes = new byte[4];
            Array.Copy(scriptbin, metadata_size_bytes, 4);           //The size of the metadata is stored as Bigendian in the script
            //Determine if the system is little endian or not
            if (BitConverter.IsLittleEndian == true)
            {
                Array.Reverse(metadata_size_bytes);
            }
            //Now put the bytes into an int
            uint metadata_size = BitConverter.ToUInt32(metadata_size_bytes, 0);

            scriptbin = ByteArrayErase(scriptbin, 4);            //Remove the size int on the remaining data
            if (scriptbin.Length != metadata_size)
            {
                throw new Exception("Metadata information is invalid");
            }

            tx.metadata = scriptbin;             //Our metadata is what remains in the script. Just raw data to be used for any purpose
        }