Example #1
0
        private static byte[] calcDigest(Transaction tx, bool needSigns)
        {
            string encoded  = "";
            var    settings = new JsonSerializerSettings()
            {
                Formatting           = Formatting.None,
                DefaultValueHandling = DefaultValueHandling.Ignore,
                NullValueHandling    = NullValueHandling.Ignore,
            };

            if (tx.TxInputs != null)
            {
                for (var i = 0; i < tx.TxInputs.Count; i++)
                {
                    var input = tx.TxInputs[i];
                    if (input.RefTxid.Length > 0)
                    {
                        encoded += JsonConvert.SerializeObject(input.RefTxid) + "\n";
                    }
                    encoded += JsonConvert.SerializeObject(input.RefOffset) + "\n";
                    if (input.FromAddr.Length > 0)
                    {
                        encoded += JsonConvert.SerializeObject(input.FromAddr) + "\n";
                    }
                    if (input.Amount.Length > 0)
                    {
                        encoded += JsonConvert.SerializeObject(input.Amount) + "\n";
                    }
                    encoded += JsonConvert.SerializeObject(input.FrozenHeight) + "\n";
                }
            }

            encoded += JsonConvert.SerializeObject(tx.TxOutputs, settings) + "\n";
            if (tx.Desc != null && tx.Desc.Length > 0)
            {
                encoded += JsonConvert.SerializeObject(tx.Desc) + "\n";
            }
            encoded += JsonConvert.SerializeObject(tx.Nonce, settings) + "\n";
            encoded += JsonConvert.SerializeObject(tx.Timestamp) + "\n";
            encoded += JsonConvert.SerializeObject(tx.Version) + "\n";
            if (tx.TxInputsExt != null)
            {
                for (var i = 0; i < tx.TxInputsExt.Count; i++)
                {
                    var input = tx.TxInputsExt[i];
                    encoded += JsonConvert.SerializeObject(input.Bucket) + "\n";
                    if (input.Key.Length > 0)
                    {
                        encoded += JsonConvert.SerializeObject(input.Key) + "\n";
                    }
                    if (input.RefTxid.Length > 0)
                    {
                        encoded += JsonConvert.SerializeObject(input.RefTxid) + "\n";
                    }
                    encoded += JsonConvert.SerializeObject(input.RefOffset) + "\n";
                }
            }

            if (tx.TxOutputsExt != null)
            {
                foreach (var output in tx.TxOutputsExt)
                {
                    encoded += (JsonConvert.SerializeObject(output.Bucket) + "\n");
                    if (output.Key.Length > 0)
                    {
                        encoded += (JsonConvert.SerializeObject(output.Key) + "\n");
                    }
                    if (output.Value.Length > 0)
                    {
                        encoded += (JsonConvert.SerializeObject(output.Value) + "\n");
                    }
                }
            }

            encoded += (JsonConvert.SerializeObject(tx.ContractRequests, settings) + "\n");
            encoded += (JsonConvert.SerializeObject(tx.Initiator) + "\n");
            encoded += (JsonConvert.SerializeObject(tx.AuthRequire) + "\n");

            if (needSigns)
            {
                encoded += (JsonConvert.SerializeObject(tx.InitiatorSigns) + "\n");
                encoded += (JsonConvert.SerializeObject(tx.AuthRequireSigns) + "\n");
            }

            encoded += (JsonConvert.SerializeObject(tx.Coinbase) + "\n");
            encoded += (JsonConvert.SerializeObject(tx.Autogen) + "\n");
            //Console.WriteLine("Debug: digest=\n" + encoded);
            var encodedBytes = Encoding.ASCII.GetBytes(encoded);

            return(XCrypto.DoubleSha256(encodedBytes));
        }
Example #2
0
        private Transaction AssembleTx(Pb.UtxoOutput utxo, XCAccount account, List <string> authRequire,
                                       string to, BigInteger amount, Pb.InvokeResponse contractInvoke, string desc)
        {
            var tx = new Transaction();

            // check param
            if (amount < 0 || account == null)
            {
                return(null);
            }
            // if have utxo, assemble utxo input/ouput
            if (utxo != null)
            {
                // assemble TxInputs
                tx.TxInputs = new List <TxInput>();
                var total = BigInteger.Parse(utxo.TotalSelected);
                for (var i = 0; i < utxo.UtxoList.Count; i++)
                {
                    var utxoItem = utxo.UtxoList[i];
                    var input    = new TxInput
                    {
                        FromAddr  = utxoItem.ToAddr.ToByteArray(),
                        Amount    = utxoItem.Amount.ToByteArray(),
                        RefTxid   = utxoItem.RefTxid.ToByteArray(),
                        RefOffset = utxoItem.RefOffset,
                    };
                    tx.TxInputs.Add(input);
                }

                tx.TxOutputs = new List <TxOutput>();
                // Assemble utxo Output for transferring to
                if (amount > 0 && to != "")
                {
                    // utxo check
                    if (amount > total)
                    {
                        Console.WriteLine("Utxo use greater than utxo selected" + ", selected=" + total + ", use=", amount);
                        return(null);
                    }
                    var output = new TxOutput()
                    {
                        ToAddr = Encoding.ASCII.GetBytes(to),
                        Amount = amount.ToByteArray(),
                    };
                    Array.Reverse(output.Amount, 0, output.Amount.Length);
                    tx.TxOutputs.Add(output);
                    total -= amount;
                }

                // Assemble contract fee
                if (contractInvoke != null && contractInvoke.GasUsed > 0)
                {
                    var gasUsed = new BigInteger(contractInvoke.GasUsed);
                    if (gasUsed > total)
                    {
                        Console.WriteLine("Utxo use greater than utxo selected" + ", selected=" + total + ", use=", gasUsed);
                        return(null);
                    }
                    var output = new TxOutput()
                    {
                        ToAddr = Encoding.ASCII.GetBytes("$"),
                        Amount = gasUsed.ToByteArray(),
                    };
                    Array.Reverse(output.Amount, 0, output.Amount.Length);
                    tx.TxOutputs.Add(output);
                    total -= gasUsed;
                }

                // charge utxo to user
                if (total > 0)
                {
                    var chargeOutput = new TxOutput()
                    {
                        ToAddr = Encoding.ASCII.GetBytes(account.Address),
                        Amount = total.ToByteArray(),
                    };
                    Array.Reverse(chargeOutput.Amount, 0, chargeOutput.Amount.Length);
                    tx.TxOutputs.Add(chargeOutput);
                }
            }

            // Assemble contracts
            if (contractInvoke != null)
            {
                if (contractInvoke.Inputs.Count > 0)
                {
                    tx.TxInputsExt = new List <TxInputExt>();
                }
                if (contractInvoke.Outputs.Count > 0)
                {
                    tx.TxOutputsExt = new List <TxOutputExt>();
                }
                if (contractInvoke.Requests.Count > 0)
                {
                    tx.ContractRequests = new List <InvokeRequest>();
                }
                // TODO: transfer within contract is not supported
                foreach (var input in contractInvoke.Inputs)
                {
                    var inputExt = new TxInputExt
                    {
                        Bucket    = input.Bucket,
                        Key       = input.Key.ToByteArray(),
                        RefTxid   = input.RefTxid.ToByteArray(),
                        RefOffset = input.RefOffset,
                    };
                    tx.TxInputsExt.Add(inputExt);
                }
                foreach (var output in contractInvoke.Outputs)
                {
                    var outputExt = new TxOutputExt
                    {
                        Bucket = output.Bucket,
                        Key    = output.Key.ToByteArray(),
                        Value  = output.Value.ToByteArray(),
                    };
                    tx.TxOutputsExt.Add(outputExt);
                }
                foreach (var request in contractInvoke.Requests)
                {
                    var invoke = new InvokeRequest
                    {
                        ModuleName   = request.ModuleName,
                        ContractName = request.ContractName,
                        MethodName   = request.MethodName,
                    };
                    foreach (var arg in request.Args)
                    {
                        invoke.Args.Add(arg.Key, arg.Value.ToByteArray());
                    }
                    foreach (var limit in request.ResourceLimits)
                    {
                        invoke.ResourceLimits.Add(new ResourceLimit
                        {
                            Type  = (ResourceType)limit.Type,
                            Limit = limit.Limit,
                        });
                    }
                    tx.ContractRequests.Add(invoke);
                }
            }

            // Assemble other data
            tx.Desc      = Encoding.ASCII.GetBytes(desc);
            tx.Version   = 1;
            tx.Coinbase  = false;
            tx.Autogen   = false;
            tx.Initiator = account.Address;
            if (authRequire != null && authRequire.Count > 0)
            {
                tx.AuthRequire = authRequire;
            }
            var digestHash = XDigest.MakeDigestHash(tx);
            var sign       = XCrypto.SignHash(account.PrivateKey, digestHash);
            var signInfo   = new SignatureInfo()
            {
                PublicKey = account.PublicKey.RawKey,
                Sign      = sign,
            };

            tx.InitiatorSigns = new List <SignatureInfo>();
            tx.InitiatorSigns.Add(signInfo);
            if (authRequire != null && authRequire.Count > 0)
            {
                tx.AuthRequireSigns = new List <SignatureInfo>();
                tx.AuthRequireSigns.Add(signInfo);
            }
            var txid = XDigest.MakeTransactionID(tx);

            tx.Txid = txid;
            return(tx);
        }