Skip to content

Commit

Permalink
Fix : MultiSig with invalid pubkey should be a valid multisig
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolasDorier committed Oct 24, 2014
1 parent dccb690 commit 30c4a36
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 21 deletions.
12 changes: 12 additions & 0 deletions NBitcoin.Tests/script_tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,18 @@ public void CanCompressScript2()
Assert.Equal(script.ToString(), new Script(compressed, true).ToString());
}

[Fact]
[Trait("UnitTest", "UnitTest")]
public void PayToMultiSigTemplateShouldAcceptNonKeyParameters()
{
var tx = new Transaction("0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000");
var redeemScript = new PayToScriptHashTemplate().ExtractScriptSigParameters(tx.Inputs[1].ScriptSig).RedeemScript;
var result = new PayToMultiSigTemplate().ExtractScriptPubKeyParameters(redeemScript);
Assert.Equal(2, result.PubKeys.Length);
Assert.Equal(2, result.SignatureCount);
Assert.Equal(1, result.InvalidPubKeys.Length);
}

[Fact]
[Trait("UnitTest", "UnitTest")]
public void PayToPubkeyHashTemplateDoNotCrashOnInvalidSig()
Expand Down
57 changes: 36 additions & 21 deletions NBitcoin/StandardScriptTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ public PubKey[] PubKeys
get;
set;
}

public byte[][] InvalidPubKeys
{
get;
set;
}
}
public class PayToMultiSigTemplate : ScriptTemplate
{
Expand Down Expand Up @@ -120,46 +126,55 @@ protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPu
var sigCount = ops[0];
if(!sigCount.IsSmallUInt)
return false;

var expectedKeyCount = 0;
var keyCountIndex = 0;
for(int i = 1 ; i < ops.Length ; i++)
var pubKeyCount = ops[ops.Length - 2];
if(!pubKeyCount.IsSmallUInt)
return false;
var keyCount = (uint)pubKeyCount.GetValue();
if(1 + keyCount + 1 + 1 != ops.Length)
return false;
for(int i = 1 ; i < keyCount + 1; i++)
{
if(ops[i].PushData == null)
return false;
if(!PubKey.IsValidSize(ops[i].PushData.Length))
{
keyCountIndex = i;
break;
}
expectedKeyCount++;
}
if(!ops[keyCountIndex].IsSmallUInt)
return false;
if(ops[keyCountIndex].GetValue() != expectedKeyCount)
return false;
return ops[keyCountIndex + 1].Code == OpcodeType.OP_CHECKMULTISIG &&
keyCountIndex + 1 == ops.Length - 1;
return ops[ops.Length - 1].Code == OpcodeType.OP_CHECKMULTISIG;
}

public PayToMultiSigTemplateParameters ExtractScriptPubKeyParameters(Script scriptPubKey)
{
if(!FastCheckScriptPubKey(scriptPubKey))
return null;
var ops = scriptPubKey.ToOps().ToArray();
if(!CheckScriptPubKeyCore(scriptPubKey, ops))
return null;
var sigCount = (byte)ops[0].PushData[0];

var sigCount = (int)ops[0].GetValue();
var keyCount = (int)ops[ops.Length - 2].GetValue();

List<PubKey> keys = new List<PubKey>();
for(int i = 1 ; i < ops.Length ; i++)
List<byte[]> invalidKeys = new List<byte[]>();
for(int i = 1 ; i < keyCount + 1; i++)
{
if(!PubKey.IsValidSize(ops[i].PushData.Length))
break;
keys.Add(new PubKey(ops[i].PushData));
invalidKeys.Add(ops[i].PushData);
else
{
try
{
keys.Add(new PubKey(ops[i].PushData));
}
catch(FormatException)
{
invalidKeys.Add(ops[i].PushData);
}
}
}

return new PayToMultiSigTemplateParameters()
{
SignatureCount = sigCount,
PubKeys = keys.ToArray()
PubKeys = keys.ToArray(),
InvalidPubKeys = invalidKeys.ToArray()
};
}

Expand Down

0 comments on commit 30c4a36

Please sign in to comment.