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

update #5

Merged
merged 16 commits into from
Dec 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 9 additions & 9 deletions src/neo/Consensus/ConsensusContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class ConsensusContext : IDisposable, ISerializable
/// <summary>
/// Key for saving consensus state.
/// </summary>
private static readonly byte[] ConsensusStateKey = { 0xf4 };
private const byte ConsensusStatePrefix = 0xf4;

public Block Block;
public byte ViewNumber;
Expand All @@ -42,11 +42,11 @@ internal class ConsensusContext : IDisposable, ISerializable
/// </summary>
public SendersFeeMonitor SendersFeeMonitor = new SendersFeeMonitor();

public Snapshot Snapshot { get; private set; }
public SnapshotView Snapshot { get; private set; }
private KeyPair keyPair;
private int _witnessSize;
private readonly Wallet wallet;
private readonly Store store;
private readonly IStore store;

public int F => (Validators.Length - 1) / 3;
public int M => Validators.Length - F;
Expand Down Expand Up @@ -74,7 +74,7 @@ internal class ConsensusContext : IDisposable, ISerializable

public int Size => throw new NotImplementedException();

public ConsensusContext(Wallet wallet, Store store)
public ConsensusContext(Wallet wallet, IStore store)
{
this.wallet = wallet;
this.store = store;
Expand Down Expand Up @@ -146,7 +146,7 @@ public uint GetPrimaryIndex(byte viewNumber)

public bool Load()
{
byte[] data = store.Get(ConsensusStateKey);
byte[] data = store.TryGet(ConsensusStatePrefix, null);
if (data is null || data.Length == 0) return false;
using (MemoryStream ms = new MemoryStream(data, false))
using (BinaryReader reader = new BinaryReader(ms))
Expand Down Expand Up @@ -280,9 +280,9 @@ internal void EnsureMaxBlockSize(IEnumerable<Transaction> txs)
public ConsensusPayload MakePrepareRequest()
{
var random = new Random();
byte[] buffer = new byte[sizeof(ulong)];
Span<byte> buffer = stackalloc byte[sizeof(ulong)];
random.NextBytes(buffer);
Block.ConsensusData.Nonce = BitConverter.ToUInt64(buffer, 0);
Block.ConsensusData.Nonce = BitConverter.ToUInt64(buffer);
EnsureMaxBlockSize(Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions());
Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1);

Expand Down Expand Up @@ -346,7 +346,7 @@ public void Reset(byte viewNumber)
{
PrevHash = Snapshot.CurrentBlockHash,
Index = Snapshot.Height + 1,
NextConsensus = Blockchain.GetConsensusAddress(NativeContract.NEO.GetValidators(Snapshot).ToArray())
NextConsensus = Blockchain.GetConsensusAddress(NativeContract.NEO.GetValidators(Snapshot))
};
var pv = Validators;
Validators = NativeContract.NEO.GetNextBlockValidators(Snapshot);
Expand Down Expand Up @@ -409,7 +409,7 @@ public void Reset(byte viewNumber)

public void Save()
{
store.PutSync(ConsensusStateKey, this.ToArray());
store.PutSync(ConsensusStatePrefix, null, this.ToArray());
}

public void Serialize(BinaryWriter writer)
Expand Down
2 changes: 2 additions & 0 deletions src/neo/Consensus/ConsensusMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public abstract class ConsensusMessage : ISerializable

protected ConsensusMessage(ConsensusMessageType type)
{
if (!Enum.IsDefined(typeof(ConsensusMessageType), type))
throw new ArgumentOutOfRangeException(nameof(type));
this.Type = type;
}

Expand Down
12 changes: 6 additions & 6 deletions src/neo/Consensus/ConsensusService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ internal class Timer { public uint Height; public byte ViewNumber; }
/// </summary>
private bool isRecovering = false;

public ConsensusService(IActorRef localNode, IActorRef taskManager, Store store, Wallet wallet)
public ConsensusService(IActorRef localNode, IActorRef taskManager, IStore store, Wallet wallet)
: this(localNode, taskManager, new ConsensusContext(wallet, store))
{
}
Expand All @@ -61,7 +61,7 @@ internal ConsensusService(IActorRef localNode, IActorRef taskManager, ConsensusC

private bool AddTransaction(Transaction tx, bool verify)
{
if (verify && !tx.Verify(context.Snapshot, context.SendersFeeMonitor.GetSenderFee(tx.Sender)))
if (verify && tx.Verify(context.Snapshot, context.SendersFeeMonitor.GetSenderFee(tx.Sender)) != RelayResultReason.Succeed)
{
Log($"Invalid transaction: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
RequestChangeView(ChangeViewReason.TxInvalid);
Expand Down Expand Up @@ -231,7 +231,7 @@ private void OnCommitReceived(ConsensusPayload payload, Commit commit)
{
existingCommitPayload = payload;
}
else if (Crypto.Default.VerifySignature(hashData, commit.Signature,
else if (Crypto.VerifySignature(hashData, commit.Signature,
context.Validators[payload.ValidatorIndex].EncodePoint(false)))
{
existingCommitPayload = payload;
Expand Down Expand Up @@ -433,7 +433,7 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m
byte[] hashData = context.EnsureHeader().GetHashData();
for (int i = 0; i < context.CommitPayloads.Length; i++)
if (context.CommitPayloads[i]?.ConsensusMessage.ViewNumber == context.ViewNumber)
if (!Crypto.Default.VerifySignature(hashData, context.CommitPayloads[i].GetDeserializedMessage<Commit>().Signature, context.Validators[i].EncodePoint(false)))
if (!Crypto.VerifySignature(hashData, context.CommitPayloads[i].GetDeserializedMessage<Commit>().Signature, context.Validators[i].EncodePoint(false)))
context.CommitPayloads[i] = null;

if (context.TransactionHashes.Length == 0)
Expand Down Expand Up @@ -573,7 +573,7 @@ private void OnTimer(Timer timer)
{
var reason = ChangeViewReason.Timeout;

if (context.Block != null && context.TransactionHashes?.Count() > context.Transactions?.Count)
if (context.Block != null && context.TransactionHashes?.Length > context.Transactions?.Count)
{
reason = ChangeViewReason.TxNotFound;
}
Expand Down Expand Up @@ -601,7 +601,7 @@ protected override void PostStop()
base.PostStop();
}

public static Props Props(IActorRef localNode, IActorRef taskManager, Store store, Wallet wallet)
public static Props Props(IActorRef localNode, IActorRef taskManager, IStore store, Wallet wallet)
{
return Akka.Actor.Props.Create(() => new ConsensusService(localNode, taskManager, store, wallet)).WithMailbox("consensus-service-mailbox");
}
Expand Down
35 changes: 29 additions & 6 deletions src/neo/Cryptography/Base58.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,37 @@
using System.Linq;
using System.Numerics;
using System.Text;
using static Neo.Helper;

namespace Neo.Cryptography
{
public static class Base58
{
public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

public static byte[] Base58CheckDecode(this string input)
{
byte[] buffer = Decode(input);
if (buffer.Length < 4) throw new FormatException();
byte[] checksum = buffer.Sha256(0, buffer.Length - 4).Sha256();
if (!buffer.AsSpan(^4).SequenceEqual(checksum.AsSpan(..4)))
throw new FormatException();
var ret = buffer[..^4];
Array.Clear(buffer, 0, buffer.Length);
return ret;
}

public static string Base58CheckEncode(this ReadOnlySpan<byte> data)
{
byte[] checksum = data.Sha256().Sha256();
Span<byte> buffer = stackalloc byte[data.Length + 4];
data.CopyTo(buffer);
checksum.AsSpan(..4).CopyTo(buffer[data.Length..]);
var ret = Encode(buffer);
buffer.Clear();
return ret;
}

public static byte[] Decode(string input)
{
// Decode Base58 string to BigInteger
Expand All @@ -25,16 +49,15 @@ public static byte[] Decode(string input)
// Leading zero bytes get encoded as leading `1` characters
int leadingZeroCount = input.TakeWhile(c => c == Alphabet[0]).Count();
var leadingZeros = new byte[leadingZeroCount];
var bytesWithoutLeadingZeros = bi.ToByteArray()
.Reverse()// to big endian
.SkipWhile(b => b == 0);//strip sign byte
return leadingZeros.Concat(bytesWithoutLeadingZeros).ToArray();
if (bi.IsZero) return leadingZeros;
var bytesWithoutLeadingZeros = bi.ToByteArray(isUnsigned: true, isBigEndian: true);
return Concat(leadingZeros, bytesWithoutLeadingZeros);
}

public static string Encode(byte[] input)
public static string Encode(ReadOnlySpan<byte> input)
{
// Decode byte[] to BigInteger
BigInteger value = new BigInteger(new byte[1].Concat(input).Reverse().ToArray());
BigInteger value = new BigInteger(input, isUnsigned: true, isBigEndian: true);

// Encode BigInteger to Base58 string
var sb = new StringBuilder();
Expand Down
25 changes: 11 additions & 14 deletions src/neo/Cryptography/Crypto.cs
Original file line number Diff line number Diff line change
@@ -1,47 +1,44 @@
using System;
using System.Linq;
using System.Security.Cryptography;

namespace Neo.Cryptography
{
public class Crypto
public static class Crypto
{
public static readonly Crypto Default = new Crypto();

public byte[] Hash160(byte[] message)
public static byte[] Hash160(ReadOnlySpan<byte> message)
{
return message.Sha256().RIPEMD160();
}

public byte[] Hash256(byte[] message)
public static byte[] Hash256(ReadOnlySpan<byte> message)
{
return message.Sha256().Sha256();
}

public byte[] Sign(byte[] message, byte[] prikey, byte[] pubkey)
public static byte[] Sign(byte[] message, byte[] prikey, byte[] pubkey)
{
using (var ecdsa = ECDsa.Create(new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
D = prikey,
Q = new ECPoint
{
X = pubkey.Take(32).ToArray(),
Y = pubkey.Skip(32).ToArray()
X = pubkey[..32],
Y = pubkey[32..]
}
}))
{
return ecdsa.SignData(message, HashAlgorithmName.SHA256);
}
}

public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey)
public static bool VerifySignature(ReadOnlySpan<byte> message, ReadOnlySpan<byte> signature, byte[] pubkey)
{
if (pubkey.Length == 33 && (pubkey[0] == 0x02 || pubkey[0] == 0x03))
{
try
{
pubkey = Cryptography.ECC.ECPoint.DecodePoint(pubkey, Cryptography.ECC.ECCurve.Secp256r1).EncodePoint(false).Skip(1).ToArray();
pubkey = ECC.ECPoint.DecodePoint(pubkey, ECC.ECCurve.Secp256r1).EncodePoint(false)[1..];
}
catch
{
Expand All @@ -50,7 +47,7 @@ public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey)
}
else if (pubkey.Length == 65 && pubkey[0] == 0x04)
{
pubkey = pubkey.Skip(1).ToArray();
pubkey = pubkey[1..];
}
else if (pubkey.Length != 64)
{
Expand All @@ -61,8 +58,8 @@ public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey)
Curve = ECCurve.NamedCurves.nistP256,
Q = new ECPoint
{
X = pubkey.Take(32).ToArray(),
Y = pubkey.Skip(32).ToArray()
X = pubkey[..32],
Y = pubkey[32..]
}
}))
{
Expand Down
3 changes: 3 additions & 0 deletions src/neo/Cryptography/ECC/ECCurve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ public class ECCurve
public readonly ECPoint Infinity;
public readonly ECPoint G;

public readonly int ExpectedECPointLength;

private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G)
{
this.Q = Q;
this.ExpectedECPointLength = (Q.GetBitLength() + 7) / 8;
this.A = new ECFieldElement(A, this);
this.B = new ECFieldElement(B, this);
this.N = N;
Expand Down
11 changes: 5 additions & 6 deletions src/neo/Cryptography/ECC/ECDsa.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Numerics;
using System.Security.Cryptography;

Expand All @@ -23,22 +22,22 @@ public ECDsa(ECPoint publicKey)
this.curve = publicKey.Curve;
}

private BigInteger CalculateE(BigInteger n, byte[] message)
private BigInteger CalculateE(BigInteger n, ReadOnlySpan<byte> message)
{
int messageBitLength = message.Length * 8;
BigInteger trunc = new BigInteger(message.Reverse().Concat(new byte[1]).ToArray());
BigInteger trunc = new BigInteger(message, isUnsigned: true, isBigEndian: true);
if (n.GetBitLength() < messageBitLength)
{
trunc >>= messageBitLength - n.GetBitLength();
}
return trunc;
}

public BigInteger[] GenerateSignature(byte[] message)
public BigInteger[] GenerateSignature(ReadOnlySpan<byte> message)
{
if (privateKey == null) throw new InvalidOperationException();
BigInteger e = CalculateE(curve.N, message);
BigInteger d = new BigInteger(privateKey.Reverse().Concat(new byte[1]).ToArray());
BigInteger d = new BigInteger(privateKey, isUnsigned: true, isBigEndian: true);
BigInteger r, s;
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
Expand Down Expand Up @@ -92,7 +91,7 @@ private static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger k, ECPoint Q, Bi
return R;
}

public bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
public bool VerifySignature(ReadOnlySpan<byte> message, BigInteger r, BigInteger s)
{
if (r.Sign < 1 || s.Sign < 1 || r.CompareTo(curve.N) >= 0 || s.CompareTo(curve.N) >= 0)
return false;
Expand Down
15 changes: 6 additions & 9 deletions src/neo/Cryptography/ECC/ECFieldElement.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Numerics;

namespace Neo.Cryptography.ECC
Expand Down Expand Up @@ -28,9 +27,7 @@ public override bool Equals(object obj)
if (obj == this)
return true;

ECFieldElement other = obj as ECFieldElement;

if (other == null)
if (!(obj is ECFieldElement other))
return false;

return Equals(other);
Expand Down Expand Up @@ -142,12 +139,12 @@ public ECFieldElement Square()

public byte[] ToByteArray()
{
byte[] data = Value.ToByteArray();
byte[] data = Value.ToByteArray(isUnsigned: true, isBigEndian: true);
if (data.Length == 32)
return data.Reverse().ToArray();
if (data.Length > 32)
return data.Take(32).Reverse().ToArray();
return Enumerable.Repeat<byte>(0, 32 - data.Length).Concat(data.Reverse()).ToArray();
return data;
byte[] buffer = new byte[32];
Buffer.BlockCopy(data, 0, buffer, buffer.Length - data.Length, data.Length);
return buffer;
}

public static ECFieldElement operator -(ECFieldElement x)
Expand Down
Loading