예제 #1
0
        /// <summary>
        /// Hash returns the network-specific transaction hash for a signed transaction.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public JObject ConstructionHash(ConstructionHashRequest request)
        {
            NeoTransaction neoTx;

            try
            {
                neoTx = NeoTransaction.DeserializeFrom(request.SignedTransaction.HexToBytes());
            }
            catch (Exception)
            {
                return(Error.TX_DESERIALIZE_ERROR.ToJson());
            }
            var hash = neoTx.Hash.ToString();
            ConstructionHashResponse response = new ConstructionHashResponse(hash);

            return(response.ToJson());
        }
예제 #2
0
        /// <summary>
        /// Submit a pre-signed transaction to the node. This call should not block on the transaction being included in a block.
        /// Rather, it should return immediately with an indication of whether or not the transaction was included in the mempool.
        /// The transaction submission response should only return a 200 status if the submitted transaction could be included in the mempool.
        /// Otherwise, it should return an error.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public JObject ConstructionSubmit(ConstructionSubmitRequest request)
        {
            NeoTransaction neoTx;

            try
            {
                neoTx = NeoTransaction.DeserializeFrom(request.SignedTransaction.HexToBytes());
            }
            catch (Exception)
            {
                return(Error.TX_DESERIALIZE_ERROR.ToJson());
            }

            RelayResultReason reason = system.Blockchain.Ask <RelayResultReason>(neoTx).Result;

            switch (reason)
            {
            case RelayResultReason.Succeed:
                TransactionIdentifier      transactionIdentifier = new TransactionIdentifier(neoTx.Hash.ToString());
                ConstructionSubmitResponse response = new ConstructionSubmitResponse(transactionIdentifier);
                return(response.ToJson());

            case RelayResultReason.AlreadyExists:
                return(Error.ALREADY_EXISTS.ToJson());

            case RelayResultReason.OutOfMemory:
                return(Error.OUT_OF_MEMORY.ToJson());

            case RelayResultReason.UnableToVerify:
                return(Error.UNABLE_TO_VERIFY.ToJson());

            case RelayResultReason.Invalid:
                return(Error.TX_INVALID.ToJson());

            case RelayResultReason.PolicyFail:
                return(Error.POLICY_FAIL.ToJson());

            default:
                return(Error.UNKNOWN_ERROR.ToJson());
            }
        }
예제 #3
0
        public override void Deserialize(BinaryReader reader)
        {
            base.Deserialize(reader);
            Transactions = new Transaction[reader.ReadVarInt(MaxTransactionsPerBlock)];
            if (Transactions.Length == 0)
            {
                throw new FormatException();
            }
            HashSet <UInt256> hashes = new HashSet <UInt256>();

            for (int i = 0; i < Transactions.Length; i++)
            {
                Transactions[i] = Transaction.DeserializeFrom(reader);
                if (i == 0)
                {
                    if (Transactions[0].Type != TransactionType.MinerTransaction)
                    {
                        throw new FormatException();
                    }
                }
                else
                {
                    if (Transactions[i].Type == TransactionType.MinerTransaction)
                    {
                        throw new FormatException();
                    }
                }
                if (!hashes.Add(Transactions[i].Hash))
                {
                    throw new FormatException();
                }
            }
            if (MerkleTree.ComputeRoot(Transactions.Select(p => p.Hash).ToArray()) != MerkleRoot)
            {
                throw new FormatException();
            }
        }
예제 #4
0
        /// <summary>
        /// Parse is called on both unsigned and signed transactions to understand the intent of the formulated transaction.
        /// This is run as a sanity check before signing (after `/construction/payloads`) and before broadcast (after `/construction/combine`).
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public JObject ConstructionParse(ConstructionParseRequest request)
        {
            NeoTransaction neoTx;

            try
            {
                if (request.Signed)
                {
                    neoTx = NeoTransaction.DeserializeFrom(request.Transaction.HexToBytes());
                }
                else
                {
                    byte[]          rawTx = request.Transaction.HexToBytes();
                    TransactionType type  = (TransactionType)rawTx[0];
                    switch (type)
                    {
                    case TransactionType.ClaimTransaction:
                        neoTx = new ClaimTransaction();
                        break;

                    case TransactionType.ContractTransaction:
                        neoTx = new ContractTransaction();
                        break;

                    case TransactionType.StateTransaction:
                        neoTx = new StateTransaction();
                        break;

                    case TransactionType.InvocationTransaction:
                        neoTx = new InvocationTransaction();
                        break;

                    default:
                        throw new ArgumentException();
                    }
                    using (MemoryStream ms = new MemoryStream(rawTx, false))
                        using (BinaryReader br = new BinaryReader(ms, Encoding.UTF8))
                        {
                            (neoTx as IVerifiable).DeserializeUnsigned(br);
                        }
                }
            }
            catch (Exception)
            {
                return(Error.TX_DESERIALIZE_ERROR.ToJson());
            }

            Transaction tx = ConvertTx(neoTx);

            Operation[] operations = tx.Operations;
            string[]    signers    = new string[0];
            if (request.Signed)
            {
                signers = GetSignersFromWitnesses(neoTx.Witnesses);
                if (signers is null)
                {
                    return(Error.TX_WITNESS_INVALID.ToJson());
                }
            }
            ConstructionParseResponse response = new ConstructionParseResponse(operations, signers, tx.Metadata);

            return(response.ToJson());
        }