multisig: Added info on signers

Added variables to track the number of total signers, required signers and signed signatures. Also added code to get multisig information from transaction inputs and display it in the UI.
This commit is contained in:
Nathan Woodburn 2023-06-26 18:13:08 +10:00
parent 5be4f0d6e9
commit 6da345e650
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
2 changed files with 174 additions and 30 deletions

View File

@ -35,6 +35,11 @@
panelOut = new Panel();
buttonSign = new Button();
Cancelbutton2 = new Button();
label1 = new Label();
labelSigsTotal = new Label();
labelSigsReq = new Label();
labelSigsSigned = new Label();
labelSigInfo = new Label();
groupBoxIn.SuspendLayout();
groupBoxOut.SuspendLayout();
SuspendLayout();
@ -44,7 +49,7 @@
groupBoxIn.Controls.Add(panelIn);
groupBoxIn.Location = new Point(12, 83);
groupBoxIn.Name = "groupBoxIn";
groupBoxIn.Size = new Size(341, 355);
groupBoxIn.Size = new Size(376, 355);
groupBoxIn.TabIndex = 3;
groupBoxIn.TabStop = false;
groupBoxIn.Text = "Inputs";
@ -55,15 +60,15 @@
panelIn.Dock = DockStyle.Fill;
panelIn.Location = new Point(3, 19);
panelIn.Name = "panelIn";
panelIn.Size = new Size(335, 333);
panelIn.Size = new Size(370, 333);
panelIn.TabIndex = 0;
//
// groupBoxOut
//
groupBoxOut.Controls.Add(panelOut);
groupBoxOut.Location = new Point(359, 83);
groupBoxOut.Location = new Point(391, 80);
groupBoxOut.Name = "groupBoxOut";
groupBoxOut.Size = new Size(429, 355);
groupBoxOut.Size = new Size(484, 355);
groupBoxOut.TabIndex = 0;
groupBoxOut.TabStop = false;
groupBoxOut.Text = "Outputs";
@ -74,25 +79,26 @@
panelOut.Dock = DockStyle.Fill;
panelOut.Location = new Point(3, 19);
panelOut.Name = "panelOut";
panelOut.Size = new Size(423, 333);
panelOut.Size = new Size(478, 333);
panelOut.TabIndex = 0;
//
// buttonSign
//
buttonSign.FlatStyle = FlatStyle.Flat;
buttonSign.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
buttonSign.Location = new Point(705, 444);
buttonSign.Location = new Point(789, 444);
buttonSign.Name = "buttonSign";
buttonSign.Size = new Size(83, 36);
buttonSign.TabIndex = 2;
buttonSign.Text = "Sign";
buttonSign.UseVisualStyleBackColor = true;
buttonSign.Click += buttonSign_Click;
//
// Cancelbutton2
//
Cancelbutton2.FlatStyle = FlatStyle.Flat;
Cancelbutton2.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
Cancelbutton2.Location = new Point(616, 444);
Cancelbutton2.Location = new Point(700, 444);
Cancelbutton2.Name = "Cancelbutton2";
Cancelbutton2.Size = new Size(83, 36);
Cancelbutton2.TabIndex = 2;
@ -100,11 +106,60 @@
Cancelbutton2.UseVisualStyleBackColor = true;
Cancelbutton2.Click += Cancelbutton2_Click;
//
// label1
//
label1.AutoSize = true;
label1.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
label1.Location = new Point(12, 9);
label1.Name = "label1";
label1.Size = new Size(87, 21);
label1.TabIndex = 4;
label1.Text = "Signatures:";
//
// labelSigsTotal
//
labelSigsTotal.BackColor = Color.Blue;
labelSigsTotal.Location = new Point(105, 7);
labelSigsTotal.Name = "labelSigsTotal";
labelSigsTotal.Size = new Size(250, 32);
labelSigsTotal.TabIndex = 5;
//
// labelSigsReq
//
labelSigsReq.BackColor = Color.FromArgb(255, 128, 0);
labelSigsReq.Location = new Point(105, 7);
labelSigsReq.Name = "labelSigsReq";
labelSigsReq.Size = new Size(191, 32);
labelSigsReq.TabIndex = 6;
//
// labelSigsSigned
//
labelSigsSigned.BackColor = Color.Lime;
labelSigsSigned.Location = new Point(105, 7);
labelSigsSigned.Name = "labelSigsSigned";
labelSigsSigned.Size = new Size(100, 32);
labelSigsSigned.TabIndex = 7;
//
// labelSigInfo
//
labelSigInfo.AutoSize = true;
labelSigInfo.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
labelSigInfo.Location = new Point(361, 7);
labelSigInfo.Name = "labelSigInfo";
labelSigInfo.Size = new Size(19, 21);
labelSigInfo.TabIndex = 8;
labelSigInfo.Text = "#";
//
// ImportTXForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 485);
ClientSize = new Size(887, 485);
Controls.Add(labelSigInfo);
Controls.Add(labelSigsSigned);
Controls.Add(labelSigsReq);
Controls.Add(labelSigsTotal);
Controls.Add(label1);
Controls.Add(groupBoxOut);
Controls.Add(groupBoxIn);
Controls.Add(Cancelbutton2);
@ -113,11 +168,12 @@
Icon = (Icon)resources.GetObject("$this.Icon");
MaximizeBox = false;
Name = "ImportTXForm";
Text = "ImportTXForm";
Text = "Import TX";
Load += ImportTXForm_Load;
groupBoxIn.ResumeLayout(false);
groupBoxOut.ResumeLayout(false);
ResumeLayout(false);
PerformLayout();
}
#endregion
@ -127,5 +183,10 @@
private Button Cancelbutton2;
private Panel panelIn;
private Panel panelOut;
private Label label1;
private Label labelSigsTotal;
private Label labelSigsReq;
private Label labelSigsSigned;
private Label labelSigInfo;
}
}

View File

@ -6,6 +6,9 @@ namespace FireWallet
{
MainForm mainForm;
JObject tx;
int totalSigs;
int reqSigs;
int sigs;
public ImportTXForm(MainForm mainForm)
{
InitializeComponent();
@ -14,6 +17,11 @@ namespace FireWallet
private void ImportTXForm_Load(object sender, EventArgs e)
{
// Default variables
totalSigs = 3;
reqSigs = 2;
sigs = 0;
// Theme
this.BackColor = ColorTranslator.FromHtml(mainForm.Theme["background"]);
this.ForeColor = ColorTranslator.FromHtml(mainForm.Theme["foreground"]);
@ -74,6 +82,58 @@ namespace FireWallet
JArray inputs = (JArray)json["result"]["vin"];
JArray outputs = (JArray)json["result"]["vout"];
// Get multisig info
JObject firstIn = (JObject)inputs[0];
JArray witnesses = (JArray)firstIn["txinwitness"];
string scriptSig = witnesses[witnesses.Count - 1].ToString();
// decode script
string sigGetContent = "{\"method\":\"decodescript\",\"params\":[\"" + scriptSig + "\"]}";
string sigGetResponse = await mainForm.APIPost("", false, sigGetContent);
if (sigGetResponse == null)
{
NotifyForm notifyForm = new NotifyForm("Error decoding transaction");
notifyForm.ShowDialog();
notifyForm.Dispose();
return;
}
JObject sigGetJson = JObject.Parse(sigGetResponse);
if (sigGetJson["error"].ToString() != "")
{
NotifyForm notifyForm = new NotifyForm("Error decoding transaction");
notifyForm.ShowDialog();
notifyForm.Dispose();
return;
}
JObject sigGetResult = (JObject)sigGetJson["result"];
string[] asm = sigGetResult["asm"].ToString().Split(" ");
string totalSigsStr = asm[asm.Length - 2];
totalSigs = int.Parse(totalSigsStr.Replace("OP_",""));
reqSigs = int.Parse(sigGetResult["reqSigs"].ToString());
sigs = -1;
for (int i = 0; i < witnesses.Count; i++)
{
string witness = witnesses[i].ToString();
if (witness != "")
{
sigs++;
}
}
// Set sig label sizes
labelSigsReq.Width = (labelSigsTotal.Width / totalSigs) * reqSigs;
labelSigsSigned.Width = (labelSigsTotal.Width / totalSigs) * sigs;
labelSigInfo.Text = "Signed: " + sigs + "\nReq: " + reqSigs + " of "+ totalSigs;
for (int i = 0; i < inputs.Count; i++)
{
JObject input = (JObject)inputs[i];
@ -84,11 +144,6 @@ namespace FireWallet
PanelInput.Location = new Point(5, panelIn.Controls.Count * 50);
PanelInput.BorderStyle = BorderStyle.FixedSingle;
Label txid = new Label();
txid.Text = "TXID: " + input["txid"].ToString();
txid.Location = new Point(5, 5);
txid.AutoSize = true;
PanelInput.Controls.Add(txid);
if (metaInput.ContainsKey("sighashType"))
{
@ -99,19 +154,40 @@ namespace FireWallet
PanelInput.Controls.Add(sighashType);
}
//Label address = new Label();
//string addressString = input["address"].ToString().Substring(0, 5) + "..." + input["address"].ToString().Substring(input["address"].ToString().Length - 5, 5);
//address.Text = "Address: " + addressString;
//address.Location = new Point(5, 5);
//address.AutoSize = true;
//PanelInput.Controls.Add(address);
string txid = input["txid"].ToString();
int vout = int.Parse(input["vout"].ToString());
string txInfo = await mainForm.APIGet("tx/" + txid, false);
if (txInfo == "Error" || txInfo == "")
{
NotifyForm notifyForm = new NotifyForm("Error getting transaction info");
notifyForm.ShowDialog();
notifyForm.Dispose();
return;
}
else
{
JObject txInfoJson = JObject.Parse(txInfo);
JArray txoutputs = (JArray)txInfoJson["outputs"];
JObject txoutput = (JObject)txoutputs[vout];
string txoutputAddress = txoutput["address"].ToString();
Label address = new Label();
string addressString = txoutputAddress.Substring(0, 5) + "..." + txoutputAddress.Substring(txoutputAddress.Length - 5, 5);
address.Text = "Address: " + addressString;
address.Location = new Point(5, 5);
address.AutoSize = true;
PanelInput.Controls.Add(address);
Label amount = new Label();
Decimal value = Decimal.Parse(txoutput["value"].ToString()) / 1000000;
amount.Text = "Amount: " + value.ToString();
amount.Location = new Point(5, 25);
amount.AutoSize = true;
PanelInput.Controls.Add(amount);
}
//Label amount = new Label();
//Decimal value = Decimal.Parse(input["value"].ToString()) / 1000000;
//amount.Text = "Amount: " + value.ToString();
//amount.Location = new Point(5, 25);
//amount.AutoSize = true;
//PanelInput.Controls.Add(amount);
//if (input["path"].ToString() != "")
//{
@ -167,14 +243,14 @@ namespace FireWallet
}
bool own = false;
string addressResp = await mainForm.APIGet("wallet/" + mainForm.Account + "/key/" + addressRaw["string"].ToString(),true);
string addressResp = await mainForm.APIGet("wallet/" + mainForm.Account + "/key/" + addressRaw["string"].ToString(), true);
if (addressResp != "Error") own = true;
if (own)
{
Label ownAddress = new Label();
ownAddress.Text = "Own Address";
ownAddress.Location = new Point(PanelOutput.Width - 100, 5);
ownAddress.Location = new Point(PanelOutput.Width - 150, 5);
ownAddress.AutoSize = true;
PanelOutput.Controls.Add(ownAddress);
}
@ -182,11 +258,18 @@ namespace FireWallet
Label amount = new Label();
Decimal value = Decimal.Parse(output["value"].ToString());
amount.Text = "Amount: " + value.ToString();
amount.Location = new Point(PanelOutput.Width - 100, 25);
amount.Location = new Point(PanelOutput.Width - 150, 25);
amount.AutoSize = true;
PanelOutput.Controls.Add(amount);
panelOut.Controls.Add(PanelOutput);
}
}
private async void buttonSign_Click(object sender, EventArgs e)
{
string content = "{\"tx\":\"" + tx["tx"].ToString() + "\", \"passphrase\":\"" + mainForm.Password + "\"}";
string response = await mainForm.APIPost("wallet/" + mainForm.Account + "/sign", true, content);
mainForm.AddLog(response);
}
}
}