Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sender from signers #1752

Merged
merged 30 commits into from
Jul 11, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3702164
Sender from signers
shargon Jul 7, 2020
576973b
Remove co-
shargon Jul 7, 2020
a618ebf
Merge branch 'master' into sender-from-signers
shargon Jul 8, 2020
4d70d15
Move signers outside attributes
shargon Jul 8, 2020
d775492
Fix UT and remove Signers class
shargon Jul 9, 2020
fc6a3fa
Fix UT
shargon Jul 9, 2020
ec0262e
Add FeeOnly scope
shargon Jul 9, 2020
09860a4
Remove orderBy
shargon Jul 9, 2020
f4a6205
Merge branch 'master' into sender-from-signers
erikzhang Jul 10, 2020
a726699
Remove _signersCache
erikzhang Jul 10, 2020
67dc7e3
Fix Signers
erikzhang Jul 10, 2020
881fb88
Fix WitnessScope
erikzhang Jul 10, 2020
e55dfee
Fix Sender
erikzhang Jul 10, 2020
e28cd1d
Update TransactionAttributeType.cs
erikzhang Jul 10, 2020
eb7e302
Update Wallet.cs
erikzhang Jul 10, 2020
c536c30
Fix Wallet
erikzhang Jul 10, 2020
0f5db32
Rename
erikzhang Jul 10, 2020
8a8b837
Update Wallet.cs
erikzhang Jul 10, 2020
ffc55fe
Update Wallet.cs
erikzhang Jul 10, 2020
e018eb6
Partial UT fix
shargon Jul 10, 2020
59f934d
More UT fixes
shargon Jul 10, 2020
eea80a2
Fix Sender's WitnessScope
erikzhang Jul 10, 2020
cf8ffba
Fix Wallet
erikzhang Jul 10, 2020
6b4a56b
Fix UT
shargon Jul 10, 2020
a2ae4a2
Explicit FeeOnly for DeployNativeContracts
shargon Jul 10, 2020
f09a8a5
Same order as serialization
shargon Jul 10, 2020
4870875
Test FeeOnly
shargon Jul 10, 2020
abc7999
Merge branch 'master' into sender-from-signers
shargon Jul 10, 2020
cb8f978
dotnet format
shargon Jul 10, 2020
be47d0d
format
erikzhang Jul 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ private static Transaction DeployNativeContracts()
{
Version = 0,
Script = script,
Sender = (new[] { (byte)OpCode.PUSH1 }).ToScriptHash(),
SystemFee = 0,
Signers = new[] { new Signer() { Account = (new[] { (byte)OpCode.PUSH1 }).ToScriptHash() } },
Attributes = Array.Empty<TransactionAttribute>(),
Witnesses = new[]
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Neo.Network.P2P.Payloads
{
public class Cosigner : TransactionAttribute
public class Signer : ISerializable
{
// This limits maximum number of AllowedContracts or AllowedGroups here
private const int MaxSubitems = 16;
Expand All @@ -16,16 +16,13 @@ public class Cosigner : TransactionAttribute
public UInt160[] AllowedContracts;
public ECPoint[] AllowedGroups;

public override TransactionAttributeType Type => TransactionAttributeType.Cosigner;
public override bool AllowMultiple => true;

public override int Size => base.Size +
public int Size =>
/*Account*/ UInt160.Length +
/*Scopes*/ sizeof(WitnessScope) +
/*AllowedContracts*/ (Scopes.HasFlag(WitnessScope.CustomContracts) ? AllowedContracts.GetVarSize() : 0) +
/*AllowedGroups*/ (Scopes.HasFlag(WitnessScope.CustomGroups) ? AllowedGroups.GetVarSize() : 0);

protected override void DeserializeWithoutType(BinaryReader reader)
public void Deserialize(BinaryReader reader)
{
Account = reader.ReadSerializable<UInt160>();
Scopes = (WitnessScope)reader.ReadByte();
Expand All @@ -37,7 +34,7 @@ protected override void DeserializeWithoutType(BinaryReader reader)
: new ECPoint[0];
}

protected override void SerializeWithoutType(BinaryWriter writer)
public void Serialize(BinaryWriter writer)
{
writer.Write(Account);
writer.Write((byte)Scopes);
Expand All @@ -47,9 +44,9 @@ protected override void SerializeWithoutType(BinaryWriter writer)
writer.Write(AllowedGroups);
}

public override JObject ToJson()
public JObject ToJson()
{
JObject json = base.ToJson();
var json = new JObject();
json["account"] = Account.ToString();
json["scopes"] = Scopes;
if (Scopes.HasFlag(WitnessScope.CustomContracts))
Expand Down
56 changes: 33 additions & 23 deletions src/neo/Network/P2P/Payloads/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,48 @@ public class Transaction : IEquatable<Transaction>, IInventory, IInteroperable

private byte version;
private uint nonce;
private UInt160 sender;
private long sysfee;
private long netfee;
private uint validUntilBlock;
private TransactionAttribute[] attributes;
private byte[] script;
private Witness[] witnesses;
private Signer[] _signers;
private Dictionary<UInt160, Signer> _signersCache;

public const int HeaderSize =
sizeof(byte) + //Version
sizeof(uint) + //Nonce
20 + //Sender
sizeof(long) + //SystemFee
sizeof(long) + //NetworkFee
sizeof(uint); //ValidUntilBlock

public TransactionAttribute[] Attributes
{
get => attributes;
set { attributes = value; _cosigners = null; _hash = null; _size = 0; }
set { attributes = value; _hash = null; _size = 0; }
}

private Dictionary<UInt160, Cosigner> _cosigners;
public IReadOnlyDictionary<UInt160, Cosigner> Cosigners => _cosigners ??= attributes.OfType<Cosigner>().ToDictionary(p => p.Account);
public Signer[] Signers
{
get => _signers;
set
{
var cache = value.ToDictionary(u => u.Account);
if (cache.Count != value.Length)
throw new FormatException("Signers accounts must be unique");

_signersCache = cache;
_signers = value;
_hash = null;
_size = 0;
}
}

/// <summary>
/// Correspond with the first entry of Signers
/// </summary>
public UInt160 Sender => _signers.Length > 0 ? _signers[0].Account : UInt160.Zero;

/// <summary>
/// The <c>NetworkFee</c> for the transaction divided by its <c>Size</c>.
Expand Down Expand Up @@ -95,12 +113,6 @@ public byte[] Script
set { script = value; _hash = null; _size = 0; }
}

public UInt160 Sender
{
get => sender;
set { sender = value; _hash = null; }
}

private int _size;
public int Size
{
Expand All @@ -110,6 +122,7 @@ public int Size
{
_size = HeaderSize +
Attributes.GetVarSize() + // Attributes
Signers.GetVarSize() + // Signers
Script.GetVarSize() + // Script
Witnesses.GetVarSize(); // Witnesses
}
Expand Down Expand Up @@ -168,27 +181,24 @@ private static IEnumerable<TransactionAttribute> DeserializeAttributes(BinaryRea
}
}

public bool TryGetSigner(UInt160 hash, out Signer signer)
{
return _signersCache.TryGetValue(hash, out signer);
}

public void DeserializeUnsigned(BinaryReader reader)
{
Version = reader.ReadByte();
if (Version > 0) throw new FormatException();
Nonce = reader.ReadUInt32();
Sender = reader.ReadSerializable<UInt160>();
SystemFee = reader.ReadInt64();
if (SystemFee < 0) throw new FormatException();
NetworkFee = reader.ReadInt64();
if (NetworkFee < 0) throw new FormatException();
if (SystemFee + NetworkFee < SystemFee) throw new FormatException();
ValidUntilBlock = reader.ReadUInt32();
Attributes = DeserializeAttributes(reader).ToArray();
try
{
_ = Cosigners;
}
catch (ArgumentException)
{
throw new FormatException();
}
Signers = reader.ReadSerializableArray<Signer>(MaxTransactionAttributes);
Script = reader.ReadVarBytes(ushort.MaxValue);
if (Script.Length == 0) throw new FormatException();
}
Expand Down Expand Up @@ -217,8 +227,7 @@ public override int GetHashCode()

public UInt160[] GetScriptHashesForVerifying(StoreView snapshot)
{
var hashes = new HashSet<UInt160>(Cosigners.Keys) { Sender };
return hashes.OrderBy(p => p).ToArray();
return _signersCache.Keys.OrderBy(p => p).ToArray();
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
}

void ISerializable.Serialize(BinaryWriter writer)
Expand All @@ -231,11 +240,11 @@ void IVerifiable.SerializeUnsigned(BinaryWriter writer)
{
writer.Write(Version);
writer.Write(Nonce);
writer.Write(Sender);
writer.Write(SystemFee);
writer.Write(NetworkFee);
writer.Write(ValidUntilBlock);
writer.Write(Attributes);
writer.Write(Signers);
writer.WriteVarBytes(Script);
}

Expand All @@ -251,6 +260,7 @@ public JObject ToJson()
json["netfee"] = NetworkFee.ToString();
json["validuntilblock"] = ValidUntilBlock;
json["attributes"] = Attributes.Select(p => p.ToJson()).ToArray();
json["signers"] = Signers.Select(p => p.ToJson()).ToArray();
json["script"] = Convert.ToBase64String(Script);
json["witnesses"] = Witnesses.Select(p => p.ToJson()).ToArray();
return json;
Expand Down
4 changes: 2 additions & 2 deletions src/neo/Network/P2P/Payloads/TransactionAttributeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Neo.Network.P2P.Payloads
{
public enum TransactionAttributeType : byte
{
[ReflectionCache(typeof(Cosigner))]
Cosigner = 0x01
//[ReflectionCache(typeof(Signer))]
//Signer = 0x01
}
}
14 changes: 7 additions & 7 deletions src/neo/SmartContract/ApplicationEngine.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,23 +104,23 @@ internal bool CheckWitnessInternal(UInt160 hash)
{
if (ScriptContainer is Transaction tx)
{
if (!tx.Cosigners.TryGetValue(hash, out Cosigner cosigner)) return false;
if (cosigner.Scopes == WitnessScope.Global) return true;
if (cosigner.Scopes.HasFlag(WitnessScope.CalledByEntry))
if (!tx.TryGetSigner(hash, out Signer signer)) return false;
if (signer.Scopes == WitnessScope.Global) return true;
if (signer.Scopes.HasFlag(WitnessScope.CalledByEntry))
{
if (CallingScriptHash == EntryScriptHash)
return true;
}
if (cosigner.Scopes.HasFlag(WitnessScope.CustomContracts))
if (signer.Scopes.HasFlag(WitnessScope.CustomContracts))
{
if (cosigner.AllowedContracts.Contains(CurrentScriptHash))
if (signer.AllowedContracts.Contains(CurrentScriptHash))
return true;
}
if (cosigner.Scopes.HasFlag(WitnessScope.CustomGroups))
if (signer.Scopes.HasFlag(WitnessScope.CustomGroups))
{
var contract = Snapshot.Contracts[CallingScriptHash];
// check if current group is the required one
if (contract.Manifest.Groups.Select(p => p.PubKey).Intersect(cosigner.AllowedGroups).Any())
if (contract.Manifest.Groups.Select(p => p.PubKey).Intersect(signer.AllowedGroups).Any())
return true;
}
return false;
Expand Down
38 changes: 20 additions & 18 deletions src/neo/Wallets/Wallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Numerics;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Policy;
using System.Text;
using static Neo.Wallets.Helper;
using ECPoint = Neo.Cryptography.ECC.ECPoint;
Expand Down Expand Up @@ -235,7 +236,7 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null
}
using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot())
{
HashSet<UInt160> cosignerList = new HashSet<UInt160>();
HashSet<UInt160> signersList = new HashSet<UInt160>();
byte[] script;
List<(UInt160 Account, BigInteger Value)> balances_gas = null;
using (ScriptBuilder sb = new ScriptBuilder())
Expand All @@ -262,7 +263,7 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null
{
balances = balances.OrderBy(p => p.Value).ToList();
var balances_used = FindPayingAccounts(balances, output.Value.Value);
cosignerList.UnionWith(balances_used.Select(p => p.Account));
signersList.UnionWith(balances_used.Select(p => p.Account));
foreach (var (account, value) in balances_used)
{
sb.EmitAppCall(output.AssetId, "transfer", account, output.ScriptHash, value);
Expand All @@ -277,39 +278,40 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null
if (balances_gas is null)
balances_gas = accounts.Select(p => (Account: p, Value: NativeContract.GAS.BalanceOf(snapshot, p))).Where(p => p.Value.Sign > 0).ToList();

var cosigners = cosignerList.Select(p =>
new Cosigner()
{
// default access for transfers should be valid only for first invocation
Scopes = WitnessScope.CalledByEntry,
Account = new UInt160(p.ToArray())
}).ToArray();
var signers = signersList.Select(p =>
new Signer()
{
// default access for transfers should be valid only for first invocation
Scopes = WitnessScope.CalledByEntry,
Account = new UInt160(p.ToArray())
}).ToArray();

return MakeTransaction(snapshot, script, cosigners, balances_gas);
return MakeTransaction(snapshot, script, signers, null, balances_gas);
}
}

public Transaction MakeTransaction(byte[] script, UInt160 sender = null, TransactionAttribute[] attributes = null)
public Transaction MakeTransaction(byte[] script, Signer[] signers = null, TransactionAttribute[] attributes = null)
{
var sender = signers?.Length > 0 ? signers[0].Account : UInt160.Zero;
UInt160[] accounts;
if (sender is null)
if (sender == UInt160.Zero)
{
accounts = GetAccounts().Where(p => !p.Lock && !p.WatchOnly).Select(p => p.ScriptHash).ToArray();
}
else
{
if (!Contains(sender))
throw new ArgumentException($"The address {sender.ToString()} was not found in the wallet");
throw new ArgumentException($"The address {sender} was not found in the wallet");
accounts = new[] { sender };
}
using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot())
{
var balances_gas = accounts.Select(p => (Account: p, Value: NativeContract.GAS.BalanceOf(snapshot, p))).Where(p => p.Value.Sign > 0).ToList();
return MakeTransaction(snapshot, script, attributes ?? new TransactionAttribute[0], balances_gas);
return MakeTransaction(snapshot, script, signers, attributes ?? Array.Empty<TransactionAttribute>(), balances_gas);
}
}

private Transaction MakeTransaction(StoreView snapshot, byte[] script, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas)
private Transaction MakeTransaction(StoreView snapshot, byte[] script, Signer[] signers, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas)
shargon marked this conversation as resolved.
Show resolved Hide resolved
{
Random rand = new Random();
foreach (var (account, value) in balances_gas)
Expand All @@ -319,9 +321,9 @@ private Transaction MakeTransaction(StoreView snapshot, byte[] script, Transacti
Version = 0,
Nonce = (uint)rand.Next(),
Script = script,
Sender = account,
ValidUntilBlock = snapshot.Height + Transaction.MaxValidUntilBlockIncrement,
Attributes = attributes,
Signers = signers ?? Array.Empty<Signer>(),
Attributes = attributes ?? Array.Empty<TransactionAttribute>(),
};

// will try to execute 'transfer' script to check if it works
Expand All @@ -335,7 +337,7 @@ private Transaction MakeTransaction(StoreView snapshot, byte[] script, Transacti
UInt160[] hashes = tx.GetScriptHashesForVerifying(snapshot);

// base size for transaction: includes const_header + attributes + script + hashes
int size = Transaction.HeaderSize + tx.Attributes.GetVarSize() + script.GetVarSize() + IO.Helper.GetVarSize(hashes.Length);
int size = Transaction.HeaderSize + tx.Attributes.GetVarSize() + tx.Signers.GetVarSize() + script.GetVarSize() + IO.Helper.GetVarSize(hashes.Length);

foreach (UInt160 hash in hashes)
{
Expand Down
4 changes: 2 additions & 2 deletions tests/neo.UnitTests/Consensus/UT_ConsensusContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ private Transaction CreateTransactionWithSize(int v)
var tx = new Transaction()
{
Attributes = System.Array.Empty<TransactionAttribute>(),
Signers = System.Array.Empty<Signer>(),
NetworkFee = 0,
Nonce = (uint)Environment.TickCount,
Script = new byte[0],
Sender = UInt160.Zero,
SystemFee = 0,
ValidUntilBlock = (uint)r.Next(),
Version = 0,
Expand All @@ -145,10 +145,10 @@ private Transaction CreateTransactionWithSytemFee(long fee)
var tx = new Transaction()
{
Attributes = System.Array.Empty<TransactionAttribute>(),
Signers = System.Array.Empty<Signer>(),
NetworkFee = 0,
Nonce = (uint)Environment.TickCount,
Script = new byte[0],
Sender = UInt160.Zero,
SystemFee = fee,
ValidUntilBlock = int.MaxValue,
Version = 0,
Expand Down
2 changes: 1 addition & 1 deletion tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ public void TestTest()
Transaction tx = new Transaction
{
Script = TestUtils.GetByteArray(32, 0x42),
Sender = UInt160.Zero,
SystemFee = 4200000000,
Signers = Array.Empty<Signer>(),
Attributes = Array.Empty<TransactionAttribute>(),
Witnesses = new[]
{
Expand Down
5 changes: 2 additions & 3 deletions tests/neo.UnitTests/IO/Caching/UT_RelayCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,15 @@ public void TestGetKeyForItem()
{
Version = 0,
Nonce = 1,
Sender = UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"),
SystemFee = 0,
NetworkFee = 0,
ValidUntilBlock = 100,
Attributes = Array.Empty<TransactionAttribute>(),
Signers = Array.Empty<Signer>(),
Script = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 },
Witnesses = new Witness[0]
Witnesses = Array.Empty<Witness>()
};
relayCache.Add(tx);

relayCache.Contains(tx).Should().BeTrue();
relayCache.TryGet(tx.Hash, out IInventory tmp).Should().BeTrue();
(tmp is Transaction).Should().BeTrue();
Expand Down
Loading