Skip to content

Commit

Permalink
Added SignerBuilder and started WitnessRuleBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
cschuchardt88 committed Sep 4, 2024
1 parent d421c59 commit a4c71f3
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 48 deletions.
55 changes: 55 additions & 0 deletions src/Neo/Builders/SignerBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// SignerBuilder.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo.Cryptography.ECC;
using Neo.Network.P2P.Payloads;

namespace Neo.Builders
{
public sealed class SignerBuilder
{
private readonly Signer _signer = new Signer()
{
AllowedContracts = [],
AllowedGroups = [],
Rules = [],
Scopes = WitnessScope.None,
};

private SignerBuilder(UInt160 scriptHash)
{
_signer.Account = scriptHash;
}

public static SignerBuilder Create(UInt160 scriptHash)
{
return new SignerBuilder(scriptHash);
}

public SignerBuilder AllowContract(UInt160 contractHash)
{
_signer.AllowedContracts = [.. _signer.AllowedContracts, contractHash];
return this;
}

public SignerBuilder AllowGroup(ECPoint publicKey)
{
_signer.AllowedGroups = [.. _signer.AllowedGroups, publicKey];
return this;
}

public SignerBuilder AddWitnessScope(WitnessScope scope)
{
_signer.Scopes |= scope;
return this;
}
}
}
65 changes: 30 additions & 35 deletions src/Neo/Builders/TransactionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ namespace Neo.Builders
public sealed class TransactionBuilder
{

private byte _version = 0;
private uint _nonce = (uint)new Random().Next();
private uint _systemFee = 0;
private uint _networkFee = 0;
private uint _validUntilBlock = 0;
private byte[] _script = [];
private TransactionAttribute[] _attributes = [];
private Signer[] _signers = [];
private Witness[] _witnesses = [];
private readonly Transaction _tx = new()
{
Script = new[] { (byte)OpCode.RET },
Attributes = [],
Signers = [],
Witnesses = [],
};

private TransactionBuilder() { }

Expand All @@ -37,72 +35,69 @@ public static TransactionBuilder CreateEmpty()

public TransactionBuilder Version(byte version)
{
_version = version;
_tx.Version = version;
return this;
}

public TransactionBuilder Nonce(uint nonce)
{
_nonce = nonce;
_tx.Nonce = nonce;
return this;
}

public TransactionBuilder SystemFee(uint systemFee)
{
_systemFee = systemFee;
_tx.SystemFee = systemFee;
return this;
}

public TransactionBuilder NetworkFee(uint networkFee)
{
_networkFee = networkFee;
_tx.NetworkFee = networkFee;
return this;
}

public TransactionBuilder ValidUntil(uint blockIndex)
{
_validUntilBlock = blockIndex;
_tx.ValidUntilBlock = blockIndex;
return this;
}

public TransactionBuilder AttachSystem(Action<ScriptBuilder> scriptBuilder)
public TransactionBuilder AttachSystem(Action<ScriptBuilder> action)
{
var sb = new ScriptBuilder();
scriptBuilder(sb);
_script = sb.ToArray();
action(sb);
_tx.Script = sb.ToArray();
return this;
}

public TransactionBuilder AddAttributes(Action<TransactionAttributesBuilder> transactionAttributeBuilder)
public TransactionBuilder AddAttributes(Action<TransactionAttributesBuilder> action)
{
var ab = TransactionAttributesBuilder.CreateEmpty();
transactionAttributeBuilder(ab);
_attributes = ab.Build();
action(ab);
_tx.Attributes = ab.Build();
return this;
}

public TransactionBuilder AddWitness(Action<WitnessBuilder> action)
{
var wb = WitnessBuilder.CreateEmpty();
action(wb);
_tx.Witnesses = [.. _tx.Witnesses, wb.Build()];
return this;
}

public TransactionBuilder AddWitness(Action<WitnessBuilder> witnessBuilder)
public TransactionBuilder AddWitness(Action<WitnessBuilder, Transaction> action)
{
var wb = WitnessBuilder.CreateEmpty();
witnessBuilder(wb);
_witnesses = [.. _witnesses, wb.Build()];
action(wb, _tx);
_tx.Witnesses = [.. _tx.Witnesses, wb.Build()];
return this;
}

public Transaction Build()
{
return new Transaction()
{
Version = _version,
Nonce = _nonce,
SystemFee = _systemFee,
NetworkFee = _networkFee,
ValidUntilBlock = _validUntilBlock,
Script = _script,
Attributes = _attributes,
Signers = _signers,
Witnesses = _witnesses
};
return _tx;
}
}
}
22 changes: 9 additions & 13 deletions src/Neo/Builders/WitnessBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo.Cryptography.ECC;
using Neo.Network.P2P.Payloads;
using Neo.SmartContract;
using Neo.VM;
using System;

Expand All @@ -37,25 +35,23 @@ public WitnessBuilder AddInvocation(Action<ScriptBuilder> scriptBuilder)
return this;
}

public WitnessBuilder AddSigner(Action<ScriptBuilder> scriptBuilder)
public WitnessBuilder AddInvocation(byte[] bytes)
{
var sb = new ScriptBuilder();
scriptBuilder(sb);
_verificationScript = sb.ToArray();
_invocationScript = bytes;
return this;
}

public WitnessBuilder AddSigner(Action<Contract> contract)
public WitnessBuilder AddVerification(Action<ScriptBuilder> scriptBuilder)
{
var c = new Contract();
contract(c);
_verificationScript = c.Script;
var sb = new ScriptBuilder();
scriptBuilder(sb);
_verificationScript = sb.ToArray();
return this;
}

public WitnessBuilder AddSigner(ECPoint publicKey)
public WitnessBuilder AddVerification(byte[] bytes)
{
_verificationScript = Contract.CreateSignatureRedeemScript(publicKey);
_verificationScript = bytes;
return this;
}

Expand All @@ -64,7 +60,7 @@ public Witness Build()
return new Witness()
{
InvocationScript = _invocationScript,
VerificationScript = _verificationScript
VerificationScript = _verificationScript,
};
}
}
Expand Down
30 changes: 30 additions & 0 deletions src/Neo/Builders/WitnessRuleBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// WitnessRuleBuilder.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo.Network.P2P.Payloads;

namespace Neo.Builders
{
public sealed class WitnessRuleBuilder
{
private readonly WitnessRule _rule = new();

private WitnessRuleBuilder(WitnessRuleAction action)
{
_rule.Action = action;
}

public static WitnessRuleBuilder Create(WitnessRuleAction action)
{
return new WitnessRuleBuilder(action);
}
}
}
67 changes: 67 additions & 0 deletions tests/Neo.UnitTests/Builders/UT_TransactionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.Builders;
using Neo.Network.P2P.Payloads;
using Neo.VM;
using Neo.Wallets;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -81,5 +84,69 @@ public void TestValidUntilBlock()
Assert.AreEqual(expectedValidUntilBlock, tx.ValidUntilBlock);
Assert.IsNotNull(tx.Hash);
}

[TestMethod]
public void TestAttachScript()
{
byte[] expectedScript = [(byte)OpCode.NOP];
var tx = TransactionBuilder.CreateEmpty()
.AttachSystem(sb => sb.Emit(OpCode.NOP))
.Build();

CollectionAssert.AreEqual(expectedScript, tx.Script.ToArray());
Assert.IsNotNull(tx.Hash);
}

[TestMethod]
public void TestTransactionAttributes()
{
var tx = TransactionBuilder.CreateEmpty()
.AddAttributes(ab => ab.AddHighPriority())
.Build();

Assert.AreEqual(1, tx.Attributes.Length);
Assert.IsInstanceOfType<HighPriorityAttribute>(tx.Attributes[0]);
Assert.IsNotNull(tx.Hash);
}

[TestMethod]
public void TestWitness()
{
var tx = TransactionBuilder.CreateEmpty()
.AddWitness(wb =>
{
// Contract signature
wb.AddInvocation([]);
wb.AddVerification([]);
})
.Build();

Assert.AreEqual(1, tx.Witnesses.Length);
Assert.AreEqual(0, tx.Witnesses[0].InvocationScript.Length);
Assert.AreEqual(0, tx.Witnesses[0].VerificationScript.Length);
Assert.IsNotNull(tx.Hash);
}

[TestMethod]
public void TestWitnessWithTransactionParameter()
{
var tx = TransactionBuilder.CreateEmpty()
.AddWitness((wb, tx) =>
{
// Checks to make sure the transaction is hash able
// NOTE: transaction can be used for signing here
Assert.IsNotNull(tx.Hash);
})
.Build();
}

[TestMethod]
public void TestEmptyTransaction()
{
var tx = TransactionBuilder.CreateEmpty()
.Build();

Assert.IsNotNull(tx.Hash);
}
}
}

0 comments on commit a4c71f3

Please sign in to comment.