Skip to content

Commit 6f377b1

Browse files
Add script templates feature with 3 predefined templates as a start.
1 parent 08ce036 commit 6f377b1

17 files changed

+939
-92
lines changed

BitcoinTransactionTool/BitcoinTransactionTool.csproj

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,28 +163,43 @@
163163
<Compile Include="Backend\StackInt.cs" />
164164
<Compile Include="Models\BitcoinAddress.cs" />
165165
<Compile Include="Models\ButtonModel.cs" />
166+
<Compile Include="Models\PublicKeyModel.cs" />
166167
<Compile Include="Models\UTXO.cs" />
167168
<Compile Include="Services\Api.cs" />
168169
<Compile Include="Services\ErrorCollection.cs" />
169-
<Compile Include="Services\OPCodes.cs" />
170+
<Compile Include="Services\OperationConverter.cs" />
170171
<Compile Include="Services\PushServices.cs" />
171172
<Compile Include="Services\Response.cs" />
172-
<Compile Include="Services\TransactionQR.cs" />
173+
<Compile Include="Services\ScriptReader.cs" />
174+
<Compile Include="Services\ScriptToStringConverter.cs" />
173175
<Compile Include="Services\TransactionServices\BlockchainInfo.cs" />
174176
<Compile Include="Services\TransactionServices\BlockCypher.cs" />
175177
<Compile Include="Services\TxBuilder.cs" />
176178
<Compile Include="ViewModels\MainWindowViewModel.cs" />
177179
<Compile Include="Services\WindowManager.cs" />
178180
<Compile Include="ViewModels\QrViewModel.cs" />
181+
<Compile Include="ViewModels\ScrAddressViewModel.cs" />
182+
<Compile Include="ViewModels\ScrArbitraryDataViewModel.cs" />
179183
<Compile Include="ViewModels\ScriptViewModel.cs" />
184+
<Compile Include="ViewModels\ScriptVMBase.cs" />
185+
<Compile Include="ViewModels\ScrMultiSigViewModel.cs" />
180186
<Compile Include="ViewModels\TransactionEditViewModel.cs" />
181187
<Compile Include="ViewModels\TxJsonViewModel.cs" />
182188
<Compile Include="Views\QrView.xaml.cs">
183189
<DependentUpon>QrView.xaml</DependentUpon>
184190
</Compile>
191+
<Compile Include="Views\ScrAddressView.xaml.cs">
192+
<DependentUpon>ScrAddressView.xaml</DependentUpon>
193+
</Compile>
194+
<Compile Include="Views\ScrArbitraryDataView.xaml.cs">
195+
<DependentUpon>ScrArbitraryDataView.xaml</DependentUpon>
196+
</Compile>
185197
<Compile Include="Views\ScriptView.xaml.cs">
186198
<DependentUpon>ScriptView.xaml</DependentUpon>
187199
</Compile>
200+
<Compile Include="Views\ScrMultiSigView.xaml.cs">
201+
<DependentUpon>ScrMultiSigView.xaml</DependentUpon>
202+
</Compile>
188203
<Compile Include="Views\TransactionEditView.xaml.cs">
189204
<DependentUpon>TransactionEditView.xaml</DependentUpon>
190205
</Compile>
@@ -207,10 +222,22 @@
207222
<SubType>Designer</SubType>
208223
<Generator>MSBuild:Compile</Generator>
209224
</Page>
225+
<Page Include="Views\ScrAddressView.xaml">
226+
<SubType>Designer</SubType>
227+
<Generator>MSBuild:Compile</Generator>
228+
</Page>
229+
<Page Include="Views\ScrArbitraryDataView.xaml">
230+
<SubType>Designer</SubType>
231+
<Generator>MSBuild:Compile</Generator>
232+
</Page>
210233
<Page Include="Views\ScriptView.xaml">
211234
<SubType>Designer</SubType>
212235
<Generator>MSBuild:Compile</Generator>
213236
</Page>
237+
<Page Include="Views\ScrMultiSigView.xaml">
238+
<SubType>Designer</SubType>
239+
<Generator>MSBuild:Compile</Generator>
240+
</Page>
214241
<Page Include="Views\TransactionEditView.xaml">
215242
<SubType>Designer</SubType>
216243
<Generator>MSBuild:Compile</Generator>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Bitcoin Transaction Tool
2+
// Copyright (c) 2017 Coding Enthusiast
3+
// Distributed under the MIT software license, see the accompanying
4+
// file LICENCE or http://www.opensource.org/licenses/mit-license.php.
5+
6+
using BitcoinTransactionTool.Backend.Encoders;
7+
using BitcoinTransactionTool.Backend.MVVM;
8+
using System;
9+
10+
namespace BitcoinTransactionTool.Models
11+
{
12+
public class PublicKeyModel : ValidatableBase
13+
{
14+
private string _key;
15+
public string PubKey
16+
{
17+
get => _key;
18+
set
19+
{
20+
if (SetField(ref _key, value))
21+
{
22+
Validate();
23+
}
24+
}
25+
}
26+
27+
28+
public override void Validate()
29+
{
30+
ClearErrors(nameof(PubKey));
31+
32+
// TODO: replace this with Autarkysoft.Cryptocurrency.Keypairs.PublicKey for real validations!
33+
34+
if (string.IsNullOrEmpty(PubKey))
35+
{
36+
AddError(nameof(PubKey), "PubKey can not be empty.");
37+
}
38+
else if (!Base16.IsValid(PubKey))
39+
{
40+
AddError(nameof(PubKey), "PubKey input is not a base-16 encoded string.");
41+
}
42+
else
43+
{
44+
byte[] ba = Base16.ToByteArray(PubKey);
45+
if (ba.Length != 33 && ba.Length != 65)
46+
{
47+
AddError(nameof(PubKey), "PubKey input has invalid length.");
48+
}
49+
else if (ba.Length == 33 && ba[0] != 0x02 && ba[0] != 0x03)
50+
{
51+
AddError(nameof(PubKey), "Compressed PubKey needs to start with 0x02 or 0x03.");
52+
}
53+
else if (ba.Length == 65 && ba[0] != 0x04)
54+
{
55+
AddError(nameof(PubKey), "Uncompressed PubKey needs to start with 0x04.");
56+
}
57+
}
58+
}
59+
}
60+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Bitcoin Transaction Tool
2+
// Copyright (c) 2017 Coding Enthusiast
3+
// Distributed under the MIT software license, see the accompanying
4+
// file LICENCE or http://www.opensource.org/licenses/mit-license.php.
5+
6+
using BitcoinTransactionTool.Backend.Blockchain.Scripts;
7+
using BitcoinTransactionTool.Backend.Blockchain.Scripts.Operations;
8+
using System;
9+
10+
namespace BitcoinTransactionTool.Services
11+
{
12+
public class OperationConverter
13+
{
14+
// A Fake reader used only for the coversion of OP to IOperation
15+
private class ScriptReader : Script
16+
{
17+
public ScriptReader()
18+
{
19+
IsWitness = false;
20+
}
21+
}
22+
23+
// two Fake ops only used for returning an IOperation, not to be used for anything else.
24+
private class ElseOp : IOperation
25+
{
26+
public OP OpValue => OP.ELSE;
27+
public bool Run(IOpData opData, out string error) => throw new NotImplementedException();
28+
}
29+
private class EndIfOp : IOperation
30+
{
31+
public OP OpValue => OP.EndIf;
32+
public bool Run(IOpData opData, out string error) => throw new NotImplementedException();
33+
}
34+
35+
private readonly ScriptReader reader = new ScriptReader();
36+
37+
public IOperation ConvertToOperation(OP op)
38+
{
39+
switch (op)
40+
{
41+
case OP.IF:
42+
return new IFOp();
43+
case OP.NotIf:
44+
return new NotIfOp();
45+
case OP.ELSE:
46+
return new ElseOp();
47+
case OP.EndIf:
48+
return new EndIfOp();
49+
}
50+
51+
byte[] data = new byte[2] { 1, (byte)op };
52+
int offset = 0;
53+
if (reader.TryDeserialize(data, ref offset, out string error))
54+
{
55+
return reader.OperationList[0];
56+
}
57+
else
58+
{
59+
throw new ArgumentException($"An error occured while trying to convert: {error}");
60+
}
61+
}
62+
}
63+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Bitcoin Transaction Tool
2+
// Copyright (c) 2017 Coding Enthusiast
3+
// Distributed under the MIT software license, see the accompanying
4+
// file LICENCE or http://www.opensource.org/licenses/mit-license.php.
5+
6+
using BitcoinTransactionTool.Backend;
7+
using BitcoinTransactionTool.Backend.Blockchain.Scripts;
8+
using BitcoinTransactionTool.Backend.Blockchain.Scripts.Operations;
9+
using BitcoinTransactionTool.Backend.Encoders;
10+
11+
namespace BitcoinTransactionTool.Services
12+
{
13+
public class ScriptReader
14+
{
15+
private class Helper : Script
16+
{
17+
public Helper()
18+
{
19+
IsWitness = false;
20+
}
21+
}
22+
23+
public Response<IOperation[]> Read(string hex)
24+
{
25+
Response<IOperation[]> resp = new Response<IOperation[]>();
26+
27+
if (!Base16.IsValid(hex))
28+
{
29+
resp.Errors.Add("Invalid base-16 string.");
30+
}
31+
else
32+
{
33+
byte[] data = Base16.ToByteArray(hex);
34+
int offset = 0;
35+
CompactInt len = new CompactInt(data.Length);
36+
data = len.ToByteArray().ConcatFast(data);
37+
38+
Script scr = new Helper();
39+
if (scr.TryDeserialize(data, ref offset, out string error))
40+
{
41+
resp.Result = scr.OperationList;
42+
}
43+
else
44+
{
45+
resp.Errors.Add(error);
46+
}
47+
}
48+
49+
return resp;
50+
}
51+
}
52+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Bitcoin Transaction Tool
2+
// Copyright (c) 2017 Coding Enthusiast
3+
// Distributed under the MIT software license, see the accompanying
4+
// file LICENCE or http://www.opensource.org/licenses/mit-license.php.
5+
6+
using BitcoinTransactionTool.Backend;
7+
using BitcoinTransactionTool.Backend.Blockchain.Scripts;
8+
using BitcoinTransactionTool.Backend.Blockchain.Scripts.Operations;
9+
using System.Collections.Generic;
10+
using System.Text;
11+
12+
namespace BitcoinTransactionTool.Services
13+
{
14+
public class ScriptToStringConverter
15+
{
16+
private readonly StringBuilder sb = new StringBuilder();
17+
18+
private string OpValueToString(OP op)
19+
{
20+
return $"OP_{op.ToString().Replace("_", string.Empty)} ";
21+
}
22+
23+
private void Convert(IOperation op)
24+
{
25+
if (op is PushDataOp push)
26+
{
27+
// for OP_numbers data is null for the rest ToByteArray() contains the length
28+
if (push.data is null)
29+
{
30+
sb.Append(OpValueToString(op.OpValue));
31+
}
32+
else
33+
{
34+
sb.Append($"<{((PushDataOp)op).data.ToBase16()}> ");
35+
}
36+
}
37+
else if (op is ReturnOp ret)
38+
{
39+
if (ret.Data.Length == 1)
40+
{
41+
sb.Append(OpValueToString(op.OpValue));
42+
}
43+
else
44+
{
45+
sb.Append($"{OpValueToString(op.OpValue).TrimEnd(' ')}<{ret.Data.ToBase16()}> ");
46+
}
47+
}
48+
else if (op is IfElseOp conditional)
49+
{
50+
sb.Append(OpValueToString(op.OpValue));
51+
if (conditional.mainOps is null)
52+
{
53+
return; // This happens when the buttons are used to create an OP_IF
54+
}
55+
foreach (var main in conditional.mainOps)
56+
{
57+
Convert(main);
58+
}
59+
if (!(conditional.elseOps is null))
60+
{
61+
sb.Append(OpValueToString(OP.ELSE));
62+
foreach (var branch in conditional.elseOps)
63+
{
64+
Convert(branch);
65+
}
66+
}
67+
sb.Append(OpValueToString(OP.EndIf));
68+
}
69+
else
70+
{
71+
sb.Append(OpValueToString(op.OpValue));
72+
}
73+
}
74+
75+
public string GetString(IEnumerable<IOperation> opList)
76+
{
77+
sb.Clear();
78+
79+
foreach (var op in opList)
80+
{
81+
Convert(op);
82+
}
83+
84+
return sb.ToString();
85+
}
86+
87+
public string GetHex(IEnumerable<IOperation> opList)
88+
{
89+
sb.Clear();
90+
91+
foreach (var op in opList)
92+
{
93+
if (op is PushDataOp push)
94+
{
95+
sb.Append(push.ToByteArray().ToBase16());
96+
}
97+
else if (op is ReturnOp ret)
98+
{
99+
sb.Append(ret.ToByteArray().ToBase16());
100+
}
101+
else if (op is IfElseOp conditional)
102+
{
103+
if (conditional.mainOps is null)
104+
{
105+
sb.Append($"{(byte)op.OpValue:x2}");
106+
}
107+
else
108+
{
109+
sb.Append(conditional.ToByteArray().ToBase16());
110+
}
111+
}
112+
else
113+
{
114+
sb.Append($"{(byte)op.OpValue:x2}");
115+
}
116+
}
117+
118+
return sb.ToString();
119+
}
120+
}
121+
}

0 commit comments

Comments
 (0)