Exemple #1
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);
        }
        public static Transaction PbTxToLocalTx(Pb.Transaction tx)
        {
            var localTx = new Transaction();

            localTx.Txid = tx.Txid.ToByteArray();
            if (!tx.Blockid.IsEmpty)
            {
                localTx.Blockid = tx.Blockid.ToByteArray();
            }
            if (tx.TxInputs != null && tx.TxInputs.Count > 0)
            {
                localTx.TxInputs = new List <TxInput>();
                foreach (var input in tx.TxInputs)
                {
                    localTx.TxInputs.Add(new TxInput
                    {
                        FromAddr     = input.FromAddr.ToByteArray(),
                        Amount       = input.Amount.ToByteArray(),
                        RefOffset    = input.RefOffset,
                        RefTxid      = input.RefTxid.ToByteArray(),
                        FrozenHeight = input.FrozenHeight,
                    });
                }
            }

            if (tx.TxOutputs != null && tx.TxOutputs.Count > 0)
            {
                localTx.TxOutputs = new List <TxOutput>();
                foreach (var output in tx.TxOutputs)
                {
                    localTx.TxOutputs.Add(new TxOutput
                    {
                        ToAddr       = output.ToAddr.ToByteArray(),
                        Amount       = output.Amount.ToByteArray(),
                        FrozenHeight = output.FrozenHeight,
                    });
                }
            }
            if (tx.Desc != null)
            {
                localTx.Desc = tx.Desc.ToByteArray();
            }
            localTx.Coinbase  = tx.Coinbase;
            localTx.Nonce     = tx.Nonce;
            localTx.Timestamp = tx.Timestamp;
            localTx.Version   = tx.Version;
            localTx.Autogen   = tx.Autogen;

            if (tx.TxInputsExt != null && tx.TxInputsExt.Count > 0)
            {
                localTx.TxInputsExt = new List <TxInputExt>();
                foreach (var input in tx.TxInputsExt)
                {
                    localTx.TxInputsExt.Add(new TxInputExt
                    {
                        Key       = input.Key.ToByteArray(),
                        Bucket    = input.Bucket,
                        RefTxid   = input.RefTxid.ToByteArray(),
                        RefOffset = input.RefOffset,
                    });
                }
            }

            if (tx.TxOutputsExt != null && tx.TxOutputsExt.Count > 0)
            {
                localTx.TxOutputsExt = new List <TxOutputExt>();
                foreach (var output in tx.TxOutputsExt)
                {
                    localTx.TxOutputsExt.Add(new TxOutputExt
                    {
                        Key    = output.Key.ToByteArray(),
                        Bucket = output.Bucket,
                        Value  = output.Value.ToByteArray(),
                    });
                }
            }

            if (tx.ContractRequests != null && tx.ContractRequests.Count > 0)
            {
                localTx.ContractRequests = new List <InvokeRequest>();
                foreach (var cr in tx.ContractRequests)
                {
                    var invokeReq = new InvokeRequest
                    {
                        ModuleName   = cr.ModuleName,
                        ContractName = cr.ContractName,
                        MethodName   = cr.MethodName,
                    };
                    foreach (var arg in cr.Args)
                    {
                        invokeReq.Args = new SortedDictionary <string, byte[]>();
                        invokeReq.Args.Add(arg.Key, arg.Value.ToByteArray());
                    }
                    foreach (var limit in cr.ResourceLimits)
                    {
                        invokeReq.ResourceLimits = new List <ResourceLimit>();
                        invokeReq.ResourceLimits.Add(new ResourceLimit
                        {
                            Type  = (ResourceType)limit.Type,
                            Limit = limit.Limit,
                        });
                    }
                    localTx.ContractRequests.Add(invokeReq);
                }
            }

            localTx.Initiator = tx.Initiator;
            if (tx.InitiatorSigns != null && tx.InitiatorSigns.Count > 0)
            {
                localTx.InitiatorSigns = new List <SignatureInfo>();
                foreach (var sign in tx.InitiatorSigns)
                {
                    localTx.InitiatorSigns.Add(new SignatureInfo
                    {
                        PublicKey = sign.PublicKey,
                        Sign      = sign.Sign.ToByteArray(),
                    });
                }
            }
            if (tx.AuthRequire != null && tx.AuthRequire.Count > 0)
            {
                localTx.AuthRequire = new List <string>();
                foreach (var addr in tx.AuthRequire)
                {
                    localTx.AuthRequire.Add(addr);
                }
            }
            if (tx.AuthRequireSigns != null && tx.AuthRequireSigns.Count > 0)
            {
                localTx.AuthRequireSigns = new List <SignatureInfo>();
                foreach (var sign in tx.AuthRequireSigns)
                {
                    localTx.AuthRequireSigns.Add(new SignatureInfo
                    {
                        PublicKey = sign.PublicKey,
                        Sign      = sign.Sign.ToByteArray(),
                    });
                }
            }

            return(localTx);
        }