mirror of
https://github.com/Nathanwoodburn/FireWallet.git
synced 2024-11-10 09:18:15 +11:00
multisig: Added multisig from batching
This commit is contained in:
parent
db5934bf4a
commit
f69f16df4a
@ -29,6 +29,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DnsClient" Version="1.7.0" />
|
<PackageReference Include="DnsClient" Version="1.7.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
||||||
<PackageReference Include="QRCoder" Version="1.4.3" />
|
<PackageReference Include="QRCoder" Version="1.4.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using System.Windows.Forms.VisualStyles;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace FireWallet
|
namespace FireWallet
|
||||||
{
|
{
|
||||||
@ -10,15 +11,25 @@ namespace FireWallet
|
|||||||
int reqSigs;
|
int reqSigs;
|
||||||
int sigs;
|
int sigs;
|
||||||
string signedTX;
|
string signedTX;
|
||||||
|
string[] domains;
|
||||||
public ImportTXForm(MainForm mainForm)
|
public ImportTXForm(MainForm mainForm)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.mainForm = mainForm;
|
this.mainForm = mainForm;
|
||||||
|
tx = null;
|
||||||
|
}
|
||||||
|
public ImportTXForm(MainForm mainForm, string tx)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
this.mainForm = mainForm;
|
||||||
|
JObject txObj = JObject.Parse(tx);
|
||||||
|
this.tx = txObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ImportTXForm_Load(object sender, EventArgs e)
|
private void ImportTXForm_Load(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// Default variables
|
// Default variables
|
||||||
|
domains = new string[0];
|
||||||
signedTX = "";
|
signedTX = "";
|
||||||
totalSigs = 3;
|
totalSigs = 3;
|
||||||
reqSigs = 2;
|
reqSigs = 2;
|
||||||
@ -31,6 +42,8 @@ namespace FireWallet
|
|||||||
{
|
{
|
||||||
mainForm.ThemeControl(c);
|
mainForm.ThemeControl(c);
|
||||||
}
|
}
|
||||||
|
if (tx == null)
|
||||||
|
{
|
||||||
OpenFileDialog openFileDialog = new OpenFileDialog();
|
OpenFileDialog openFileDialog = new OpenFileDialog();
|
||||||
openFileDialog.Filter = "Transaction files (*.json)|*.json";
|
openFileDialog.Filter = "Transaction files (*.json)|*.json";
|
||||||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||||||
@ -40,7 +53,6 @@ namespace FireWallet
|
|||||||
{
|
{
|
||||||
JObject txObj = JObject.Parse(tx);
|
JObject txObj = JObject.Parse(tx);
|
||||||
this.tx = txObj;
|
this.tx = txObj;
|
||||||
ParseTX();
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -51,6 +63,8 @@ namespace FireWallet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ParseTX();
|
||||||
|
}
|
||||||
|
|
||||||
private void Cancelbutton2_Click(object sender, EventArgs e)
|
private void Cancelbutton2_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
@ -230,9 +244,6 @@ namespace FireWallet
|
|||||||
{
|
{
|
||||||
if (metaOutput.ContainsKey("name"))
|
if (metaOutput.ContainsKey("name"))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Label covenantLabel = new Label();
|
Label covenantLabel = new Label();
|
||||||
string name = metaOutput["name"].ToString();
|
string name = metaOutput["name"].ToString();
|
||||||
|
|
||||||
@ -240,6 +251,14 @@ namespace FireWallet
|
|||||||
covenantLabel.Location = new Point(5, 25);
|
covenantLabel.Location = new Point(5, 25);
|
||||||
covenantLabel.AutoSize = true;
|
covenantLabel.AutoSize = true;
|
||||||
PanelOutput.Controls.Add(covenantLabel);
|
PanelOutput.Controls.Add(covenantLabel);
|
||||||
|
|
||||||
|
string[] domainsNew = new string[domains.Length + 1];
|
||||||
|
for (int j = 0; j < domains.Length; j++)
|
||||||
|
{
|
||||||
|
domainsNew[j] = domains[j];
|
||||||
|
}
|
||||||
|
domainsNew[domainsNew.Length - 1] = name;
|
||||||
|
domains = domainsNew;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,12 +307,14 @@ namespace FireWallet
|
|||||||
labelSigsSigned.Width = (labelSigsTotal.Width / totalSigs) * sigs;
|
labelSigsSigned.Width = (labelSigsTotal.Width / totalSigs) * sigs;
|
||||||
labelSigInfo.Text = "Signed: " + sigs + "\nReq: " + reqSigs + " of " + totalSigs;
|
labelSigInfo.Text = "Signed: " + sigs + "\nReq: " + reqSigs + " of " + totalSigs;
|
||||||
signedTX = response;
|
signedTX = response;
|
||||||
|
} else {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buttonExport_Click(object sender, EventArgs e)
|
private void buttonExport_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
mainForm.ExportTransaction(signedTX);
|
mainForm.ExportTransaction(signedTX,domains);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void buttonSend_Click(object sender, EventArgs e)
|
private async void buttonSend_Click(object sender, EventArgs e)
|
||||||
|
@ -6,6 +6,7 @@ using System.Security.Cryptography;
|
|||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows.Forms.VisualStyles;
|
||||||
using DnsClient;
|
using DnsClient;
|
||||||
using DnsClient.Protocol;
|
using DnsClient.Protocol;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
@ -1982,6 +1983,26 @@ namespace FireWallet
|
|||||||
}
|
}
|
||||||
ExportTransaction(output);
|
ExportTransaction(output);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string content = "{\"method\": \"createsendtoaddress\",\"params\": [ \"" + address + "\", " +
|
||||||
|
amount.ToString() + ", \"\", \"\", " + subtractFee + " ]}";
|
||||||
|
string output = await APIPost("", true, content);
|
||||||
|
JObject APIresp = JObject.Parse(output);
|
||||||
|
if (APIresp["error"].ToString() != "")
|
||||||
|
{
|
||||||
|
AddLog("Failed:");
|
||||||
|
AddLog(APIresp.ToString());
|
||||||
|
JObject error = JObject.Parse(APIresp["error"].ToString());
|
||||||
|
string ErrorMessage = error["message"].ToString();
|
||||||
|
|
||||||
|
NotifyForm notify = new NotifyForm("Error Transaction Failed\n" + ErrorMessage);
|
||||||
|
notify.ShowDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string signed = signRaw(output,new string[0]);
|
||||||
|
ExportTransaction(signed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2521,6 +2542,7 @@ namespace FireWallet
|
|||||||
BatchMode = true;
|
BatchMode = true;
|
||||||
}
|
}
|
||||||
BatchForm.AddBatch(domain, operation);
|
BatchForm.AddBatch(domain, operation);
|
||||||
|
BatchForm.UpdateTheme();
|
||||||
|
|
||||||
}
|
}
|
||||||
public void AddBatch(string domain, string operation, decimal bid, decimal lockup)
|
public void AddBatch(string domain, string operation, decimal bid, decimal lockup)
|
||||||
@ -2533,6 +2555,7 @@ namespace FireWallet
|
|||||||
BatchMode = true;
|
BatchMode = true;
|
||||||
}
|
}
|
||||||
BatchForm.AddBatch(domain, operation, bid, lockup);
|
BatchForm.AddBatch(domain, operation, bid, lockup);
|
||||||
|
BatchForm.UpdateTheme();
|
||||||
|
|
||||||
}
|
}
|
||||||
public void AddBatch(string domain, string operation, DNS[] updateRecords)
|
public void AddBatch(string domain, string operation, DNS[] updateRecords)
|
||||||
@ -2544,6 +2567,7 @@ namespace FireWallet
|
|||||||
BatchMode = true;
|
BatchMode = true;
|
||||||
}
|
}
|
||||||
BatchForm.AddBatch(domain, operation, updateRecords);
|
BatchForm.AddBatch(domain, operation, updateRecords);
|
||||||
|
BatchForm.UpdateTheme();
|
||||||
}
|
}
|
||||||
public void AddBatch(string domain, string operation, string address)
|
public void AddBatch(string domain, string operation, string address)
|
||||||
{
|
{
|
||||||
@ -2554,6 +2578,7 @@ namespace FireWallet
|
|||||||
BatchMode = true;
|
BatchMode = true;
|
||||||
}
|
}
|
||||||
BatchForm.AddBatch(domain, operation, address);
|
BatchForm.AddBatch(domain, operation, address);
|
||||||
|
BatchForm.UpdateTheme();
|
||||||
}
|
}
|
||||||
public void FinishBatch()
|
public void FinishBatch()
|
||||||
{
|
{
|
||||||
@ -2699,7 +2724,11 @@ namespace FireWallet
|
|||||||
|
|
||||||
|
|
||||||
#region Multi
|
#region Multi
|
||||||
public void ExportTransaction(string rawTX)
|
public async Task<string> ExportTransaction(string rawTX)
|
||||||
|
{
|
||||||
|
return await ExportTransaction(rawTX, new string[0]);
|
||||||
|
}
|
||||||
|
public async Task<string> ExportTransaction(string rawTX, string[] domains)
|
||||||
{
|
{
|
||||||
JObject tx = JObject.Parse(rawTX);
|
JObject tx = JObject.Parse(rawTX);
|
||||||
JObject toExport = new JObject();
|
JObject toExport = new JObject();
|
||||||
@ -2709,6 +2738,14 @@ namespace FireWallet
|
|||||||
JArray outputsParsed = new JArray();
|
JArray outputsParsed = new JArray();
|
||||||
JArray inputs = JArray.Parse(tx["inputs"].ToString());
|
JArray inputs = JArray.Parse(tx["inputs"].ToString());
|
||||||
JArray outputs = JArray.Parse(tx["outputs"].ToString());
|
JArray outputs = JArray.Parse(tx["outputs"].ToString());
|
||||||
|
|
||||||
|
Dictionary<string,string> hashes = new Dictionary<string, string>();
|
||||||
|
foreach (string domain in domains)
|
||||||
|
{
|
||||||
|
// sha3 hash of domain
|
||||||
|
hashes.Add(CalculateSHA3Hash(domain),domain);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (JObject input in inputs)
|
foreach (JObject input in inputs)
|
||||||
{
|
{
|
||||||
JObject coin = JObject.Parse(input["coin"].ToString());
|
JObject coin = JObject.Parse(input["coin"].ToString());
|
||||||
@ -2722,6 +2759,7 @@ namespace FireWallet
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddLog("Not supported yet");
|
AddLog("Not supported yet");
|
||||||
|
return "Error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (JObject output in outputs)
|
foreach (JObject output in outputs)
|
||||||
@ -2735,7 +2773,20 @@ namespace FireWallet
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddLog("Not supported yet");
|
AddLog(covenant.ToString());
|
||||||
|
string hash = covenant["items"][0].ToString();
|
||||||
|
if (hashes.ContainsKey(hash))
|
||||||
|
{
|
||||||
|
data["name"] = hashes[hash];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddLog("Cannot find name for hash " + hash);
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
|
||||||
|
//data["name"];
|
||||||
|
outputsParsed.Add(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JObject metadata = new JObject();
|
JObject metadata = new JObject();
|
||||||
@ -2753,8 +2804,81 @@ namespace FireWallet
|
|||||||
StreamWriter sw = new StreamWriter(saveFileDialog.FileName);
|
StreamWriter sw = new StreamWriter(saveFileDialog.FileName);
|
||||||
sw.Write(toExport.ToString());
|
sw.Write(toExport.ToString());
|
||||||
sw.Dispose();
|
sw.Dispose();
|
||||||
|
return toExport.ToString();
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
return "Error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public string signRaw(string tx, string[] domains)
|
||||||
|
{
|
||||||
|
string domainslist = string.Join(",", domains.Select(domain => "\\\"" + domain + "\\\""));
|
||||||
|
NotifyForm notify = new NotifyForm("Please confirm the transaction on your Ledger device", false);
|
||||||
|
notify.Show();
|
||||||
|
|
||||||
|
var proc = new Process();
|
||||||
|
proc.StartInfo.CreateNoWindow = true;
|
||||||
|
proc.StartInfo.RedirectStandardInput = true;
|
||||||
|
proc.StartInfo.RedirectStandardOutput = true;
|
||||||
|
proc.StartInfo.UseShellExecute = false;
|
||||||
|
proc.StartInfo.RedirectStandardError = true;
|
||||||
|
proc.StartInfo.FileName = "node.exe";
|
||||||
|
proc.StartInfo.WorkingDirectory = dir + "hsd-ledger/bin/";
|
||||||
|
string args = "hsd-ledger/bin/hsd-ledger signraw \"\"" + tx.Replace("\"", "\\\"").Trim() + "\"\" [" + domainslist + "] --api-key " + NodeSettings["Key"] + " -w " + Account;
|
||||||
|
AddLog(args);
|
||||||
|
|
||||||
|
proc.StartInfo.Arguments = dir + args;
|
||||||
|
var outputBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
// Event handler for capturing output data
|
||||||
|
proc.OutputDataReceived += (sender, args) =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(args.Data))
|
||||||
|
{
|
||||||
|
outputBuilder.AppendLine(args.Data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
proc.Start();
|
||||||
|
proc.BeginOutputReadLine();
|
||||||
|
proc.WaitForExit();
|
||||||
|
|
||||||
|
notify.CloseNotification();
|
||||||
|
notify.Dispose();
|
||||||
|
|
||||||
|
string output = outputBuilder.ToString();
|
||||||
|
AddLog(output);
|
||||||
|
if (output.Length > 2)
|
||||||
|
{
|
||||||
|
// Signed
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddLog(args);
|
||||||
|
AddLog(proc.StandardError.ReadToEnd());
|
||||||
|
NotifyForm notifyError = new NotifyForm("Error sign Failed\nCheck logs for more details");
|
||||||
|
notifyError.ShowDialog();
|
||||||
|
notifyError.Dispose();
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static string CalculateSHA3Hash(string input)
|
||||||
|
{
|
||||||
|
var hashAlgorithm = new Org.BouncyCastle.Crypto.Digests.Sha3Digest(256);
|
||||||
|
|
||||||
|
// Choose correct encoding based on your usecase
|
||||||
|
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
|
||||||
|
|
||||||
|
hashAlgorithm.BlockUpdate(inputBytes, 0, inputBytes.Length);
|
||||||
|
|
||||||
|
byte[] result = new byte[256/8];
|
||||||
|
hashAlgorithm.DoFinal(result, 0);
|
||||||
|
|
||||||
|
string hashString = BitConverter.ToString(result);
|
||||||
|
hashString = hashString.Replace("-", "").ToLowerInvariant();
|
||||||
|
return hashString;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user