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); }