bool IsConfirmedUTXOExist(Types.Outpoint outpoint) { using (var dbTx = _DBContext.GetTransactionContext()) { return(UTXOStore.ContainsKey(dbTx, outpoint)); } }
public static Types.Transaction AddInput(this Types.Transaction tx, Types.Outpoint outpoint) { return(new Types.Transaction(tx.version, FSharpList <Types.Outpoint> .Cons(outpoint, tx.inputs), tx.witnesses, tx.outputs, tx.contract)); }
public void CanUseEquals() { Types.Outpoint o1 = new Types.Outpoint(new byte[] { 0x00 }, 1); Types.Outpoint o2 = new Types.Outpoint(new byte[] { 0x00 }, 1); Assert.IsFalse(o1.GetHashCode() != o2.GetHashCode()); Assert.IsFalse(o1 == o2); Assert.IsTrue(o1.Equals(o2)); }
public bool ContainsOutpoint(Types.Outpoint outpoint) { foreach (var item in this) { if (item.Value.pInputs.Select(t => t.Item1).Contains(outpoint)) { return(true); } } return(false); }
public void CanUseEqualsWithLists() { Types.Outpoint o1 = new Types.Outpoint(new byte[] { 0x00 }, 1); Types.Outpoint o2 = new Types.Outpoint(new byte[] { 0x00 }, 1); IList <Types.Outpoint> list = new List <Types.Outpoint>(); list.Add(o1); Assert.IsTrue(list.Contains(o1)); Assert.IsTrue(list.Contains(o2)); }
public void CanUseEqualsWithMaps() { Types.Outpoint o1 = new Types.Outpoint(new byte[] { 0x00 }, 1); Types.Outpoint o2 = new Types.Outpoint(new byte[] { 0x00 }, 1); IDictionary <Types.Outpoint, Types.Transaction> dictionary = new Dictionary <Types.Outpoint, Types.Transaction>(); dictionary.Add(o1, Util.GetNewTransaction(1)); Assert.IsTrue(dictionary.ContainsKey(o1)); Assert.IsTrue(dictionary.ContainsKey(o2)); }
//TODO: refactore for efficiency bool HasUtxos(TransactionValidation.PointedTransaction ptx) { foreach (var input in ptx.pInputs) { foreach (var tx in _ValidatedTxs) { foreach (var txInput in tx.pInputs) { if (input.Item1.Equals(txInput)) { return(false); } } } } foreach (var input in ptx.pInputs) { foreach (var tx in _ValidatedTxs) { var txHash = Merkle.transactionHasher.Invoke(TransactionValidation.unpoint(ptx)); for (var i = 0; i < tx.outputs.Length; i++) { var outpoint = new Types.Outpoint(txHash, (uint)i); if (input.Item1.Equals(outpoint)) { return(true); } } } } foreach (var input in ptx.pInputs) { if (!_UtxoSet.Any(t => t.Item1.Equals(input.Item1))) { return(false); } } return(true); }
bool ExtendMain(List <QueueAction> queuedActions, double totalWork, bool isGenesis = false) { if (_BlockChain.BlockStore.ContainsKey(_DbTx, _BkHash)) { _BlockChain.BlockStore.SetLocation(_DbTx, _BkHash, LocationEnum.Main); } else { _BlockChain.BlockStore.Put(_DbTx, _BkHash, _Bk, LocationEnum.Main, totalWork); } _BlockChain.Timestamps.Push(_Bk.header.timestamp); if (_Bk.header.blockNumber % 2000 == 0) { _BlockChain.BlockNumberDifficulties.Add(_DbTx.Transaction, _Bk.header.blockNumber, _BkHash); } var blockUndoData = new BlockUndoData(); var confirmedTxs = new HashDictionary <TransactionValidation.PointedTransaction>(); //TODO: lock with mempool for (var txIdx = 0; txIdx < _Bk.transactions.Count(); txIdx++) { var tx = _Bk.transactions[txIdx]; var txHash = Merkle.transactionHasher.Invoke(tx); TransactionValidation.PointedTransaction ptx; if (!isGenesis) { if ((txIdx == 0 && !IsCoinbaseTxValid(tx)) || (txIdx > 0 && IsCoinbaseTxValid(tx))) { if (txIdx == 0) { BlockChainTrace.Information("Invalid coinbase tx"); } else { BlockChainTrace.Information($"Invalid tx ({txIdx})"); } return(false); } if (!IsTransactionValid(tx, txHash, out ptx)) { return(false); } confirmedTxs[txHash] = ptx; foreach (var pInput in ptx.pInputs) { _BlockChain.UTXOStore.Remove(_DbTx, pInput.Item1); BlockChainTrace.Information($"utxo spent, amount {pInput.Item2.spend.amount}", ptx); //BlockChainTrace.Information($" of", pInput.Item1.txHash); blockUndoData.RemovedUTXO.Add(new Tuple <Types.Outpoint, Types.Output>(pInput.Item1, pInput.Item2)); } } else { ptx = TransactionValidation.toPointedTransaction( tx, ListModule.Empty <Types.Output>() ); } _BlockChain.BlockStore.TxStore.Put(_DbTx, txHash, tx, true); var contractExtendSacrifices = new HashDictionary <ulong>(); var activationSacrifice = 0UL; for (var outputIdx = 0; outputIdx < tx.outputs.Count(); outputIdx++) { var output = tx.outputs[outputIdx]; if ([email protected]) { if (!output.spend.asset.SequenceEqual(Tests.zhash)) { continue; // not Zen } var contractSacrificeLock = (Types.OutputLock.ContractSacrificeLock)output.@lock; if (contractSacrificeLock.IsHighVLock) { continue; // not current version } if (contractSacrificeLock.Item.lockData.Length > 0 && contractSacrificeLock.Item.lockData[0] != null && contractSacrificeLock.Item.lockData[0].Length > 0) { var contractKey = contractSacrificeLock.Item.lockData[0]; // output-lock-level indicated contract contractExtendSacrifices[contractKey] = (contractExtendSacrifices.ContainsKey(contractKey) ? contractExtendSacrifices[contractKey] : 0) + output.spend.amount; } else if (contractSacrificeLock.Item.lockData.Length == 0) { activationSacrifice += output.spend.amount; } } //todo: fix to exclude CSLocks&FLocks, instead of including by locktype if ([email protected] || [email protected]) { BlockChainTrace.Information($"new utxo, amount {output.spend.amount}", tx); var outpoint = new Types.Outpoint(txHash, (uint)outputIdx); _BlockChain.UTXOStore.Put(_DbTx, outpoint, output); blockUndoData.AddedUTXO.Add(new Tuple <Types.Outpoint, Types.Output>(outpoint, output)); } } if (FSharpOption <Types.ExtendedContract> .get_IsSome(tx.contract) && !tx.contract.Value.IsHighVContract) { var codeBytes = ((Types.ExtendedContract.Contract)tx.contract.Value).Item.code; var contractHash = Merkle.innerHash(codeBytes); var contractCode = System.Text.Encoding.ASCII.GetString(codeBytes); if (_BlockChain.ActiveContractSet.TryActivate(_DbTx, contractCode, activationSacrifice, contractHash, _Bk.header.blockNumber)) { blockUndoData.ACSDeltas.Add(contractHash, new ACSUndoData()); ContractsTxsStore.Add(_DbTx.Transaction, contractHash, txHash); } } foreach (var item in contractExtendSacrifices) { var currentACSItem = _BlockChain.ActiveContractSet.Get(_DbTx, item.Key); if (currentACSItem.Value != null) { if (_BlockChain.ActiveContractSet.TryExtend(_DbTx, item.Key, item.Value)) { if (!blockUndoData.ACSDeltas.ContainsKey(item.Key)) { blockUndoData.ACSDeltas.Add(item.Key, new ACSUndoData() { LastBlock = currentACSItem.Value.LastBlock }); } } } } } var expiringContracts = _BlockChain.ActiveContractSet.GetExpiringList(_DbTx, _Bk.header.blockNumber); foreach (var acsItem in expiringContracts) { if (!blockUndoData.ACSDeltas.ContainsKey(acsItem.Key)) { blockUndoData.ACSDeltas.Add(acsItem.Key, new ACSUndoData() { ACSItem = acsItem.Value }); } } if (!isGenesis) { _BlockChain.BlockStore.SetUndoData(_DbTx, _BkHash, blockUndoData); } _BlockChain.ActiveContractSet.DeactivateContracts(_DbTx, expiringContracts.Select(t => t.Key)); ValidateACS(); _BlockChain.ChainTip.Context(_DbTx).Value = _BkHash; //TODO: only update after commit _BlockChain.Tip = new Keyed <Types.Block>(_BkHash, _Bk); queuedActions.Add(new MessageAction(new BlockMessage(confirmedTxs, _Bk.header.blockNumber))); foreach (var item in confirmedTxs) { ConfirmedTxs[item.Key] = item.Value; UnconfirmedTxs.Remove(item.Key); } return(true); }
public WalletSendLayout() { this.Build(); SendInfo = new SendInfo(); _AssetsController = new AssetsController(this); _DeltasController = new DeltasController(this); vboxDataPaste.ModifyFg(StateType.Normal, Constants.Colors.DialogBackground.Gdk); eventboxSeperator.ModifyBg(StateType.Normal, Constants.Colors.Seperator.Gdk); eventboxSeperator1.ModifyBg(StateType.Normal, Constants.Colors.Seperator.Gdk); entryAmount.ModifyFg(StateType.Normal, Constants.Colors.Text2.Gdk); entryAmount.ModifyFont(Constants.Fonts.ActionBarSmall); labelBalance.ModifyFg(StateType.Normal, Constants.Colors.TextBlue.Gdk); labelBalance.ModifyFont(Constants.Fonts.LogBig); labelHeader.ModifyFg(StateType.Normal, Constants.Colors.TextHeader.Gdk); labelHeader.ModifyFont(Constants.Fonts.ActionBarBig); //error labels Apply((Label label) => { label.ModifyFg(StateType.Normal, Constants.Colors.Error.Gdk); label.ModifyFont(Constants.Fonts.ActionBarSmall); }, labelDestinationError, labelDataError, labelAmountError); //labels Apply((Label label) => { label.ModifyFg(StateType.Normal, Constants.Colors.LabelText.Gdk); label.ModifyFont(Constants.Fonts.ActionBarIntermediate); }, labelDestination, labelData, labelAmount, labelSelectAsset, labelBalanceHeader); //entries Apply((Entry entry) => { entry.ModifyBg(StateType.Normal, Constants.Colors.Seperator.Gdk); entry.ModifyText(StateType.Normal, Constants.Colors.Text.Gdk); entry.ModifyFont(Constants.Fonts.ActionBarSmall); entry.ModifyBase(StateType.Normal, Constants.Colors.ButtonUnselected.Gdk); }, entryDestination, entryAmount); txtData.ModifyFg(StateType.Normal, Constants.Colors.Text2.Gdk); txtData.ModifyFont(Constants.Fonts.ActionBarSmall); txtData.ModifyBase(StateType.Normal, Constants.Colors.ButtonUnselected.Gdk); txtData.ModifyText(StateType.Normal, Constants.Colors.Text.Gdk); _Tx = null; eventboxPasteAddress.ButtonPressEvent += delegate { try { var clipboard = Gtk.Clipboard.Get(Gdk.Atom.Intern("CLIPBOARD", true)); entryDestination.Text = clipboard.WaitForText(); } catch { } }; eventboxPasterData.ButtonPressEvent += delegate { try { var clipboard = Gtk.Clipboard.Get(Gdk.Atom.Intern("CLIPBOARD", true)); txtData.Buffer.Text = clipboard.WaitForText(); } catch { } }; vboxMainInner.Remove(vboxData); entryDestination.Changed += (sender, e) => { try { var value = ((Entry)sender).Text; var address = string.IsNullOrEmpty(value) ? null : new Address(value); SendInfo.Destination = address; labelDestinationError.Text = ""; vboxMainInner.Remove(vboxData); if (address != null && address.AddressType == AddressType.Contract) { vboxMainInner.Add(vboxData); vboxMainInner.ReorderChild(vboxData, 2); } } catch { SendInfo.Destination = null; labelDestinationError.Text = "Invalid address"; } UpdateButtons(); }; txtData.Buffer.Changed += (sender, e) => { var text = ((TextBuffer)sender).Text; if (string.IsNullOrWhiteSpace(text) || text.Trim().Length == 0) { SendInfo.Data = null; SendInfo.DataValid = true; labelDataError.Text = ""; } else { try { SendInfo.Data = JObject.Parse(text); //TODO: deeper validation SendInfo.DataValid = true; labelDataError.Text = ""; } catch { SendInfo.Data = null; SendInfo.DataValid = false; labelDataError.Text = "Invalid data"; } } UpdateButtons(); }; entryAmount.Changed += (sender, e) => { var text = ((Entry)sender).Text; if (text.Trim().Length == 0) { SendInfo.Amount = 0; labelAmountError.Text = ""; } else { Zen zen; if (!Zen.IsValidText(text, out zen)) { SendInfo.Amount = 0; labelAmountError.Text = "Invalid amount"; } else { SendInfo.Amount = zen.Kalapas; CheckAssetAmount(); } } UpdateButtons(); }; eventboxBack.ButtonPressEvent += Back; comboboxAsset.Model = _AssetsStore; var textRenderer = new CellRendererText(); comboboxAsset.PackStart(textRenderer, false); comboboxAsset.AddAttribute(textRenderer, "text", 1); comboboxAsset.Changed += (sender, e) => { var comboBox = sender as Gtk.ComboBox; TreeIter iter; if (comboBox.GetActiveIter(out iter)) { var value = new GLib.Value(); comboBox.Model.GetValue(iter, 0, ref value); byte[] asset = value.Val as byte[]; SendInfo.Asset = asset; } else { SendInfo.Asset = null; } // var assetMatadataList = App.Instance.AssetsMetadata.GetAssetMatadataList().Where(t => t.Asset.SequenceEqual(SendInfo.Asset)); // if (assetMatadataList.Count() != 0) // { // labelSelectedAsset.Text = assetMatadataList.First().Display; // labelSelectedAsset1.Text = assetMatadataList.First().Display; //} UpdateBalance(); }; TreeIter iterDefault; if (_AssetsStore.Find(t => t.SequenceEqual(Consensus.Tests.zhash), out iterDefault)) { comboboxAsset.SetActiveIter(iterDefault); } UpdateBalance(); eventboxSend.ButtonPressEvent += async delegate { SendInfo.Reset(); UpdateStatus(""); HideButtons(); if (SendInfo.Destination.AddressType == AddressType.Contract && SendInfo.Data != null) { try { var data = SendInfo.Data; byte[] firstData = null; if (data["first"] is JObject) { byte[] signature; var pubkey = Convert.FromBase64String(data["first"]["pubkey"].Value <string>()); var toSign = Convert.FromBase64String(data["first"]["toSign"].Value <string>()); //TODO: run on non-ui thread? if (!App.Instance.Wallet.SignData(pubkey, toSign, out signature)) { labelDataError.Text = "Could not sign data"; UpdateButtons(); return; } byte[] _data = Convert.FromBase64String(data["first"]["data"].Value <string>()); firstData = _data.Concat(signature).ToArray(); } else { firstData = Convert.FromBase64String(data["first"].ToString()); } SendInfo.Destination.Data = firstData; if (data["second"] is JObject) { SendInfo.Json = ContractUtilities.DataGenerator.parseJson(data.ToString()); SendInfo.NeedAutoTx = true; } } catch { labelDataError.Text = "Could not parse data"; UpdateButtons(); return; } } _Tx = await Task.Run(() => App.Instance.Wallet.Sign( SendInfo.Destination, SendInfo.Asset, SendInfo.Amount )); SendInfo.Signed = _Tx != null; if (!SendInfo.Signed) { Gtk.Application.Invoke(delegate { UpdateStatus("Could not sign transaction"); }); return; } await Task.Run(() => { try { WalletSendLayout.SendInfo.TxResult = App.Instance.Node.Transmit(WalletSendLayout.Tx).Result; if (WalletSendLayout.SendInfo.TxResult != BlockChain.BlockChain.TxResultEnum.Accepted) { Gtk.Application.Invoke(delegate { UpdateStatus($"Could not broadcast transaction ({WalletSendLayout.SendInfo.TxResult})"); }); } else if (!WalletSendLayout.SendInfo.NeedAutoTx) { Gtk.Application.Invoke(delegate { UpdateStatus("Transaction transmitted", true); }); } else { var outputIdx = WalletSendLayout.Tx.outputs.ToList().FindIndex(t => t.@lock is Consensus.Types.OutputLock.ContractLock); var outpoint = new Types.Outpoint(Merkle.transactionHasher.Invoke(WalletSendLayout.Tx), (uint)outputIdx); byte[] witnessData = ContractUtilities.DataGenerator.makeMessage( WalletSendLayout.SendInfo.Json, outpoint); var autoTxResult = new ExecuteContractAction() { ContractHash = WalletSendLayout.SendInfo.Destination.Bytes, Message = witnessData }.Publish().Result; WalletSendLayout.SendInfo.AutoTxCreated = autoTxResult.Item1; if (WalletSendLayout.SendInfo.AutoTxCreated) { WalletSendLayout.SendInfo.AutoTxResult = App.Instance.Node.Transmit(autoTxResult.Item2).Result; if (WalletSendLayout.SendInfo.AutoTxResult == BlockChain.BlockChain.TxResultEnum.Accepted) { Gtk.Application.Invoke(delegate { UpdateStatus("Transmitted", true); }); } else { Gtk.Application.Invoke(delegate { UpdateStatus($"Could not broadcast auto transaction ({WalletSendLayout.SendInfo.AutoTxResult})"); }); } } else { Gtk.Application.Invoke(delegate { UpdateStatus($"Could not execute contract"); }); } } } catch { Gtk.Application.Invoke(delegate { UpdateStatus("Error sending message to contract"); }); } }); }; }
Types.Output GetUTXO(Types.Outpoint outpoint, TransactionContext dbTx, bool isInBlock, out bool valid, TransactionValidation.PointedTransaction validatingPtx = null) { valid = true; if (!isInBlock) { foreach (var item in memPool.TxPool) { foreach (var pInput in item.Value.pInputs) { if (outpoint.Equals(pInput.Item1)) { return(null); } } } } var result = UTXOStore.Get(dbTx, outpoint); if (result != null) { return(result.Value); } if (isInBlock) { return(null); } if (!memPool.TxPool.Contains(outpoint.txHash)) { return(null); } if (validatingPtx == null) { var tx = memPool.TxPool[outpoint.txHash]; if (tx.outputs.Count() > outpoint.index) { return(tx.outputs[(int)outpoint.index]); } else { valid = false; } } else { foreach (var pInput in validatingPtx.pInputs) { if (outpoint.Equals(pInput.Item1)) { return(pInput.Item2); } } } return(null); }
void HandleTx(TransactionValidation.PointedTransaction ptx) { //TODO: try simplify using hash from message var txHash = Merkle.transactionHasher.Invoke(TransactionValidation.unpoint(ptx)); var activationSacrifice = 0UL; for (var i = 0; i < ptx.outputs.Length; i++) { var output = ptx.outputs[i]; if ([email protected]) { if (!output.spend.asset.SequenceEqual(Tests.zhash)) { continue; // not Zen } var contractSacrificeLock = (Types.OutputLock.ContractSacrificeLock)output.@lock; if (contractSacrificeLock.IsHighVLock) { continue; // not current version } if (contractSacrificeLock.Item.lockData.Length == 0) { activationSacrifice += output.spend.amount; } } //todo: fix to exclude CSLocks&FLocks, instead of including by locktype if ([email protected] || [email protected]) { var outpoint = new Types.Outpoint(txHash, (uint)i); _UtxoSet.Add(new Tuple <Types.Outpoint, Types.Output>(outpoint, output)); } } if (FSharpOption <Types.ExtendedContract> .get_IsSome(ptx.contract) && !ptx.contract.Value.IsHighVContract) { var codeBytes = ((Types.ExtendedContract.Contract)ptx.contract.Value).Item.code; var contractHash = Merkle.innerHash(codeBytes); var contractCode = System.Text.Encoding.ASCII.GetString(codeBytes); if (!_ActiveContracts.Contains(contractHash)) { if (activationSacrifice > ActiveContractSet.KalapasPerBlock(contractCode)) { try { var compiledCodeOpt = ContractExamples.FStarExecution.compile(contractCode); if (FSharpOption <byte[]> .get_IsSome(compiledCodeOpt)) { _ActiveContracts.Add(contractHash); } } catch (Exception e) { MinerTrace.Error("Could not compile contract " + Convert.ToBase64String(contractHash), e); } } } } }
public WalletSendConfirmationLayout() { this.Build(); Apply((Label label) => { label.ModifyFg(StateType.Normal, Constants.Colors.Success.Gdk); label.ModifyFont(Constants.Fonts.ActionBarSmall); }, labelStatus); Apply((EventBox eventbox) => { eventbox.ModifyBg(StateType.Normal, Constants.Colors.Textbox.Gdk); }, eventboxStatus, eventboxDestination, eventboxAsset, eventboxAmount); Apply((Label label) => { label.ModifyFg(StateType.Normal, Constants.Colors.SubText.Gdk); label.ModifyFont(Constants.Fonts.ActionBarIntermediate); }, labelDestination, labelAsset, labelAmount, labelAmountValue); Apply((Label label) => { label.ModifyFg(StateType.Normal, Constants.Colors.SubText.Gdk); label.ModifyFont(Constants.Fonts.ActionBarSmall); }, labelSelectedAsset, labelSelectedAsset1); Apply((Entry entry) => { entry.ModifyFg(StateType.Normal, Constants.Colors.Text2.Gdk); entry.ModifyFont(Constants.Fonts.ActionBarSmall); }, entryDestination); buttonBack.Clicked += Back; buttonTransmit.Clicked += async delegate { buttonTransmit.Sensitive = false; await Task.Run(() => { WalletSendLayout.SendInfo.TxResult = App.Instance.Node.Transmit(WalletSendLayout.Tx).Result; if (WalletSendLayout.SendInfo.TxResult == BlockChain.BlockChain.TxResultEnum.Accepted && WalletSendLayout.SendInfo.NeedAutoTx) { var outputIdx = WalletSendLayout.Tx.outputs.ToList().FindIndex(t => t.@lock is Consensus.Types.OutputLock.ContractLock); var outpoint = new Types.Outpoint(Merkle.transactionHasher.Invoke(WalletSendLayout.Tx), (uint)outputIdx); byte[] witnessData = ContractUtilities.DataGenerator.makeMessage( WalletSendLayout.SendInfo.Json, outpoint); var autoTxResult = new ExecuteContractAction() { ContractHash = WalletSendLayout.SendInfo.Destination.Bytes, Message = witnessData }.Publish().Result; WalletSendLayout.SendInfo.AutoTxCreated = autoTxResult.Item1; if (WalletSendLayout.SendInfo.AutoTxCreated) { WalletSendLayout.SendInfo.AutoTxResult = App.Instance.Node.Transmit(autoTxResult.Item2).Result; } } }); Gtk.Application.Invoke(delegate { buttonTransmit.Sensitive = true; UpdateStatus(); }); }; }
public ActionResult Generate() { if (!Directory.Exists("db")) { Directory.CreateDirectory("db"); } var contractManager = new OracleContractManager(); if (!contractManager.IsSetup) { ViewData["Result"] = false; ViewData["Message"] = contractManager.Message; return(View()); } _StockAPI.Tickers = WebConfigurationManager.AppSettings["tickers"].Split(','); var rawTickers = _StockAPI.FetchResults().Result; var now = DateTime.Now.ToUniversalTime(); var nowTicks = now.Ticks; var items = rawTickers.Select(t => new ContractExamples.Oracle.TickerItem(t.Name, t.Value, nowTicks)); var secret = Convert.FromBase64String(WebConfigurationManager.AppSettings["oracleSecret"]); var commitmentData = ContractExamples.Oracle.commitments(items, secret); var getOutpointsResult = Client.Send <GetContractPointedOutputsResultPayload>(NodeRPCAddress, new GetContractPointedOutputsPayload() { ContractHash = contractManager.ContractAddress.Bytes }).Result; if (!getOutpointsResult.Success || getOutpointsResult.PointedOutputs.Count == 0) { ViewData["Result"] = false; ViewData["Message"] = "Could not find outputs"; return(View()); } var utxos = GetContractPointedOutputsResultPayload.Unpack(getOutpointsResult.PointedOutputs); if (utxos.Count() == 0) { ViewData["Result"] = false; ViewData["Message"] = "Could not find output"; return(View()); } var utxo = utxos.First(); //var serializer = new ContractExamples.FStarCompatibility.DataSerializer(Consensus.Serialization.context); //Consensus.Serialization.context.Serializers.RegisterOverride(serializer); var data = ContractUtilities.DataGenerator.makeOracleMessage(commitmentData.Item2, utxo.Item1); //var data = ContractExamples.QuotedContracts.simplePackOutpoint(utxo.Item1) // .Concat(commitmentData.Item2).ToArray(); //var signiture = Authentication.sign(data, contractManager.PrivateKey); //data = data.Concat(signiture).ToArray(); var sendContractResult = Client.Send <SendContractResultPayload>(NodeRPCAddress, new SendContractPayload() { ContractHash = contractManager.ContractAddress.Bytes, Data = data }).Result; ViewData["Result"] = sendContractResult.Success; if (sendContractResult.Success) { var file = Path.Combine("db", $"{now.ToFileTime()}"); MemoryStream ms = new MemoryStream(); ContractExamples.Oracle.proofMapSerializer.WriteObject(ms, commitmentData.Item1); ms.Position = 0; var sr = new StreamReader(ms); System.IO.File.WriteAllText(Path.ChangeExtension(file, ".data.json"), sr.ReadToEnd()); var outpoint = new Types.Outpoint(sendContractResult.TxHash, 1); // oracle always puts data on output #1 System.IO.File.WriteAllText(Path.ChangeExtension(file, ".outpoint.txt"), Convert.ToBase64String(Merkle.serialize(outpoint))); } else { ViewData["Message"] = "Reason: send result was '" + sendContractResult.Message + "'"; } return(View()); }