diff --git a/.gitignore b/.gitignore index 84381b0e3..45ea3b60e 100644 --- a/.gitignore +++ b/.gitignore @@ -202,4 +202,5 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser -# End of https://www.toptal.com/developers/gitignore/api/rider \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/rider +.idea diff --git a/build-debian-11.sh b/build-debian-11.sh index 294a081c5..5ea3aafc6 100755 --- a/build-debian-11.sh +++ b/build-debian-11.sh @@ -1,5 +1,9 @@ #!/bin/bash +# install install-dependencies +sudo apt-get update; \ + sudo apt-get -y install wget + # add dotnet repo sudo wget https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb diff --git a/build-ubuntu-20.04.sh b/build-ubuntu-20.04.sh index 51dcd577b..d3fe3dd11 100755 --- a/build-ubuntu-20.04.sh +++ b/build-ubuntu-20.04.sh @@ -1,5 +1,9 @@ #!/bin/bash +# install install-dependencies +sudo apt-get update; \ + sudo apt-get -y install wget + # add dotnet repo wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb diff --git a/build-ubuntu-21.04.sh b/build-ubuntu-21.04.sh index bbc8c49a8..c46ca983e 100755 --- a/build-ubuntu-21.04.sh +++ b/build-ubuntu-21.04.sh @@ -1,5 +1,9 @@ #!/bin/bash +# install install-dependencies +sudo apt-get update; \ + sudo apt-get -y install wget + # add dotnet repo wget https://packages.microsoft.com/config/ubuntu/21.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb diff --git a/build-ubuntu-22.04.sh b/build-ubuntu-22.04.sh new file mode 100644 index 000000000..de1e3750c --- /dev/null +++ b/build-ubuntu-22.04.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# dotnet 6 or higher is included in Ubuntu 22.04 and up + +# install dev-dependencies +sudo apt-get update; \ + sudo apt-get -y install dotnet-sdk-6.0 git cmake build-essential libssl-dev pkg-config libboost-all-dev libsodium-dev libzmq5 + +(cd src/Miningcore && \ +BUILDIR=${1:-../../build} && \ +echo "Building into $BUILDIR" && \ +dotnet publish -c Release --framework net6.0 -o $BUILDIR) diff --git a/libs/runtimes/win-x64/libcryptonote.dll b/libs/runtimes/win-x64/libcryptonote.dll index cdd76dc39..cf7410910 100644 Binary files a/libs/runtimes/win-x64/libcryptonote.dll and b/libs/runtimes/win-x64/libcryptonote.dll differ diff --git a/src/Miningcore.Tests/Banning/IntegratedBanManagerTests.cs b/src/Miningcore.Tests/Banning/IntegratedBanManagerTests.cs new file mode 100644 index 000000000..c87398fc2 --- /dev/null +++ b/src/Miningcore.Tests/Banning/IntegratedBanManagerTests.cs @@ -0,0 +1,48 @@ +using System; +using System.Net; +using System.Threading; +using Autofac; +using Miningcore.Banning; +using Miningcore.Configuration; +using Xunit; + +namespace Miningcore.Tests.Banning; + +public class IntegratedBanManagerTests : TestBase +{ + private static readonly IPAddress address = IPAddress.Parse("192.168.1.1"); + + [Fact] + public void Ban_Valid_Address() + { + var manager = ModuleInitializer.Container.ResolveKeyed(BanManagerKind.Integrated); + + Assert.False(manager.IsBanned(address)); + manager.Ban(address, TimeSpan.FromSeconds(1)); + Assert.True(manager.IsBanned(address)); + + // let it expire + Thread.Sleep(TimeSpan.FromSeconds(2)); + Assert.False(manager.IsBanned(address)); + } + + [Fact] + public void Throw_Invalid_Duration() + { + var manager = ModuleInitializer.Container.ResolveKeyed(BanManagerKind.Integrated); + + Assert.ThrowsAny(() => manager.Ban(address, TimeSpan.Zero)); + } + + [Fact] + public void Dont_Ban_Loopback() + { + var manager = ModuleInitializer.Container.ResolveKeyed(BanManagerKind.Integrated); + + manager.Ban(IPAddress.Loopback, TimeSpan.FromSeconds(1)); + Assert.False(manager.IsBanned(address)); + + manager.Ban(IPAddress.IPv6Loopback, TimeSpan.FromSeconds(1)); + Assert.False(manager.IsBanned(address)); + } +} diff --git a/src/Miningcore.Tests/Benchmarks/BenchmarkRunner.cs b/src/Miningcore.Tests/Benchmarks/BenchmarkRunner.cs new file mode 100644 index 000000000..cf6666f23 --- /dev/null +++ b/src/Miningcore.Tests/Benchmarks/BenchmarkRunner.cs @@ -0,0 +1,34 @@ +using System; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Loggers; +using BenchmarkDotNet.Running; +using Miningcore.Tests.Benchmarks.Stratum; +using Xunit; +using Xunit.Abstractions; + +namespace Miningcore.Tests.Benchmarks; + +public class Benchmarks +{ + private readonly ITestOutputHelper output; + + public Benchmarks(ITestOutputHelper output) + { + this.output = output; + } + + [Fact(Skip = "** Uncomment me to run benchmarks **")] + public void Run_Benchmarks() + { + var logger = new AccumulationLogger(); + + var config = ManualConfig.Create(DefaultConfig.Instance) + .AddLogger(logger) + .WithOptions(ConfigOptions.DisableOptimizationsValidator); + + BenchmarkRunner.Run(config); + + // write benchmark summary + output.WriteLine(logger.GetLog()); + } +} diff --git a/src/Miningcore.Tests/Benchmarks/Stratum/StratumConnectionBenchmarks.cs b/src/Miningcore.Tests/Benchmarks/Stratum/StratumConnectionBenchmarks.cs new file mode 100644 index 000000000..7860c77a2 --- /dev/null +++ b/src/Miningcore.Tests/Benchmarks/Stratum/StratumConnectionBenchmarks.cs @@ -0,0 +1,59 @@ +using System.Buffers; +using System.Diagnostics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Autofac; +using BenchmarkDotNet.Attributes; +using Microsoft.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Miningcore.JsonRpc; +using Miningcore.Stratum; +using Miningcore.Time; +using NLog; +#pragma warning disable 8974 + +namespace Miningcore.Tests.Benchmarks.Stratum; + +[MemoryDiagnoser] +public class StratumConnectionBenchmarks : TestBase +{ + private const string JsonRpcVersion = "2.0"; + private const string ConnectionId = "foo"; + private const string requestString = "{\"params\": [\"slush.miner1\", \"password\"], \"id\": 42, \"method\": \"mining.authorize\"}\\n"; + private const string ProcessRequestAsyncMethod = "ProcessRequestAsync"; + + private RecyclableMemoryStreamManager rmsm; + private IMasterClock clock; + private ILogger logger; + + private StratumConnection connection; + private PrivateObject wrapper; + + [GlobalSetup] + public void Setup() + { + ModuleInitializer.Initialize(); + + rmsm = ModuleInitializer.Container.Resolve(); + clock = ModuleInitializer.Container.Resolve(); + logger = new NullLogger(LogManager.LogFactory); + + connection = new(logger, rmsm, clock, ConnectionId); + wrapper = new(connection); + } + + Task OnPlaceholderRequestAsync(StratumConnection con, JsonRpcRequest request, CancellationToken ct) + { + return Task.CompletedTask; + } + + [Benchmark] + public async Task ProcessRequest_Handle_Valid_Request() + { + await (Task) wrapper.Invoke(ProcessRequestAsyncMethod, + CancellationToken.None, + OnPlaceholderRequestAsync, + new ReadOnlySequence(Encoding.UTF8.GetBytes(requestString))); + } +} diff --git a/src/Miningcore.Tests/Crypto/CrytonoteTests.cs b/src/Miningcore.Tests/Crypto/CrytonoteTests.cs index 44c314feb..55d90d1c1 100644 --- a/src/Miningcore.Tests/Crypto/CrytonoteTests.cs +++ b/src/Miningcore.Tests/Crypto/CrytonoteTests.cs @@ -25,6 +25,15 @@ public void Crytonote_DecodeAddress() Assert.Equal(18ul, result); } + [Fact] + public void Crytonote_DecodeSubAddress() + { + var address = "84k5FLcuZeQ9vUmTfRJkpxCxdppVF5wWdPpxhU4SdTZmAD1i1YH81rPf8XRAsbpc7Na4GG7A8xscjQbqMETLZCXZ7Cdfb7X"; + var result = CryptonoteBindings.DecodeAddress(address); + + Assert.Equal(42ul, result); + } + [Fact] public void Cryptonote_DecodeAddress_Should_Throw_On_Null_Or_Empty_Argument() { @@ -40,4 +49,15 @@ public void Crytonote_DecodeIntegratedAddress() Assert.Equal(19ul, result); } + + [Fact] + public void Cryptonote_CryptonightHashFast() + { + var value = "8519e039172b0d70e5ca7b3383d6b3167315a422747b73f019cf9528f0fde341fd0f2a63030ba6450525cf6de31837669af6f1df8131faf50aaab8d3a7405589".HexToByteArray(); + var hash = new byte[32]; + CryptonoteBindings.CryptonightHashFast(value, hash); + + var result = hash.ToHexString(); + Assert.Equal("daedcec20429ffd440ab70a0a3a549fbc89745581f539fd2ac945388698e2db2", result); + } } diff --git a/src/Miningcore.Tests/Miningcore.Tests.csproj b/src/Miningcore.Tests/Miningcore.Tests.csproj index 68977466c..1f77735bb 100644 --- a/src/Miningcore.Tests/Miningcore.Tests.csproj +++ b/src/Miningcore.Tests/Miningcore.Tests.csproj @@ -33,11 +33,14 @@ - + + + - - - + + + + all runtime; build; native; contentfiles; analyzers diff --git a/src/Miningcore.Tests/ModuleInitializer.cs b/src/Miningcore.Tests/ModuleInitializer.cs index 8229a0729..62666a13e 100644 --- a/src/Miningcore.Tests/ModuleInitializer.cs +++ b/src/Miningcore.Tests/ModuleInitializer.cs @@ -5,6 +5,8 @@ using AutoMapper; using Miningcore.Configuration; using Miningcore.Native; +using Miningcore.Tests.Util; +using Miningcore.Time; namespace Miningcore.Tests; @@ -38,6 +40,8 @@ public static void Initialize() builder.Register((ctx, parms) => amConf.CreateMapper()); + builder.RegisterType().AsImplementedInterfaces(); + // Autofac Container container = builder.Build(); diff --git a/src/Miningcore.Tests/Stratum/StratumConnectionTests.cs b/src/Miningcore.Tests/Stratum/StratumConnectionTests.cs new file mode 100644 index 000000000..c9e973aa5 --- /dev/null +++ b/src/Miningcore.Tests/Stratum/StratumConnectionTests.cs @@ -0,0 +1,129 @@ +using System; +using System.Buffers; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Autofac; +using Microsoft.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Miningcore.JsonRpc; +using Miningcore.Stratum; +using Miningcore.Time; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using NLog; +using NSubstitute; +using Xunit; + +#pragma warning disable 8974 + +namespace Miningcore.Tests.Stratum; + +public class StratumConnectionTests : TestBase +{ + private const string JsonRpcVersion = "2.0"; + private const string ConnectionId = "foo"; + private const string requestString = "{\"params\": [\"slush.miner1\", \"password\"], \"id\": 42, \"method\": \"mining.authorize\"}\\n"; + private const string ProcessRequestAsyncMethod = "ProcessRequestAsync"; + + private static readonly RecyclableMemoryStreamManager rmsm = ModuleInitializer.Container.Resolve(); + private static readonly IMasterClock clock = ModuleInitializer.Container.Resolve(); + private static readonly ILogger logger = new NullLogger(LogManager.LogFactory); + + [Fact] + public async Task ProcessRequest_Handle_Valid_Request() + { + var connection = new StratumConnection(logger, rmsm, clock, ConnectionId); + var wrapper = new PrivateObject(connection); + + Task handler(StratumConnection con, JsonRpcRequest request, CancellationToken ct) + { + Assert.Equal(request.JsonRpc, JsonRpcVersion); + Assert.Equal((long) request.Id, 42); + Assert.Equal(request.Method, "mining.authorize"); + Assert.True(request.Params is JArray); + Assert.Equal(request.ParamsAs().Count, 2); + Assert.Equal(request.ParamsAs()[0], "slush.miner1"); + Assert.Equal(request.ParamsAs()[1], "password"); + + return Task.CompletedTask; + } + + await (Task) wrapper.Invoke(ProcessRequestAsyncMethod, + CancellationToken.None, + handler, + new ReadOnlySequence(Encoding.UTF8.GetBytes(requestString))); + } + + [Fact] + public async Task ProcessRequest_Throw_On_Unparseable_Request() + { + const string invalidRequestString = "foo bar\\n"; + + var connection = new StratumConnection(logger, rmsm, clock, ConnectionId); + var wrapper = new PrivateObject(connection); + var callCount = 0; + + Task handler(StratumConnection con, JsonRpcRequest request, CancellationToken ct) + { + callCount++; + return Task.CompletedTask; + } + + await Assert.ThrowsAnyAsync(()=> (Task) wrapper.Invoke(ProcessRequestAsyncMethod, + CancellationToken.None, + handler, + new ReadOnlySequence(Encoding.UTF8.GetBytes(invalidRequestString)))); + + Assert.Equal(callCount, 0); + } + + [Fact] + public async Task ProcessRequest_Honor_CancellationToken() + { + var connection = new StratumConnection(logger, rmsm, clock, ConnectionId); + var wrapper = new PrivateObject(connection); + var callCount = 0; + + async Task handler(StratumConnection con, JsonRpcRequest request, CancellationToken ct) + { + callCount++; + + await Task.Delay(TimeSpan.FromSeconds(1), ct); + } + + using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(20)); + + await Assert.ThrowsAnyAsync(()=> (Task) wrapper.Invoke(ProcessRequestAsyncMethod, + cts.Token, + handler, + new ReadOnlySequence(Encoding.UTF8.GetBytes(requestString)))); + + Assert.Equal(callCount, 1); + } + + // [Fact] + // public async Task DetectSslHandshake_Positive() + // { + // const string MethodName = "DetectSslHandshake"; + // + // var connection = new StratumConnection(logger, rmsm, clock, ConnectionId); + // var wrapper = new PrivateObject(connection); + // + // var socket = Substitute.For(SocketType.Stream, ProtocolType.Tcp); + // var buf = new byte[1]; + // + // socket.ReceiveAsync(buf, SocketFlags.Peek, CancellationToken.None).ReturnsForAnyArgs(ValueTask.FromResult(1)).AndDoes(info => + // { + // var _buf = info.ArgAt>(0); + // _buf.Span[0] = 0x16; + // }); + // + // var result = await (Task) wrapper.Invoke(MethodName, + // socket, + // CancellationToken.None); + // + // Assert.True(result); + // } +} diff --git a/src/Miningcore.Tests/TestBase.cs b/src/Miningcore.Tests/TestBase.cs index 48c7f103d..1e89becd9 100644 --- a/src/Miningcore.Tests/TestBase.cs +++ b/src/Miningcore.Tests/TestBase.cs @@ -1,12 +1,7 @@ -using System.Collections.Generic; -using Miningcore.Configuration; - namespace Miningcore.Tests; public abstract class TestBase { - protected Dictionary coinTemplates; - protected TestBase() { ModuleInitializer.Initialize(); diff --git a/src/Miningcore.Tests/Util/PrivateObjectPrivateType.cs b/src/Miningcore.Tests/Util/PrivateObjectPrivateType.cs new file mode 100644 index 000000000..e99016828 --- /dev/null +++ b/src/Miningcore.Tests/Util/PrivateObjectPrivateType.cs @@ -0,0 +1,1864 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Reflection; + +namespace Microsoft.VisualStudio.TestTools.UnitTesting +{ + /// + /// This class represents the live NON public INTERNAL object in the system + /// + public class PrivateObject + { + // bind everything + private const BindingFlags BindToEveryThing = BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public; + + private static BindingFlags constructorFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.NonPublic; + + private object target; // automatically initialized to null + private Type originalType; // automatically initialized to null + + private Dictionary> methodCache; // automatically initialized to null + + /// + /// Initializes a new instance of the class that contains + /// the already existing object of the private class + /// + /// object that serves as starting point to reach the private members + /// the derefrencing string using . that points to the object to be retrived as in m_X.m_Y.m_Z + public PrivateObject(object obj, string memberToAccess) + { + ValidateAccessString(memberToAccess); + + PrivateObject temp = obj as PrivateObject; + if (temp == null) + { + temp = new PrivateObject(obj); + } + + // Split The access string + string[] arr = memberToAccess.Split(new char[] { '.' }); + + for (int i = 0; i < arr.Length; i++) + { + object next = temp.InvokeHelper(arr[i], BindToEveryThing | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty, null, CultureInfo.InvariantCulture); + temp = new PrivateObject(next); + } + + this.target = temp.target; + this.originalType = temp.originalType; + } + + /// + /// Initializes a new instance of the class that wraps the + /// specified type. + /// + /// Name of the assembly + /// fully qualified name + /// Argmenets to pass to the constructor + public PrivateObject(string assemblyName, string typeName, params object[] args) + : this(assemblyName, typeName, null, args) + { + } + + /// + /// Initializes a new instance of the class that wraps the + /// specified type. + /// + /// Name of the assembly + /// fully qualified name + /// An array of objects representing the number, order, and type of the parameters for the constructor to get + /// Argmenets to pass to the constructor + public PrivateObject(string assemblyName, string typeName, Type[] parameterTypes, object[] args) + : this(Type.GetType(string.Format(CultureInfo.InvariantCulture, "{0}, {1}", typeName, assemblyName), false), parameterTypes, args) + { + } + + /// + /// Initializes a new instance of the class that wraps the + /// specified type. + /// + /// type of the object to create + /// Argmenets to pass to the constructor + public PrivateObject(Type type, params object[] args) + : this(type, null, args) + { + } + + /// + /// Initializes a new instance of the class that wraps the + /// specified type. + /// + /// type of the object to create + /// An array of objects representing the number, order, and type of the parameters for the constructor to get + /// Argmenets to pass to the constructor + public PrivateObject(Type type, Type[] parameterTypes, object[] args) + { + object o; + if (parameterTypes != null) + { + ConstructorInfo ci = type.GetConstructor(BindToEveryThing, null, parameterTypes, null); + if (ci == null) + { + throw new ArgumentException("The constructor with the specified signature could not be found. You might need to regenerate your private accessor, or the member may be private and defined on a base class. If the latter is true, you need to pass the type that defines the member into PrivateObject's constructor."); + } + + try + { + o = ci.Invoke(args); + } + catch (TargetInvocationException e) + { + Debug.Assert(e.InnerException != null, "Inner exception should not be null."); + if (e.InnerException != null) + { + throw e.InnerException; + } + + throw; + } + } + else + { + o = Activator.CreateInstance(type, constructorFlags, null, args, null); + } + + this.ConstructFrom(o); + } + + /// + /// Initializes a new instance of the class that wraps + /// the given object. + /// + /// object to wrap + public PrivateObject(object obj) + { + this.ConstructFrom(obj); + } + + /// + /// Initializes a new instance of the class that wraps + /// the given object. + /// + /// object to wrap + /// PrivateType object + public PrivateObject(object obj, PrivateType type) + { + this.target = obj; + this.originalType = type.ReferencedType; + } + + /// + /// Gets or sets the target + /// + public object Target + { + get + { + return this.target; + } + + set + { + this.target = value; + this.originalType = value.GetType(); + } + } + + /// + /// Gets the type of underlying object + /// + public Type RealType + { + get + { + return this.originalType; + } + } + + private Dictionary> GenericMethodCache + { + get + { + if (this.methodCache == null) + { + this.BuildGenericMethodCacheForType(this.originalType); + } + + Debug.Assert(this.methodCache != null, "Invalid method cache for type."); + + return this.methodCache; + } + } + + /// + /// returns the hash code of the target object + /// + /// int representing hashcode of the target object + public override int GetHashCode() + { + Debug.Assert(this.target != null, "target should not be null."); + return this.target.GetHashCode(); + } + + /// + /// Equals + /// + /// Object with whom to compare + /// returns true if the objects are equal. + public override bool Equals(object obj) + { + if (this != obj) + { + Debug.Assert(this.target != null, "target should not be null."); + if (typeof(PrivateObject) == obj?.GetType()) + { + return this.target.Equals(((PrivateObject)obj).target); + } + else + { + return false; + } + } + + return true; + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// Arguments to pass to the member to invoke. + /// Result of method call + public object Invoke(string name, params object[] args) + { + return this.Invoke(name, null, args, CultureInfo.InvariantCulture); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// An array of objects representing the number, order, and type of the parameters for the method to get. + /// Arguments to pass to the member to invoke. + /// Result of method call + public object Invoke(string name, Type[] parameterTypes, object[] args) + { + return this.Invoke(name, parameterTypes, args, CultureInfo.InvariantCulture); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// An array of objects representing the number, order, and type of the parameters for the method to get. + /// Arguments to pass to the member to invoke. + /// An array of types corresponding to the types of the generic arguments. + /// Result of method call + public object Invoke(string name, Type[] parameterTypes, object[] args, Type[] typeArguments) + { + return this.Invoke(name, BindToEveryThing, parameterTypes, args, CultureInfo.InvariantCulture, typeArguments); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// Arguments to pass to the member to invoke. + /// Culture info + /// Result of method call + public object Invoke(string name, object[] args, CultureInfo culture) + { + return this.Invoke(name, null, args, culture); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// An array of objects representing the number, order, and type of the parameters for the method to get. + /// Arguments to pass to the member to invoke. + /// Culture info + /// Result of method call + public object Invoke(string name, Type[] parameterTypes, object[] args, CultureInfo culture) + { + return this.Invoke(name, BindToEveryThing, parameterTypes, args, culture); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// A bitmask comprised of one or more that specify how the search is conducted. + /// Arguments to pass to the member to invoke. + /// Result of method call + public object Invoke(string name, BindingFlags bindingFlags, params object[] args) + { + return this.Invoke(name, bindingFlags, null, args, CultureInfo.InvariantCulture); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// A bitmask comprised of one or more that specify how the search is conducted. + /// An array of objects representing the number, order, and type of the parameters for the method to get. + /// Arguments to pass to the member to invoke. + /// Result of method call + public object Invoke(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args) + { + return this.Invoke(name, bindingFlags, parameterTypes, args, CultureInfo.InvariantCulture); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// A bitmask comprised of one or more that specify how the search is conducted. + /// Arguments to pass to the member to invoke. + /// Culture info + /// Result of method call + public object Invoke(string name, BindingFlags bindingFlags, object[] args, CultureInfo culture) + { + return this.Invoke(name, bindingFlags, null, args, culture); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// A bitmask comprised of one or more that specify how the search is conducted. + /// An array of objects representing the number, order, and type of the parameters for the method to get. + /// Arguments to pass to the member to invoke. + /// Culture info + /// Result of method call + public object Invoke(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args, CultureInfo culture) + { + return this.Invoke(name, bindingFlags, parameterTypes, args, culture, null); + } + + /// + /// Invokes the specified method + /// + /// Name of the method + /// A bitmask comprised of one or more that specify how the search is conducted. + /// An array of objects representing the number, order, and type of the parameters for the method to get. + /// Arguments to pass to the member to invoke. + /// Culture info + /// An array of types corresponding to the types of the generic arguments. + /// Result of method call + public object Invoke(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args, CultureInfo culture, Type[] typeArguments) + { + if (parameterTypes != null) + { + bindingFlags |= BindToEveryThing | BindingFlags.Instance; + + // Fix up the parameter types + MethodInfo member = this.originalType.GetMethod(name, bindingFlags, null, parameterTypes, null); + + // If the method was not found and type arguments were provided for generic paramaters, + // attempt to look up a generic method. + if ((member == null) && (typeArguments != null)) + { + // This method may contain generic parameters...if so, the previous call to + // GetMethod() will fail because it doesn't fully support generic parameters. + + // Look in the method cache to see if there is a generic method + // on the incoming type that contains the correct signature. + member = this.GetGenericMethodFromCache(name, parameterTypes, typeArguments, bindingFlags, null); + } + + if (member == null) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, "The member specified ({0}) could not be found. You might need to regenerate your private accessor, or the member may be private and defined on a base class. If the latter is true, you need to pass the type that defines the member into PrivateObject's constructor.", name)); + } + + try + { + if (member.IsGenericMethodDefinition) + { + MethodInfo constructed = member.MakeGenericMethod(typeArguments); + return constructed.Invoke(this.target, bindingFlags, null, args, culture); + } + else + { + return member.Invoke(this.target, bindingFlags, null, args, culture); + } + } + catch (TargetInvocationException e) + { + Debug.Assert(e.InnerException != null, "Inner exception should not be null."); + if (e.InnerException != null) + { + throw e.InnerException; + } + + throw; + } + } + else + { + return this.InvokeHelper(name, bindingFlags | BindingFlags.InvokeMethod, args, culture); + } + } + + /// + /// Gets the array element using array of subsrcipts for each dimension + /// + /// Name of the member + /// the indices of array + /// An arrya of elements. + public object GetArrayElement(string name, params int[] indices) + { + return this.GetArrayElement(name, BindToEveryThing, indices); + } + + /// + /// Sets the array element using array of subsrcipts for each dimension + /// + /// Name of the member + /// Value to set + /// the indices of array + public void SetArrayElement(string name, object value, params int[] indices) + { + this.SetArrayElement(name, BindToEveryThing, value, indices); + } + + /// + /// Gets the array element using array of subsrcipts for each dimension + /// + /// Name of the member + /// A bitmask comprised of one or more that specify how the search is conducted. + /// the indices of array + /// An arrya of elements. + public object GetArrayElement(string name, BindingFlags bindingFlags, params int[] indices) + { + Array arr = (Array)this.InvokeHelper(name, BindingFlags.GetField | bindingFlags, null, CultureInfo.InvariantCulture); + return arr.GetValue(indices); + } + + /// + /// Sets the array element using array of subsrcipts for each dimension + /// + /// Name of the member + /// A bitmask comprised of one or more that specify how the search is conducted. + /// Value to set + /// the indices of array + public void SetArrayElement(string name, BindingFlags bindingFlags, object value, params int[] indices) + { + Array arr = (Array)this.InvokeHelper(name, BindingFlags.GetField | bindingFlags, null, CultureInfo.InvariantCulture); + arr.SetValue(value, indices); + } + + /// + /// Get the field + /// + /// Name of the field + /// The field. + public object GetField(string name) + { + return this.GetField(name, BindToEveryThing); + } + + /// + /// Sets the field + /// + /// Name of the field + /// value to set + public void SetField(string name, object value) + { + this.SetField(name, BindToEveryThing, value); + } + + /// + /// Gets the field + /// + /// Name of the field + /// A bitmask comprised of one or more that specify how the search is conducted. + /// The field. + public object GetField(string name, BindingFlags bindingFlags) + { + return this.InvokeHelper(name, BindingFlags.GetField | bindingFlags, null, CultureInfo.InvariantCulture); + } + + /// + /// Sets the field + /// + /// Name of the field + /// A bitmask comprised of one or more that specify how the search is conducted. + /// value to set + public void SetField(string name, BindingFlags bindingFlags, object value) + { + this.InvokeHelper(name, BindingFlags.SetField | bindingFlags, new object[] { value }, CultureInfo.InvariantCulture); + } + + /// + /// Get the field or property + /// + /// Name of the field or property + /// The field or property. + public object GetFieldOrProperty(string name) + { + return this.GetFieldOrProperty(name, BindToEveryThing); + } + + /// + /// Sets the field or property + /// + /// Name of the field or property + /// value to set + public void SetFieldOrProperty(string name, object value) + { + this.SetFieldOrProperty(name, BindToEveryThing, value); + } + + /// + /// Gets the field or property + /// + /// Name of the field or property + /// A bitmask comprised of one or more that specify how the search is conducted. + /// The field or property. + public object GetFieldOrProperty(string name, BindingFlags bindingFlags) + { + return this.InvokeHelper(name, BindingFlags.GetField | BindingFlags.GetProperty | bindingFlags, null, CultureInfo.InvariantCulture); + } + + /// + /// Sets the field or property + /// + /// Name of the field or property + /// A bitmask comprised of one or more that specify how the search is conducted. + /// value to set + public void SetFieldOrProperty(string name, BindingFlags bindingFlags, object value) + { + this.InvokeHelper(name, BindingFlags.SetField | BindingFlags.SetProperty | bindingFlags, new object[] { value }, CultureInfo.InvariantCulture); + } + + /// + /// Gets the property + /// + /// Name of the property + /// Arguments to pass to the member to invoke. + /// The property. + public object GetProperty(string name, params object[] args) + { + return this.GetProperty(name, null, args); + } + + /// + /// Gets the property + /// + /// Name of the property + /// An array of objects representing the number, order, and type of the parameters for the indexed property. + /// Arguments to pass to the member to invoke. + /// The property. + public object GetProperty(string name, Type[] parameterTypes, object[] args) + { + return this.GetProperty(name, BindToEveryThing, parameterTypes, args); + } + + /// + /// Set the property + /// + /// Name of the property + /// value to set + /// Arguments to pass to the member to invoke. + public void SetProperty(string name, object value, params object[] args) + { + this.SetProperty(name, null, value, args); + } + + /// + /// Set the property + /// + /// Name of the property + /// An array of objects representing the number, order, and type of the parameters for the indexed property. + /// value to set + /// Arguments to pass to the member to invoke. + public void SetProperty(string name, Type[] parameterTypes, object value, object[] args) + { + this.SetProperty(name, BindToEveryThing, value, parameterTypes, args); + } + + /// + /// Gets the property + /// + /// Name of the property + /// A bitmask comprised of one or more that specify how the search is conducted. + /// Arguments to pass to the member to invoke. + /// The property. + public object GetProperty(string name, BindingFlags bindingFlags, params object[] args) + { + return this.GetProperty(name, bindingFlags, null, args); + } + + /// + /// Gets the property + /// + /// Name of the property + /// A bitmask comprised of one or more that specify how the search is conducted. + /// An array of objects representing the number, order, and type of the parameters for the indexed property. + /// Arguments to pass to the member to invoke. + /// The property. + public object GetProperty(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args) + { + if (parameterTypes != null) + { + PropertyInfo pi = this.originalType.GetProperty(name, bindingFlags, null, null, parameterTypes, null); + if (pi == null) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, "The member specified ({0}) could not be found. You might need to regenerate your private accessor, or the member may be private and defined on a base class. If the latter is true, you need to pass the type that defines the member into PrivateObject's constructor.", name)); + } + + return pi.GetValue(this.target, args); + } + else + { + return this.InvokeHelper(name, bindingFlags | BindingFlags.GetProperty, args, null); + } + } + + /// + /// Sets the property + /// + /// Name of the property + /// A bitmask comprised of one or more that specify how the search is conducted. + /// value to set + /// Arguments to pass to the member to invoke. + public void SetProperty(string name, BindingFlags bindingFlags, object value, params object[] args) + { + this.SetProperty(name, bindingFlags, value, null, args); + } + + /// + /// Sets the property + /// + /// Name of the property + /// A bitmask comprised of one or more that specify how the search is conducted. + /// value to set + /// An array of objects representing the number, order, and type of the parameters for the indexed property. + /// Arguments to pass to the member to invoke. + public void SetProperty(string name, BindingFlags bindingFlags, object value, Type[] parameterTypes, object[] args) + { + if (parameterTypes != null) + { + PropertyInfo pi = this.originalType.GetProperty(name, bindingFlags, null, null, parameterTypes, null); + if (pi == null) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, "The member specified ({0}) could not be found. You might need to regenerate your private accessor, or the member may be private and defined on a base class. If the latter is true, you need to pass the type that defines the member into PrivateObject's constructor.", name)); + } + + pi.SetValue(this.target, value, args); + } + else + { + object[] pass = new object[(args?.Length ?? 0) + 1]; + pass[0] = value; + args?.CopyTo(pass, 1); + this.InvokeHelper(name, bindingFlags | BindingFlags.SetProperty, pass, null); + } + } + + /// + /// Validate access string + /// + /// access string + private static void ValidateAccessString(string access) + { + if (access.Length == 0) + { + throw new ArgumentException("Access string has invalid syntax."); + } + + string[] arr = access.Split('.'); + foreach (string str in arr) + { + if ((str.Length == 0) || (str.IndexOfAny(new char[] { ' ', '\t', '\n' }) != -1)) + { + throw new ArgumentException("Access string has invalid syntax."); + } + } + } + + /// + /// Invokes the memeber + /// + /// Name of the member + /// Additional attributes + /// Arguments for the invocation + /// Culture + /// Result of the invocation + private object InvokeHelper(string name, BindingFlags bindingFlags, object[] args, CultureInfo culture) + { + Debug.Assert(this.target != null, "Internal Error: Null reference is returned for internal object"); + + // Invoke the actual Method + try + { + return this.originalType.InvokeMember(name, bindingFlags, null, this.target, args, culture); + } + catch (TargetInvocationException e) + { + Debug.Assert(e.InnerException != null, "Inner exception should not be null."); + if (e.InnerException != null) + { + throw e.InnerException; + } + + throw; + } + } + + private void ConstructFrom(object obj) + { + this.target = obj; + this.originalType = obj.GetType(); + } + + private void BuildGenericMethodCacheForType(Type t) + { + Debug.Assert(t != null, "type should not be null."); + this.methodCache = new Dictionary>(); + + MethodInfo[] members = t.GetMethods(BindToEveryThing); + LinkedList listByName; // automatically initialized to null + + foreach (MethodInfo member in members) + { + if (member.IsGenericMethod || member.IsGenericMethodDefinition) + { + if (!this.GenericMethodCache.TryGetValue(member.Name, out listByName)) + { + listByName = new LinkedList(); + this.GenericMethodCache.Add(member.Name, listByName); + } + + Debug.Assert(listByName != null, "list should not be null."); + listByName.AddLast(member); + } + } + } + + /// + /// Extracts the most appropriate generic method signature from the current private type. + /// + /// The name of the method in which to search the signature cache. + /// An array of types corresponding to the types of the parameters in which to search. + /// An array of types corresponding to the types of the generic arguments. + /// to further filter the method signatures. + /// Modifiers for parameters. + /// A methodinfo instance. + private MethodInfo GetGenericMethodFromCache(string methodName, Type[] parameterTypes, Type[] typeArguments, BindingFlags bindingFlags, ParameterModifier[] modifiers) + { + Debug.Assert(!string.IsNullOrEmpty(methodName), "Invalid method name."); + Debug.Assert(parameterTypes != null, "Invalid parameter type array."); + Debug.Assert(typeArguments != null, "Invalid type arguments array."); + + // Build a preliminary list of method candidates that contain roughly the same signature. + var methodCandidates = this.GetMethodCandidates(methodName, parameterTypes, typeArguments, bindingFlags, modifiers); + + // Search of ambiguous methods (methods with the same signature). + MethodInfo[] finalCandidates = new MethodInfo[methodCandidates.Count]; + methodCandidates.CopyTo(finalCandidates, 0); + + if ((parameterTypes != null) && (parameterTypes.Length == 0)) + { + for (int i = 0; i < finalCandidates.Length; i++) + { + MethodInfo methodInfo = finalCandidates[i]; + + if (!RuntimeTypeHelper.CompareMethodSigAndName(methodInfo, finalCandidates[0])) + { + throw new AmbiguousMatchException(); + } + } + + // All the methods have the exact same name and sig so return the most derived one. + return RuntimeTypeHelper.FindMostDerivedNewSlotMeth(finalCandidates, finalCandidates.Length) as MethodInfo; + } + + // Now that we have a preliminary list of candidates, select the most appropriate one. + return RuntimeTypeHelper.SelectMethod(bindingFlags, finalCandidates, parameterTypes, modifiers) as MethodInfo; + } + + private LinkedList GetMethodCandidates(string methodName, Type[] parameterTypes, Type[] typeArguments, BindingFlags bindingFlags, ParameterModifier[] modifiers) + { + Debug.Assert(!string.IsNullOrEmpty(methodName), "methodName should not be null."); + Debug.Assert(parameterTypes != null, "parameterTypes should not be null."); + Debug.Assert(typeArguments != null, "typeArguments should not be null."); + + LinkedList methodCandidates = new LinkedList(); + LinkedList methods = null; + + if (!this.GenericMethodCache.TryGetValue(methodName, out methods)) + { + return methodCandidates; + } + + Debug.Assert(methods != null, "methods should not be null."); + + foreach (MethodInfo candidate in methods) + { + bool paramMatch = true; + ParameterInfo[] candidateParams = null; + Type[] genericArgs = candidate.GetGenericArguments(); + Type sourceParameterType = null; + + if (genericArgs.Length != typeArguments.Length) + { + continue; + } + + // Since we can't just get the correct MethodInfo from Reflection, + // we will just match the number of parameters, their order, and their type + var methodCandidate = candidate; + candidateParams = methodCandidate.GetParameters(); + + if (candidateParams.Length != parameterTypes.Length) + { + continue; + } + + // Exact binding + if ((bindingFlags & BindingFlags.ExactBinding) != 0) + { + int i = 0; + + foreach (ParameterInfo candidateParam in candidateParams) + { + sourceParameterType = parameterTypes[i++]; + + if (candidateParam.ParameterType.ContainsGenericParameters) + { + // Since we have a generic parameter here, just make sure the IsArray matches. + if (candidateParam.ParameterType.IsArray != sourceParameterType.IsArray) + { + paramMatch = false; + break; + } + } + else + { + if (candidateParam.ParameterType != sourceParameterType) + { + paramMatch = false; + break; + } + } + } + + if (paramMatch) + { + methodCandidates.AddLast(methodCandidate); + continue; + } + } + else + { + methodCandidates.AddLast(methodCandidate); + } + } + + return methodCandidates; + } + } + + /// + /// This class represents a private class for the Private Accessor functionality. + /// + public class PrivateType + { + /// + /// Binds to everything + /// + private const BindingFlags BindToEveryThing = BindingFlags.Default + | BindingFlags.NonPublic | BindingFlags.Instance + | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy; + + /// + /// The wrapped type. + /// + private Type type; + + /// + /// Initializes a new instance of the class that contains the private type. + /// + /// Assembly name + /// fully qualified name of the + public PrivateType(string assemblyName, string typeName) + { + Assembly asm = Assembly.Load(assemblyName); + + this.type = asm.GetType(typeName, true); + } + + /// + /// Initializes a new instance of the class that contains + /// the private type from the type object + /// + /// The wrapped Type to create. + public PrivateType(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + this.type = type; + } + + /// + /// Gets the referenced type + /// + public Type ReferencedType => this.type; + + /// + /// Invokes static member + /// + /// Name of the member to InvokeHelper + /// Arguements to the invoction + /// Result of invocation + public object InvokeStatic(string name, params object[] args) + { + return this.InvokeStatic(name, null, args, CultureInfo.InvariantCulture); + } + + /// + /// Invokes static member + /// + /// Name of the member to InvokeHelper + /// An array of objects representing the number, order, and type of the parameters for the method to invoke + /// Arguements to the invoction + /// Result of invocation + public object InvokeStatic(string name, Type[] parameterTypes, object[] args) + { + return this.InvokeStatic(name, parameterTypes, args, CultureInfo.InvariantCulture); + } + + /// + /// Invokes static member + /// + /// Name of the member to InvokeHelper + /// An array of objects representing the number, order, and type of the parameters for the method to invoke + /// Arguements to the invoction + /// An array of types corresponding to the types of the generic arguments. + /// Result of invocation + public object InvokeStatic(string name, Type[] parameterTypes, object[] args, Type[] typeArguments) + { + return this.InvokeStatic(name, BindToEveryThing, parameterTypes, args, CultureInfo.InvariantCulture, typeArguments); + } + + /// + /// Invokes the static method + /// + /// Name of the member + /// Arguements to the invocation + /// Culture + /// Result of invocation + public object InvokeStatic(string name, object[] args, CultureInfo culture) + { + return this.InvokeStatic(name, null, args, culture); + } + + /// + /// Invokes the static method + /// + /// Name of the member + /// An array of objects representing the number, order, and type of the parameters for the method to invoke + /// Arguements to the invocation + /// Culture info + /// Result of invocation + public object InvokeStatic(string name, Type[] parameterTypes, object[] args, CultureInfo culture) + { + return this.InvokeStatic(name, BindingFlags.InvokeMethod, parameterTypes, args, culture); + } + + /// + /// Invokes the static method + /// + /// Name of the member + /// Additional invocation attributes + /// Arguements to the invocation + /// Result of invocation + public object InvokeStatic(string name, BindingFlags bindingFlags, params object[] args) + { + return this.InvokeStatic(name, bindingFlags, null, args, CultureInfo.InvariantCulture); + } + + /// + /// Invokes the static method + /// + /// Name of the member + /// Additional invocation attributes + /// An array of objects representing the number, order, and type of the parameters for the method to invoke + /// Arguements to the invocation + /// Result of invocation + public object InvokeStatic(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args) + { + return this.InvokeStatic(name, bindingFlags, parameterTypes, args, CultureInfo.InvariantCulture); + } + + /// + /// Invokes the static method + /// + /// Name of the member + /// Additional invocation attributes + /// Arguements to the invocation + /// Culture + /// Result of invocation + public object InvokeStatic(string name, BindingFlags bindingFlags, object[] args, CultureInfo culture) + { + return this.InvokeStatic(name, bindingFlags, null, args, culture); + } + + /// + /// Invokes the static method + /// + /// Name of the member + /// Additional invocation attributes + /// /// An array of objects representing the number, order, and type of the parameters for the method to invoke + /// Arguements to the invocation + /// Culture + /// Result of invocation + public object InvokeStatic(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args, CultureInfo culture) + { + return this.InvokeStatic(name, bindingFlags, parameterTypes, args, culture, null); + } + + /// + /// Invokes the static method + /// + /// Name of the member + /// Additional invocation attributes + /// /// An array of objects representing the number, order, and type of the parameters for the method to invoke + /// Arguements to the invocation + /// Culture + /// An array of types corresponding to the types of the generic arguments. + /// Result of invocation + public object InvokeStatic(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args, CultureInfo culture, Type[] typeArguments) + { + if (parameterTypes != null) + { + MethodInfo member = this.type.GetMethod(name, bindingFlags | BindToEveryThing | BindingFlags.Static, null, parameterTypes, null); + if (member == null) + { + throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "The member specified ({0}) could not be found. You might need to regenerate your private accessor, or the member may be private and defined on a base class. If the latter is true, you need to pass the type that defines the member into PrivateObject's constructor.", name)); + } + + try + { + if (member.IsGenericMethodDefinition) + { + MethodInfo constructed = member.MakeGenericMethod(typeArguments); + return constructed.Invoke(null, bindingFlags, null, args, culture); + } + else + { + return member.Invoke(null, bindingFlags, null, args, culture); + } + } + catch (TargetInvocationException e) + { + Debug.Assert(e.InnerException != null, "Inner Exception should not be null."); + if (e.InnerException != null) + { + throw e.InnerException; + } + + throw; + } + } + else + { + return this.InvokeHelperStatic(name, bindingFlags | BindingFlags.InvokeMethod, args, culture); + } + } + + /// + /// Gets the element in static array + /// + /// Name of the array + /// + /// A one-dimensional array of 32-bit integers that represent the indexes specifying + /// the position of the element to get. For instance, to access a[10][11] the indices would be {10,11} + /// + /// element at the specified location + public object GetStaticArrayElement(string name, params int[] indices) + { + return this.GetStaticArrayElement(name, BindToEveryThing, indices); + } + + /// + /// Sets the memeber of the static array + /// + /// Name of the array + /// value to set + /// + /// A one-dimensional array of 32-bit integers that represent the indexes specifying + /// the position of the element to set. For instance, to access a[10][11] the array would be {10,11} + /// + public void SetStaticArrayElement(string name, object value, params int[] indices) + { + this.SetStaticArrayElement(name, BindToEveryThing, value, indices); + } + + /// + /// Gets the element in satatic array + /// + /// Name of the array + /// Additional InvokeHelper attributes + /// + /// A one-dimensional array of 32-bit integers that represent the indexes specifying + /// the position of the element to get. For instance, to access a[10][11] the array would be {10,11} + /// + /// element at the spcified location + public object GetStaticArrayElement(string name, BindingFlags bindingFlags, params int[] indices) + { + Array arr = (Array)this.InvokeHelperStatic(name, BindingFlags.GetField | BindingFlags.GetProperty | bindingFlags, null, CultureInfo.InvariantCulture); + return arr.GetValue(indices); + } + + /// + /// Sets the memeber of the static array + /// + /// Name of the array + /// Additional InvokeHelper attributes + /// value to set + /// + /// A one-dimensional array of 32-bit integers that represent the indexes specifying + /// the position of the element to set. For instance, to access a[10][11] the array would be {10,11} + /// + public void SetStaticArrayElement(string name, BindingFlags bindingFlags, object value, params int[] indices) + { + Array arr = (Array)this.InvokeHelperStatic(name, BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Static | bindingFlags, null, CultureInfo.InvariantCulture); + arr.SetValue(value, indices); + } + + /// + /// Gets the static field + /// + /// Name of the field + /// The static field. + public object GetStaticField(string name) + { + return this.GetStaticField(name, BindToEveryThing); + } + + /// + /// Sets the static field + /// + /// Name of the field + /// Arguement to the invocation + public void SetStaticField(string name, object value) + { + this.SetStaticField(name, BindToEveryThing, value); + } + + /// + /// Gets the static field using specified InvokeHelper attributes + /// + /// Name of the field + /// Additional invocation attributes + /// The static field. + public object GetStaticField(string name, BindingFlags bindingFlags) + { + return this.InvokeHelperStatic(name, BindingFlags.GetField | BindingFlags.Static | bindingFlags, null, CultureInfo.InvariantCulture); + } + + /// + /// Sets the static field using binding attributes + /// + /// Name of the field + /// Additional InvokeHelper attributes + /// Arguement to the invocation + public void SetStaticField(string name, BindingFlags bindingFlags, object value) + { + this.InvokeHelperStatic(name, BindingFlags.SetField | bindingFlags | BindingFlags.Static, new[] { value }, CultureInfo.InvariantCulture); + } + + /// + /// Gets the static field or property + /// + /// Name of the field or property + /// The static field or property. + public object GetStaticFieldOrProperty(string name) + { + return this.GetStaticFieldOrProperty(name, BindToEveryThing); + } + + /// + /// Sets the static field or property + /// + /// Name of the field or property + /// Value to be set to field or property + public void SetStaticFieldOrProperty(string name, object value) + { + this.SetStaticFieldOrProperty(name, BindToEveryThing, value); + } + + /// + /// Gets the static field or property using specified InvokeHelper attributes + /// + /// Name of the field or property + /// Additional invocation attributes + /// The static field or property. + public object GetStaticFieldOrProperty(string name, BindingFlags bindingFlags) + { + return this.InvokeHelperStatic(name, BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Static | bindingFlags, null, CultureInfo.InvariantCulture); + } + + /// + /// Sets the static field or property using binding attributes + /// + /// Name of the field or property + /// Additional invocation attributes + /// Value to be set to field or property + public void SetStaticFieldOrProperty(string name, BindingFlags bindingFlags, object value) + { + this.InvokeHelperStatic(name, BindingFlags.SetField | BindingFlags.SetProperty | bindingFlags | BindingFlags.Static, new[] { value }, CultureInfo.InvariantCulture); + } + + /// + /// Gets the static property + /// + /// Name of the field or property + /// Arguements to the invocation + /// The static property. + public object GetStaticProperty(string name, params object[] args) + { + return this.GetStaticProperty(name, BindToEveryThing, args); + } + + /// + /// Sets the static property + /// + /// Name of the property + /// Value to be set to field or property + /// Arguments to pass to the member to invoke. + public void SetStaticProperty(string name, object value, params object[] args) + { + this.SetStaticProperty(name, BindToEveryThing, value, null, args); + } + + /// + /// Sets the static property + /// + /// Name of the property + /// Value to be set to field or property + /// An array of objects representing the number, order, and type of the parameters for the indexed property. + /// Arguments to pass to the member to invoke. + public void SetStaticProperty(string name, object value, Type[] parameterTypes, object[] args) + { + this.SetStaticProperty(name, BindingFlags.SetProperty, value, parameterTypes, args); + } + + /// + /// Gets the static property + /// + /// Name of the property + /// Additional invocation attributes. + /// Arguments to pass to the member to invoke. + /// The static property. + public object GetStaticProperty(string name, BindingFlags bindingFlags, params object[] args) + { + return this.GetStaticProperty(name, BindingFlags.GetProperty | BindingFlags.Static | bindingFlags, null, args); + } + + /// + /// Gets the static property + /// + /// Name of the property + /// Additional invocation attributes. + /// An array of objects representing the number, order, and type of the parameters for the indexed property. + /// Arguments to pass to the member to invoke. + /// The static property. + public object GetStaticProperty(string name, BindingFlags bindingFlags, Type[] parameterTypes, object[] args) + { + if (parameterTypes != null) + { + PropertyInfo pi = this.type.GetProperty(name, bindingFlags | BindingFlags.Static, null, null, parameterTypes, null); + if (pi == null) + { + throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "The member specified ({0}) could not be found. You might need to regenerate your private accessor, or the member may be private and defined on a base class. If the latter is true, you need to pass the type that defines the member into PrivateObject's constructor.", name)); + } + + return pi.GetValue(null, args); + } + else + { + return this.InvokeHelperStatic(name, bindingFlags | BindingFlags.GetProperty, args, null); + } + } + + /// + /// Sets the static property + /// + /// Name of the property + /// Additional invocation attributes. + /// Value to be set to field or property + /// Optional index values for indexed properties. The indexes of indexed properties are zero-based. This value should be null for non-indexed properties. + public void SetStaticProperty(string name, BindingFlags bindingFlags, object value, params object[] args) + { + this.SetStaticProperty(name, bindingFlags, value, null, args); + } + + /// + /// Sets the static property + /// + /// Name of the property + /// Additional invocation attributes. + /// Value to be set to field or property + /// An array of objects representing the number, order, and type of the parameters for the indexed property. + /// Arguments to pass to the member to invoke. + public void SetStaticProperty(string name, BindingFlags bindingFlags, object value, Type[] parameterTypes, object[] args) + { + if (parameterTypes != null) + { + PropertyInfo pi = this.type.GetProperty(name, bindingFlags | BindingFlags.Static, null, null, parameterTypes, null); + if (pi == null) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, "The member specified ({0}) could not be found. You might need to regenerate your private accessor, or the member may be private and defined on a base class. If the latter is true, you need to pass the type that defines the member into PrivateObject's constructor.", name)); + } + + pi.SetValue(null, value, args); + } + else + { + object[] pass = new object[(args?.Length ?? 0) + 1]; + pass[0] = value; + args?.CopyTo(pass, 1); + this.InvokeHelperStatic(name, bindingFlags | BindingFlags.SetProperty, pass, null); + } + } + + /// + /// Invokes the static method + /// + /// Name of the member + /// Additional invocation attributes + /// Arguements to the invocation + /// Culture + /// Result of invocation + private object InvokeHelperStatic(string name, BindingFlags bindingFlags, object[] args, CultureInfo culture) + { + try + { + return this.type.InvokeMember(name, bindingFlags | BindToEveryThing | BindingFlags.Static, null, null, args, culture); + } + catch (TargetInvocationException e) + { + Debug.Assert(e.InnerException != null, "Inner Exception should not be null."); + if (e.InnerException != null) + { + throw e.InnerException; + } + + throw; + } + } + } + + /// + /// Provides method signature discovery for generic methods. + /// + internal class RuntimeTypeHelper + { + /// + /// Compares the method signatures of these two methods. + /// + /// Method1 + /// Method2 + /// True if they are similiar. + internal static bool CompareMethodSigAndName(MethodBase m1, MethodBase m2) + { + ParameterInfo[] params1 = m1.GetParameters(); + ParameterInfo[] params2 = m2.GetParameters(); + + if (params1.Length != params2.Length) + { + return false; + } + + int numParams = params1.Length; + for (int i = 0; i < numParams; i++) + { + if (params1[i].ParameterType != params2[i].ParameterType) + { + return false; + } + } + + return true; + } + + /// + /// Gets the hierarchy depth from the base type of the provided type. + /// + /// The type. + /// The depth. + internal static int GetHierarchyDepth(Type t) + { + int depth = 0; + + Type currentType = t; + do + { + depth++; + currentType = currentType.BaseType; + } + while (currentType != null); + + return depth; + } + + /// + /// Finds most dervied type with the provided information. + /// + /// Candidate matches. + /// Number of matches. + /// The most derived method. + internal static MethodBase FindMostDerivedNewSlotMeth(MethodBase[] match, int cMatches) + { + int deepestHierarchy = 0; + MethodBase methWithDeepestHierarchy = null; + + for (int i = 0; i < cMatches; i++) + { + // Calculate the depth of the hierarchy of the declaring type of the + // current method. + int currentHierarchyDepth = GetHierarchyDepth(match[i].DeclaringType); + + // Two methods with the same hierarchy depth are not allowed. This would + // mean that there are 2 methods with the same name and sig on a given type + // which is not allowed, unless one of them is vararg... + if (currentHierarchyDepth == deepestHierarchy) + { + if (methWithDeepestHierarchy != null) + { + Debug.Assert( + methWithDeepestHierarchy != null && ((match[i].CallingConvention & CallingConventions.VarArgs) + | (methWithDeepestHierarchy.CallingConvention & CallingConventions.VarArgs)) != 0, + "Calling conventions: " + match[i].CallingConvention + " - " + methWithDeepestHierarchy.CallingConvention); + } + + throw new AmbiguousMatchException(); + } + + // Check to see if this method is on the most derived class. + if (currentHierarchyDepth > deepestHierarchy) + { + deepestHierarchy = currentHierarchyDepth; + methWithDeepestHierarchy = match[i]; + } + } + + return methWithDeepestHierarchy; + } + + /// + /// Given a set of methods that match the base criteria, select a method based + /// upon an array of types. This method should return null if no method matches + /// the criteria. + /// + /// Binding specification. + /// Candidate matches + /// Types + /// Parameter modifiers. + /// Matching method. Null if none matches. + internal static MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers) + { + if (match == null) + { + throw new ArgumentNullException("match"); + } + + int i; + int j; + + Type[] realTypes = new Type[types.Length]; + for (i = 0; i < types.Length; i++) + { + realTypes[i] = types[i].UnderlyingSystemType; + } + + types = realTypes; + + // If there are no methods to match to, then return null, indicating that no method + // matches the criteria + if (match.Length == 0) + { + return null; + } + + // Find all the methods that can be described by the types parameter. + // Remove all of them that cannot. + int curIdx = 0; + for (i = 0; i < match.Length; i++) + { + ParameterInfo[] par = match[i].GetParameters(); + if (par.Length != types.Length) + { + continue; + } + + for (j = 0; j < types.Length; j++) + { + Type pCls = par[j].ParameterType; + + if (pCls.ContainsGenericParameters) + { + if (pCls.IsArray != types[j].IsArray) + { + break; + } + } + else + { + if (pCls == types[j]) + { + continue; + } + + if (pCls == typeof(object)) + { + continue; + } + else + { + if (!pCls.IsAssignableFrom(types[j])) + { + break; + } + } + } + } + + if (j == types.Length) + { + match[curIdx++] = match[i]; + } + } + + if (curIdx == 0) + { + return null; + } + + if (curIdx == 1) + { + return match[0]; + } + + // Walk all of the methods looking the most specific method to invoke + int currentMin = 0; + bool ambig = false; + int[] paramOrder = new int[types.Length]; + for (i = 0; i < types.Length; i++) + { + paramOrder[i] = i; + } + + for (i = 1; i < curIdx; i++) + { + int newMin = FindMostSpecificMethod(match[currentMin], paramOrder, null, match[i], paramOrder, null, types, null); + if (newMin == 0) + { + ambig = true; + } + else + { + if (newMin == 2) + { + currentMin = i; + ambig = false; + currentMin = i; + } + } + } + + if (ambig) + { + throw new AmbiguousMatchException(); + } + + return match[currentMin]; + } + + /// + /// Finds the most specific method in the two methods provided. + /// + /// Method 1 + /// Parameter order for Method 1 + /// Paramter array type. + /// Method 2 + /// Parameter order for Method 2 + /// >Paramter array type. + /// Types to search in. + /// Args. + /// An int representing the match. + internal static int FindMostSpecificMethod( + MethodBase m1, + int[] paramOrder1, + Type paramArrayType1, + MethodBase m2, + int[] paramOrder2, + Type paramArrayType2, + Type[] types, + object[] args) + { + // Find the most specific method based on the parameters. + int res = FindMostSpecific( + m1.GetParameters(), + paramOrder1, + paramArrayType1, + m2.GetParameters(), + paramOrder2, + paramArrayType2, + types, + args); + + // If the match was not ambiguous then return the result. + if (res != 0) + { + return res; + } + + // Check to see if the methods have the exact same name and signature. + if (CompareMethodSigAndName(m1, m2)) + { + // Determine the depth of the declaring types for both methods. + int hierarchyDepth1 = GetHierarchyDepth(m1.DeclaringType); + int hierarchyDepth2 = GetHierarchyDepth(m2.DeclaringType); + + // The most derived method is the most specific one. + if (hierarchyDepth1 == hierarchyDepth2) + { + return 0; + } + else if (hierarchyDepth1 < hierarchyDepth2) + { + return 2; + } + else + { + return 1; + } + } + + // The match is ambiguous. + return 0; + } + + /// + /// Finds the most specific method in the two methods provided. + /// + /// Method 1 + /// Parameter order for Method 1 + /// Paramter array type. + /// Method 2 + /// Parameter order for Method 2 + /// >Paramter array type. + /// Types to search in. + /// Args. + /// An int representing the match. + internal static int FindMostSpecific( + ParameterInfo[] p1, + int[] paramOrder1, + Type paramArrayType1, + ParameterInfo[] p2, + int[] paramOrder2, + Type paramArrayType2, + Type[] types, + object[] args) + { + // A method using params is always less specific than one not using params + if (paramArrayType1 != null && paramArrayType2 == null) + { + return 2; + } + + if (paramArrayType2 != null && paramArrayType1 == null) + { + return 1; + } + + bool p1Less = false; + bool p2Less = false; + + for (int i = 0; i < types.Length; i++) + { + if (args != null && args[i] == Type.Missing) + { + continue; + } + + Type c1, c2; + + // If a param array is present, then either + // the user re-ordered the parameters in which case + // the argument to the param array is either an array + // in which case the params is conceptually ignored and so paramArrayType1 == null + // or the argument to the param array is a single element + // in which case paramOrder[i] == p1.Length - 1 for that element + // or the user did not re-order the parameters in which case + // the paramOrder array could contain indexes larger than p.Length - 1 + //// so any index >= p.Length - 1 is being put in the param array + + if (paramArrayType1 != null && paramOrder1[i] >= p1.Length - 1) + { + c1 = paramArrayType1; + } + else + { + c1 = p1[paramOrder1[i]].ParameterType; + } + + if (paramArrayType2 != null && paramOrder2[i] >= p2.Length - 1) + { + c2 = paramArrayType2; + } + else + { + c2 = p2[paramOrder2[i]].ParameterType; + } + + if (c1 == c2) + { + continue; + } + + if (c1.ContainsGenericParameters || c2.ContainsGenericParameters) + { + continue; + } + + switch (FindMostSpecificType(c1, c2, types[i])) + { + case 0: + return 0; + case 1: + p1Less = true; + break; + case 2: + p2Less = true; + break; + } + } + + // Two way p1Less and p2Less can be equal. All the arguments are the + // same they both equal false, otherwise there were things that both + // were the most specific type on.... + if (p1Less == p2Less) + { + // it's possible that the 2 methods have same sig and default param in which case we match the one + // with the same number of args but only if they were exactly the same (that is p1Less and p2Lees are both false) + if (!p1Less && p1.Length != p2.Length && args != null) + { + if (p1.Length == args.Length) + { + return 1; + } + else if (p2.Length == args.Length) + { + return 2; + } + } + + return 0; + } + else + { + return (p1Less == true) ? 1 : 2; + } + } + + /// + /// Finds the most specific type in the two provided. + /// + /// Type 1 + /// Type 2 + /// The defining type + /// An int representing the match. + internal static int FindMostSpecificType(Type c1, Type c2, Type t) + { + // If the two types are exact move on... + if (c1 == c2) + { + return 0; + } + + if (c1 == t) + { + return 1; + } + + if (c2 == t) + { + return 2; + } + + bool c1FromC2; + bool c2FromC1; + + if (c1.IsByRef || c2.IsByRef) + { + if (c1.IsByRef && c2.IsByRef) + { + c1 = c1.GetElementType(); + c2 = c2.GetElementType(); + } + else if (c1.IsByRef) + { + if (c1.GetElementType() == c2) + { + return 2; + } + + c1 = c1.GetElementType(); + } + else + { + if (c2.GetElementType() == c1) + { + return 1; + } + + c2 = c2.GetElementType(); + } + } + + if (c1.IsPrimitive && c2.IsPrimitive) + { + c1FromC2 = true; + c2FromC1 = true; + } + else + { + c1FromC2 = c1.IsAssignableFrom(c2); + c2FromC1 = c2.IsAssignableFrom(c1); + } + + if (c1FromC2 == c2FromC1) + { + return 0; + } + + if (c1FromC2) + { + return 2; + } + else + { + return 1; + } + } + } +} \ No newline at end of file diff --git a/src/Miningcore.Tests/VarDiff/VarDiffManagerTests.cs b/src/Miningcore.Tests/VarDiff/VarDiffManagerTests.cs deleted file mode 100644 index 1a7d89225..000000000 --- a/src/Miningcore.Tests/VarDiff/VarDiffManagerTests.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace Miningcore.Tests.VarDiff; - -public class VarDiffManagerTests : TestBase -{ - /* - private static readonly VarDiffConfig config = new VarDiffConfig - { - RetargetTime = 90, - MinDiff = 1000, - MaxDiff = 10000, - TargetTime = 15, - VariancePercent = 30, - MaxDelta = 1000, - }; - - private static readonly ILogger logger = LogManager.CreateNullLogger(); - private readonly MockMasterClock clock = new MockMasterClock(); - - [Fact] - public void VarDiff_Should_Honor_MaxDelta_When_Adjusting_Up() - { - var vdm = new VarDiffManager(config, clock); - var ctx = new WorkerContextBase {Difficulty = 7500, VarDiff = new VarDiffContext() }; - - var shares = new List { 2, 3, 4 }; - var newDiff = vdm.Update(ctx, shares, string.Empty, logger); - Assert.NotNull(newDiff); - Assert.True(newDiff.Value.EqualsDigitPrecision3(8500)); - } - - [Fact] - public void VarDiff_Should_Honor_MaxDelta_When_Adjusting_Down() - { - var vdm = new VarDiffManager(config, clock); - var ctx = new WorkerContextBase { Difficulty = 7500, VarDiff = new VarDiffContext() }; - - var shares = new List { 2000000000, 3000000000, 4000000000 }; - var newDiff = vdm.Update(ctx, shares, string.Empty, logger); - Assert.NotNull(newDiff); - Assert.True(newDiff.Value.EqualsDigitPrecision3(6500)); - } - - [Fact] - public void VarDiff_Should_Honor_MaxDiff_When_Adjusting_Up() - { - var vdm = new VarDiffManager(config, clock); - var ctx = new WorkerContextBase { Difficulty = 9500, VarDiff = new VarDiffContext() }; - - var shares = new List { 2, 3, 4 }; - var newDiff = vdm.Update(ctx, shares, string.Empty, logger); - Assert.NotNull(newDiff); - Assert.True(newDiff.Value.EqualsDigitPrecision3(10000)); - } - - [Fact] - public void VarDiff_Should_Honor_MinDiff_When_Adjusting_Down() - { - var vdm = new VarDiffManager(config, clock); - var ctx = new WorkerContextBase { Difficulty = 1500, VarDiff = new VarDiffContext() }; - - var shares = new List { 2000000000, 3000000000, 4000000000 }; - var newDiff = vdm.Update(ctx, shares, string.Empty, logger); - Assert.NotNull(newDiff); - Assert.True(newDiff.Value.EqualsDigitPrecision3(1000)); - } - */ -} diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 9529bdf0e..b86506094 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -19,7 +19,6 @@ namespace Miningcore.Blockchain.Bitcoin; public class BitcoinJob { - private const string SymbolRaptoreum = "RTM"; protected IHashAlgorithm blockHasher; protected IMasterClock clock; protected IHashAlgorithm coinbaseHasher; @@ -570,7 +569,7 @@ public void Init(BlockTemplate blockTemplate, string jobId, { masterNodeParameters = BlockTemplate.Extra.SafeExtensionDataAs(); - if(coin.Symbol == SymbolRaptoreum) + if(coin.Symbol == "RTM") { if(masterNodeParameters.Extra?.ContainsKey("smartnode") == true) { diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs index e22708761..691deb33f 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs @@ -386,5 +386,10 @@ await Guard(async () => } } + public double AdjustBlockEffort(double effort) + { + return effort; + } + #endregion // IPayoutHandler } diff --git a/src/Miningcore/Blockchain/Cryptonote/CryptonoteJobManager.cs b/src/Miningcore/Blockchain/Cryptonote/CryptonoteJobManager.cs index b7b3fb672..a574e60ac 100644 --- a/src/Miningcore/Blockchain/Cryptonote/CryptonoteJobManager.cs +++ b/src/Miningcore/Blockchain/Cryptonote/CryptonoteJobManager.cs @@ -330,18 +330,21 @@ public bool ValidateAddress(string address) { case CryptonoteNetworkType.Main: if(addressPrefix != coin.AddressPrefix && + addressPrefix != coin.SubAddressPrefix && addressIntegratedPrefix != coin.AddressPrefixIntegrated) return false; break; case CryptonoteNetworkType.Test: if(addressPrefix != coin.AddressPrefixTestnet && + addressPrefix != coin.SubAddressPrefixTestnet && addressIntegratedPrefix != coin.AddressPrefixIntegratedTestnet) return false; break; case CryptonoteNetworkType.Stage: if(addressPrefix != coin.AddressPrefixStagenet && + addressPrefix != coin.SubAddressPrefixStagenet && addressIntegratedPrefix != coin.AddressPrefixIntegratedStagenet) return false; break; diff --git a/src/Miningcore/Blockchain/Cryptonote/CryptonotePayoutHandler.cs b/src/Miningcore/Blockchain/Cryptonote/CryptonotePayoutHandler.cs index 7d067a4c1..f3cc1105c 100644 --- a/src/Miningcore/Blockchain/Cryptonote/CryptonotePayoutHandler.cs +++ b/src/Miningcore/Blockchain/Cryptonote/CryptonotePayoutHandler.cs @@ -553,5 +553,10 @@ public async Task PayoutAsync(IMiningPool pool, Balance[] balances, Cancellation await rpcClientWallet.ExecuteAsync(logger, CryptonoteWalletCommands.Store, ct); } + public double AdjustBlockEffort(double effort) + { + return effort; + } + #endregion // IPayoutHandler } diff --git a/src/Miningcore/Blockchain/Ergo/ErgoPayoutHandler.cs b/src/Miningcore/Blockchain/Ergo/ErgoPayoutHandler.cs index 237b5be41..b7a1c8552 100644 --- a/src/Miningcore/Blockchain/Ergo/ErgoPayoutHandler.cs +++ b/src/Miningcore/Blockchain/Ergo/ErgoPayoutHandler.cs @@ -284,6 +284,11 @@ public override double AdjustShareDifficulty(double difficulty) return difficulty * ErgoConstants.ShareMultiplier; } + public double AdjustBlockEffort(double effort) + { + return effort * ErgoConstants.ShareMultiplier; + } + public virtual async Task PayoutAsync(IMiningPool pool, Balance[] balances, CancellationToken ct) { Contract.RequiresNonNull(balances); diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs b/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs index 1d1331efa..8fa879900 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs @@ -51,18 +51,20 @@ public class CallistoConstants public enum EthereumNetworkType { - Mainnet = 1, + Main = 1, Ropsten = 3, Callisto = 820, + MainPow = 10001, Unknown = -1, } public enum GethChainType { - Ethereum, + Main, Ropsten, Callisto, + MainPow = 10001, Unknown = -1, } diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumJob.cs b/src/Miningcore/Blockchain/Ethereum/EthereumJob.cs index 29f6bf7c9..b6bea405b 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumJob.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumJob.cs @@ -66,7 +66,7 @@ public async Task ProcessShareAsync(StratumConnection worker, throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex); // get dag for block - var dag = await ethash.GetDagAsync(BlockTemplate.Height, logger, ct); + var dag = await ethash.GetDagAsync(BlockTemplate.Height, logger, CancellationToken.None); // compute if(!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes)) diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs b/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs index 7da95b811..9f8c18992 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs @@ -180,32 +180,30 @@ public async Task ClassifyBlocksAsync(IMiningPool pool, Block[] blocks, .Select(x => x.Response.ToObject()) .FirstOrDefault(x => string.Equals(x.Miner, poolConfig.Address, StringComparison.OrdinalIgnoreCase)); - if(uncle != null) - { - // mature? - if(latestBlockHeight - uncle.Height.Value >= EthereumConstants.MinConfimations) + if(uncle != null) { - var blockHashUncleResponse = await rpcClient.ExecuteAsync(logger, EC.GetBlockByNumber, ct, - new[] { (object) uncle.Height.Value.ToStringHexWithPrefix(), true }); - var blockHashUncle = blockHashUncleResponse.Response.Hash; + // mature? + if(block.Reward == 0) + block.Reward = GetUncleReward(chainType, uncle.Height.Value, blockInfo2.Height.Value); - block.Hash = blockHashUncle; - block.Status = BlockStatus.Confirmed; - block.ConfirmationProgress = 1; - block.Reward = GetUncleReward(chainType, uncle.Height.Value, blockInfo2.Height.Value); - block.BlockHeight = uncle.Height.Value; - block.Type = EthereumConstants.BlockTypeUncle; + if(latestBlockHeight - uncle.Height.Value >= EthereumConstants.MinConfimations) + { + block.Reward = GetUncleReward(chainType, uncle.Height.Value, blockInfo2.Height.Value); + block.Status = BlockStatus.Confirmed; + block.ConfirmationProgress = 1; + block.BlockHeight = uncle.Height.Value; + block.Type = EthereumConstants.BlockTypeUncle; - logger.Info(() => $"[{LogCategory}] Unlocked uncle for block {blockInfo2.Height.Value} at height {uncle.Height.Value} worth {FormatAmount(block.Reward)}"); + logger.Info(() => $"[{LogCategory}] Unlocked uncle for block {blockInfo2.Height.Value} at height {uncle.Height.Value} worth {FormatAmount(block.Reward)}"); - messageBus.NotifyBlockUnlocked(poolConfig.Id, block, coin); - } + messageBus.NotifyBlockUnlocked(poolConfig.Id, block, coin); + } - else - logger.Info(() => $"[{LogCategory}] Got immature matching uncle for block {blockInfo2.Height.Value}. Will try again."); + else + logger.Info(() => $"[{LogCategory}] Got immature matching uncle for block {blockInfo2.Height.Value}. Will try again."); - break; - } + break; + } } } @@ -239,7 +237,7 @@ public async Task PayoutAsync(IMiningPool pool, Balance[] balances, Cancellation // ensure we have peers var infoResponse = await rpcClient.ExecuteAsync(logger, EC.GetPeerCount, ct); - if(networkType == EthereumNetworkType.Mainnet && + if((networkType == EthereumNetworkType.Main || networkType == EthereumNetworkType.MainPow) && (infoResponse.Error != null || string.IsNullOrEmpty(infoResponse.Response) || infoResponse.Response.IntegralFromHex() < EthereumConstants.MinPayoutPeerCount)) { @@ -269,6 +267,11 @@ public async Task PayoutAsync(IMiningPool pool, Balance[] balances, Cancellation NotifyPayoutSuccess(poolConfig.Id, balances, txHashes.ToArray(), null); } + public double AdjustBlockEffort(double effort) + { + return effort; + } + #endregion // IPayoutHandler private async Task FetchBlocks(Dictionary blockCache, CancellationToken ct, params long[] blockHeights) @@ -303,10 +306,10 @@ internal static decimal GetBaseBlockReward(GethChainType chainType, ulong height { switch(chainType) { - case GethChainType.Ethereum: + case GethChainType.Main: + case GethChainType.MainPow: if(height >= EthereumConstants.ConstantinopleHardForkHeight) return EthereumConstants.ConstantinopleReward; - if(height >= EthereumConstants.ByzantiumHardForkHeight) return EthereumConstants.ByzantiumBlockReward; diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumPool.cs b/src/Miningcore/Blockchain/Ethereum/EthereumPool.cs index 4c26c8355..ebcead6ac 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumPool.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumPool.cs @@ -533,11 +533,13 @@ protected override async Task OnVarDiffUpdateAsync(StratumConnection connection, var context = connection.ContextAs(); - if(context.ApplyPendingDifficulty()) + if(context.HasPendingDifficulty) { switch(context.ProtocolVersion) { case 1: + context.ApplyPendingDifficulty(); + await SendWork(context, connection, 0); break; diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumUtils.cs b/src/Miningcore/Blockchain/Ethereum/EthereumUtils.cs index 925b96476..67bf993bb 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumUtils.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumUtils.cs @@ -23,8 +23,8 @@ public static void DetectNetworkAndChain(string netVersionResponse, string gethC chainType = GethChainType.Unknown; } - if(chainType == GethChainType.Ethereum) - chainType = GethChainType.Ethereum; + if(chainType == GethChainType.Main) + chainType = GethChainType.Main; if(chainType == GethChainType.Callisto) chainType = GethChainType.Callisto; diff --git a/src/Miningcore/Configuration/ClusterConfig.cs b/src/Miningcore/Configuration/ClusterConfig.cs index 9e0e0a24e..ffe929a44 100644 --- a/src/Miningcore/Configuration/ClusterConfig.cs +++ b/src/Miningcore/Configuration/ClusterConfig.cs @@ -434,18 +434,36 @@ public partial class CryptonoteCoinTemplate : CoinTemplate /// public ulong AddressPrefix { get; set; } + /// + /// Sub Prefix of a valid sub address + /// See: namespace config -> CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX in src/cryptonote_config.h + /// + public ulong SubAddressPrefix { get; set; } + /// /// Prefix of a valid testnet-address /// See: namespace config -> CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX in src/cryptonote_config.h /// public ulong AddressPrefixTestnet { get; set; } + /// + /// Sub Prefix of a valid testnet-address + /// See: namespace config -> CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX in src/cryptonote_config.h + /// + public ulong SubAddressPrefixTestnet { get; set; } + /// /// Prefix of a valid stagenet-address /// See: namespace config -> CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX in src/cryptonote_config.h /// public ulong AddressPrefixStagenet { get; set; } + /// + /// Sub Prefix of a valid stagenet-address + /// See: namespace config -> CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX in src/cryptonote_config.h + /// + public ulong SubAddressPrefixStagenet { get; set; } + /// /// Prefix of a valid integrated address /// See: namespace testnet -> CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX in src/cryptonote_config.h diff --git a/src/Miningcore/Configuration/CoinTemplateLoader.cs b/src/Miningcore/Configuration/CoinTemplateLoader.cs index 37c94d055..fd25dd382 100644 --- a/src/Miningcore/Configuration/CoinTemplateLoader.cs +++ b/src/Miningcore/Configuration/CoinTemplateLoader.cs @@ -13,39 +13,38 @@ public static class CoinTemplateLoader private static IEnumerable> LoadTemplates(string filename, JsonSerializer serializer, IComponentContext ctx) { - using(var jreader = new JsonTextReader(File.OpenText(filename))) - { - var jo = serializer.Deserialize(jreader); + using var jreader = new JsonTextReader(File.OpenText(filename)); + + var jo = serializer.Deserialize(jreader); - foreach(var o in jo) - { - if(o.Value.Type != JTokenType.Object) - throw new PoolStartupException("Invalid coin-template file: dictionary of coin-templates expected"); + foreach(var o in jo) + { + if(o.Value.Type != JTokenType.Object) + throw new PoolStartupException("Invalid coin-template file: dictionary of coin-templates expected"); - var value = o.Value[nameof(CoinTemplate.Family).ToLower()]; - if(value == null) - throw new PoolStartupException($"Invalid coin-template '{o.Key}': missing 'family' property"); + var value = o.Value[nameof(CoinTemplate.Family).ToLower()]; + if(value == null) + throw new PoolStartupException($"Invalid coin-template '{o.Key}': missing 'family' property"); - var family = value.ToObject(); - var result = (CoinTemplate) o.Value.ToObject(CoinTemplate.Families[family]); + var family = value.ToObject(); + var result = (CoinTemplate) o.Value.ToObject(CoinTemplate.Families[family]); - ctx.InjectProperties(result); + ctx.InjectProperties(result); - // Patch explorer links - if((result.ExplorerBlockLinks == null || result.ExplorerBlockLinks.Count == 0) && - !string.IsNullOrEmpty(result.ExplorerBlockLink)) + // Patch explorer links + if((result.ExplorerBlockLinks == null || result.ExplorerBlockLinks.Count == 0) && + !string.IsNullOrEmpty(result.ExplorerBlockLink)) + { + result.ExplorerBlockLinks = new Dictionary { - result.ExplorerBlockLinks = new Dictionary - { - {"block", result.ExplorerBlockLink} - }; - } + {"block", result.ExplorerBlockLink} + }; + } - // Record the source of the template - result.Source = filename; + // Record the source of the template + result.Source = filename; - yield return KeyValuePair.Create(o.Key, result); - } + yield return KeyValuePair.Create(o.Key, result); } } diff --git a/src/Miningcore/Crypto/Hashing/Ethash/EthashFull.cs b/src/Miningcore/Crypto/Hashing/Ethash/EthashFull.cs index 7b8ee33a0..a625010a5 100644 --- a/src/Miningcore/Crypto/Hashing/Ethash/EthashFull.cs +++ b/src/Miningcore/Crypto/Hashing/Ethash/EthashFull.cs @@ -82,7 +82,9 @@ public async Task GetDagAsync(ulong block, ILogger logger, CancellationToke result.LastUsed = DateTime.Now; } + // get/generate current one await result.GenerateAsync(dagDir, logger, ct); + return result; } } diff --git a/src/Miningcore/Extensions/ArrayExtensions.cs b/src/Miningcore/Extensions/ArrayExtensions.cs index ad628ceaa..60c4851aa 100644 --- a/src/Miningcore/Extensions/ArrayExtensions.cs +++ b/src/Miningcore/Extensions/ArrayExtensions.cs @@ -45,48 +45,11 @@ public static string ToHexString(this Span value, bool withPrefix = false) return ToHexString(value, null, null, withPrefix); } - public static string ToHexString(this ReadOnlySpan value, bool withPrefix = false) - { - return ToHexString(value, null, null, withPrefix); - } public static string ToByteArrayBase64(this string value) { return Convert.ToBase64String(Encoding.UTF8.GetBytes(value)); } - public static string ToHexString(this ReadOnlySpan value, int? off, int? len, bool withPrefix = false) - { - if(value == null || value.Length == 0) - return string.Empty; - - var length = len ?? value.Length; - var bufferSize = length * 2; - - if(withPrefix) - bufferSize += 2; - - Span buffer = stackalloc char[bufferSize]; - - var offset = 0; - - if(withPrefix) - { - buffer[offset++] = '0'; - buffer[offset++] = 'x'; - } - - var start = off ?? 0; - - for(var i = start; i < length; i++) - { - var hex = HexStringTable[value[i]]; - buffer[offset + i * 2 + 0] = hex[0]; - buffer[offset + i * 2 + 1] = hex[1]; - } - - return new string(buffer); - } - public static string ToHexString(this Span value, int? off, int? len, bool withPrefix = false) { if(value == null || value.Length == 0) @@ -121,11 +84,6 @@ public static string ToHexString(this Span value, int? off, int? len, bool } - public static string ToHexString(this Memory value, bool withPrefix = false) - { - return ToHexString(value.Span, null, null, withPrefix); - } - public static byte[] ReverseByteOrder(this byte[] bytes) { using(var stream = new MemoryStream()) diff --git a/src/Miningcore/Mining/WorkerContextBase.cs b/src/Miningcore/Mining/WorkerContextBase.cs index 69d4abe1e..8ec8137e1 100644 --- a/src/Miningcore/Mining/WorkerContextBase.cs +++ b/src/Miningcore/Mining/WorkerContextBase.cs @@ -71,6 +71,8 @@ public void EnqueueNewDifficulty(double difficulty) pendingDifficulty = difficulty; } + public bool HasPendingDifficulty => pendingDifficulty.HasValue; + public bool ApplyPendingDifficulty() { if(pendingDifficulty.HasValue) diff --git a/src/Miningcore/Miningcore.csproj b/src/Miningcore/Miningcore.csproj index 2c9eee67a..8cbdf18b5 100644 --- a/src/Miningcore/Miningcore.csproj +++ b/src/Miningcore/Miningcore.csproj @@ -44,28 +44,28 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - + + + - + @@ -74,8 +74,8 @@ - - + + diff --git a/src/Miningcore/Native/Cryptonote.cs b/src/Miningcore/Native/Cryptonote.cs index cdacd0b3e..e3767c467 100644 --- a/src/Miningcore/Native/Cryptonote.cs +++ b/src/Miningcore/Native/Cryptonote.cs @@ -75,7 +75,9 @@ public static ulong DecodeAddress(string address) { Contract.Requires(!string.IsNullOrEmpty(address)); - var data = Encoding.UTF8.GetBytes(address); + var cb = Encoding.UTF8.GetByteCount(address); + Span data = stackalloc byte[cb]; + Encoding.UTF8.GetBytes(address, data); fixed (byte* input = data) { @@ -87,7 +89,9 @@ public static ulong DecodeIntegratedAddress(string address) { Contract.Requires(!string.IsNullOrEmpty(address)); - var data = Encoding.UTF8.GetBytes(address); + var cb = Encoding.UTF8.GetByteCount(address); + Span data = stackalloc byte[cb]; + Encoding.UTF8.GetBytes(address, data); fixed (byte* input = data) { diff --git a/src/Miningcore/Payments/Abstractions.cs b/src/Miningcore/Payments/Abstractions.cs index 9d65c543f..e273af373 100644 --- a/src/Miningcore/Payments/Abstractions.cs +++ b/src/Miningcore/Payments/Abstractions.cs @@ -13,6 +13,7 @@ public interface IPayoutHandler Task UpdateBlockRewardBalancesAsync(IDbConnection con, IDbTransaction tx, IMiningPool pool, Block block, CancellationToken ct); Task PayoutAsync(IMiningPool pool, Balance[] balances, CancellationToken ct); double AdjustShareDifficulty(double difficulty); + double AdjustBlockEffort(double effort); string FormatAmount(decimal amount); } diff --git a/src/Miningcore/Payments/PayoutManager.cs b/src/Miningcore/Payments/PayoutManager.cs index c8b0253cc..727ba6ed0 100644 --- a/src/Miningcore/Payments/PayoutManager.cs +++ b/src/Miningcore/Payments/PayoutManager.cs @@ -239,6 +239,9 @@ private async Task CalculateBlockEffortAsync(IMiningPool pool, PoolConfig poolCo block.Effort = await cf.Run(con => shareRepo.GetEffectiveAccumulatedShareDifficultyBetweenAsync(con, pool.Config.Id, from, to, ct)); + + if(block.Effort.HasValue) + block.Effort = handler.AdjustBlockEffort(block.Effort.Value); } protected override async Task ExecuteAsync(CancellationToken ct) diff --git a/src/Miningcore/Program.cs b/src/Miningcore/Program.cs index bf435f3ab..cb5581159 100644 --- a/src/Miningcore/Program.cs +++ b/src/Miningcore/Program.cs @@ -879,7 +879,7 @@ private static void ConfigurePostgres(PostgresConfig pgConfig, ContainerBuilder connectionString.Append($"SSL Password={pgConfig.TlsPassword};"); } - connectionString.Append($"CommandTimeout={pgConfig.CommandTimeout ?? 120};"); + connectionString.Append($"CommandTimeout={pgConfig.CommandTimeout ?? 300};"); logger.Debug(()=> $"Using postgres connection string: {connectionString}"); diff --git a/src/Miningcore/Stratum/StratumConnection.cs b/src/Miningcore/Stratum/StratumConnection.cs index 7d6627b97..368ac81d4 100644 --- a/src/Miningcore/Stratum/StratumConnection.cs +++ b/src/Miningcore/Stratum/StratumConnection.cs @@ -365,16 +365,15 @@ private async Task ProcessRequestAsync( Func onRequestAsync, ReadOnlySequence lineBuffer) { - using(var reader = new JsonTextReader(new StreamReader(new MemoryStream(lineBuffer.ToArray()), StratumConstants.Encoding))) - { - var request = serializer.Deserialize(reader); + await using var stream = rmsm.GetStream(nameof(StratumConnection), lineBuffer.ToSpan()) as RecyclableMemoryStream; + using var reader = new JsonTextReader(new StreamReader(stream!, StratumConstants.Encoding)); - if(request == null) - throw new JsonException("Unable to deserialize request"); + var request = serializer.Deserialize(reader); - // Dispatch - await onRequestAsync(this, request, ct); - } + if(request == null) + throw new JsonException("Unable to deserialize request"); + + await onRequestAsync(this, request, ct); } /// diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index bdc0af224..62a704da4 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -32,7 +32,7 @@ "actinium": { "name": "Actinium", "symbol": "ACM", - "family": "bitcoin", + "family": "bitcoin", "website": "https://actinium.org/", "market": "", "twitter": "https://twitter.com/ActiniumCrypto", @@ -57,7 +57,7 @@ "alpscoin": { "name": "Alpenstars", "symbol": "ALPS", - "family": "bitcoin", + "family": "bitcoin", "website": "https://axerunners.com/", "market": "", "twitter": "https://twitter.com/search?q=$axe", @@ -317,7 +317,7 @@ "explorerTxLink": "http://explorer.kriptokyng.com:3001/tx/{0}", "explorerAccountLink": "http://explorer.kriptokyng.com:3001/address/{0}" }, - + "bitcoin": { "name": "Bitcoin", "canonicalName": "Bitcoin", @@ -548,7 +548,7 @@ "explorerTxLink": "https://blocks.butcoin.tech/tx/{0}", "explorerAccountLink": "https://blocks.butcoin.tech/address/{0}" }, - + "butkoin-scrypt": { "name": "ButKoin Scrypt", "canonicalName": "ButKoin", @@ -614,7 +614,7 @@ "explorerTxLink": "https://blocks.butcoin.tech/tx/{0}", "explorerAccountLink": "https://blocks.butcoin.tech/address/{0}" }, - + "cannabiscoin": { "name": "Cannabiscoin", "canonicalName": "Cannabiscoin", @@ -979,7 +979,7 @@ "explorerTxLink": "https://chainz.cryptoid.info/dem/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dem/address.dws?{0}.htm" }, - + "emrals": { "name": "Emrals", "canonicalName": "Emrals", @@ -1462,7 +1462,7 @@ "explorerAccountLink": "http://157.245.248.32:3000/#/address/{0}" }, - + "lanacoin": { "name": "Lanacoin", "canonicalName": "Lana", @@ -1994,7 +1994,7 @@ "explorerTxLink": "hhttps://eksplorator.polcoin.pl/tx/{0}", "explorerAccountLink": "https://eksplorator.polcoin.pl/address/{0}" }, - + "profithunters": { "name": "Profit Hunters", "symbol": "PHC", @@ -2507,7 +2507,7 @@ "explorerTxLink": "https://explore.susukino.com/tx/{0}", "explorerAccountLink": "https://explore.susukino.com/address/{0}" }, - + "swippcoin": { "name": "Swipp", "symbol": "SWP", @@ -2721,7 +2721,7 @@ "explorerTxLink": "https://explorer.tiltcoin.io/tx/{0}", "explorerAccountLink": "https://explorer.tiltcoin.io/address/{0}" }, - + "veco": { "name": "Veco", "canonicalName": "Veco", @@ -2774,7 +2774,7 @@ "explorerTxLink": "https://chainz.cryptoid.info/vls/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/vls/address.dws?{0}.htm" }, - + "veles-scrypt": { "name": "Veles Scrypt", "canonicalName": "Veles", @@ -3228,7 +3228,7 @@ "explorerTxLink": "https://explorer.yerbas.org/tx/{0}", "explorerAccountLink": "https://explorer.yerbas.org/address/{0}" }, - + "zetacoin": { "name": "Zetacoin", "canonicalName": "Zetacoin", @@ -3994,6 +3994,9 @@ "addressPrefixIntegrated": 19, "addressPrefixIntegratedStagenet": 25, "addressPrefixIntegratedTestnet": 54, + "subAddressPrefix": 42, + "subAddressPrefixTestnet": 63, + "subAddressPrefixStagenet": 36, "explorerBlockLink": "https://www.exploremonero.com/block/$height$", "explorerTxLink": "https://www.exploremonero.com/transaction/{0}" }, diff --git a/src/Native/libcryptonote/Makefile b/src/Native/libcryptonote/Makefile index 55f3063f4..c40fb1833 100644 --- a/src/Native/libcryptonote/Makefile +++ b/src/Native/libcryptonote/Makefile @@ -1,17 +1,20 @@ INC_DIRS = -I. -Icontrib/epee/include -CFLAGS = -g -Wall -c -fPIC -O2 $(CPU_FLAGS) $(INC_DIRS) -Wno-strict-aliasing -CXXFLAGS = -Wall -Wno-unused-function -fPIC -fpermissive -std=c++0x -fexceptions -frtti -O2 -g $(CPU_FLAGS) $(INC_DIRS) +CFLAGS = $(CPU_FLAGS) $(INC_DIRS) -fno-exceptions -std=gnu11 -march=native -fPIC -DNDEBUG -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2 +CXXFLAGS = $(CPU_FLAGS) $(INC_DIRS) -fexceptions -frtti -std=gnu++11 -march=native -fPIC -DNDEBUG -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2 LDFLAGS = -shared LDLIBS = -lboost_system -lboost_date_time TARGET = libcryptonote.so -OBJECTS = contrib/epee/src/hex.o \ - common/base58.o crypto/aesb.o crypto/blake256.o crypto/chacha.o \ - contrib/epee/src/memwipe.o \ - crypto/crypto-ops-data.o crypto/crypto-ops.o crypto/crypto.o crypto/groestl.o crypto/hash-extra-blake.o \ - crypto/hash-extra-groestl.o crypto/hash-extra-jh.o crypto/hash-extra-skein.o crypto/hash.o crypto/jh.o \ - crypto/keccak.o crypto/oaes_lib.o crypto/random.o crypto/skein.o crypto/tree-hash.o \ - crypto/slow-hash-lite.o cryptonote_basic/cryptonote_format_utils.o exports.o +OBJECTS = exports.o \ + cryptonote_core/cryptonote_format_utils.o \ + offshore/pricing_record.o \ + crypto/tree-hash.o \ + crypto/crypto.o \ + crypto/crypto-ops.o \ + crypto/crypto-ops-data.o \ + crypto/hash.o \ + crypto/keccak.o \ + common/base58.o all: $(TARGET) diff --git a/src/Native/libcryptonote/Makefile.MSys2 b/src/Native/libcryptonote/Makefile.MSys2 index 87d3ee715..35b9cfb7b 100644 --- a/src/Native/libcryptonote/Makefile.MSys2 +++ b/src/Native/libcryptonote/Makefile.MSys2 @@ -1,18 +1,26 @@ +# Makefile for MSYS2 MINGW64 (Windows) +# pacman -S mingw-w64-x86_64-boost mingw-w64-x86_64-libsodium mingw-w64-x86_64-openssl + CC = gcc -INC_DIRS = -I. -Icontrib/epee/include -CFLAGS = -Wall -c -fPIC -maes -O2 $(INC_DIRS) -CXXFLAGS = -Wall -fPIC -fpermissive -std=c++0x -fexceptions -frtti -O2 $(INC_DIRS) -LDFLAGS = -shared -static-libgcc -static-libstdc++ -static -LDLIBS = -lboost_system-mt -lboost_date_time-mt +INC_DIRS = -I. -Icontrib/epee/include -I/mingw64/include +LIBRARY_DIRS = -L/mingw64/lib +CFLAGS = $(CPU_FLAGS) $(INC_DIRS) -fno-exceptions -std=gnu11 -march=native -fPIC -DNDEBUG -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2 +CXXFLAGS = $(CPU_FLAGS) $(INC_DIRS) -fexceptions -frtti -std=gnu++11 -march=native -fPIC -DNDEBUG -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2 +LDFLAGS = -shared -static-libgcc -static-libstdc++ -static $(LIBRARY_DIRS) +LDLIBS = -lboost_system-mt -lboost_date_time-mt -lssl -lsodium -lcrypto -lws2_32 TARGET = libcryptonote.dll -OBJECTS = contrib/epee/src/hex.o \ - common/base58.o crypto/aesb.o crypto/blake256.o crypto/chacha.o \ - contrib/epee/src/memwipe.o \ - crypto/crypto-ops-data.o crypto/crypto-ops.o crypto/crypto.o crypto/groestl.o crypto/hash-extra-blake.o \ - crypto/hash-extra-groestl.o crypto/hash-extra-jh.o crypto/hash-extra-skein.o crypto/hash.o crypto/jh.o \ - crypto/keccak.o crypto/oaes_lib.o crypto/random.o crypto/skein.o crypto/tree-hash.o \ - crypto/slow-hash-lite.o cryptonote_basic/cryptonote_format_utils.o exports.o +OBJECTS = exports.o \ + cryptonote_core/cryptonote_format_utils.o \ + offshore/pricing_record.o \ + crypto/tree-hash.o \ + crypto/crypto.o \ + crypto/crypto-ops.o \ + crypto/crypto-ops-data.o \ + crypto/hash.o \ + crypto/keccak.o \ + common/base58.o \ + mingw_stubs.o all: $(TARGET) diff --git a/src/Native/libcryptonote/common/base58.cpp b/src/Native/libcryptonote/common/base58.cpp index 75556cad9..ac1bf4b29 100644 --- a/src/Native/libcryptonote/common/base58.cpp +++ b/src/Native/libcryptonote/common/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -36,7 +36,6 @@ #include "crypto/hash.h" #include "int-util.h" -#include "util.h" #include "varint.h" namespace tools @@ -109,20 +108,8 @@ namespace tools assert(1 <= size && size <= sizeof(uint64_t)); uint64_t res = 0; - switch (9 - size) - { - case 1: res |= *data++; /* FALLTHRU */ - case 2: res <<= 8; res |= *data++; /* FALLTHRU */ - case 3: res <<= 8; res |= *data++; /* FALLTHRU */ - case 4: res <<= 8; res |= *data++; /* FALLTHRU */ - case 5: res <<= 8; res |= *data++; /* FALLTHRU */ - case 6: res <<= 8; res |= *data++; /* FALLTHRU */ - case 7: res <<= 8; res |= *data++; /* FALLTHRU */ - case 8: res <<= 8; res |= *data; break; - default: assert(false); - } - - return res; + memcpy(reinterpret_cast(&res) + sizeof(uint64_t) - size, data, size); + return SWAP64BE(res); } void uint_64_to_8be(uint64_t num, size_t size, uint8_t* data) @@ -247,7 +234,7 @@ namespace tools return encode(buf); } - bool decode_addr(std::string addr, uint64_t& tag, std::string& data) + bool decode_addr(const std::string &addr, uint64_t& tag, std::string& data) { std::string addr_data; bool r = decode(addr, addr_data); diff --git a/src/Native/libcryptonote/common/base58.h b/src/Native/libcryptonote/common/base58.h index 02ca96956..6bf2c3bb7 100644 --- a/src/Native/libcryptonote/common/base58.h +++ b/src/Native/libcryptonote/common/base58.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -41,6 +41,6 @@ namespace tools bool decode(const std::string& enc, std::string& data); std::string encode_addr(uint64_t tag, const std::string& data); - bool decode_addr(std::string addr, uint64_t& tag, std::string& data); + bool decode_addr(const std::string &addr, uint64_t& tag, std::string& data); } } diff --git a/src/Native/libcryptonote/common/int-util.h b/src/Native/libcryptonote/common/int-util.h index 3bcc085e2..db9e9bea7 100644 --- a/src/Native/libcryptonote/common/int-util.h +++ b/src/Native/libcryptonote/common/int-util.h @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once @@ -34,18 +8,7 @@ #include #include #include - -#ifndef _MSC_VER #include -#endif - -#if defined(__ANDROID__) -#include -#endif - -#if defined(__sun) && defined(__SVR4) -#include -#endif #if defined(_MSC_VER) #include @@ -148,25 +111,15 @@ static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uin static inline uint32_t ident32(uint32_t x) { return x; } static inline uint64_t ident64(uint64_t x) { return x; } -#ifndef __OpenBSD__ -# if defined(__ANDROID__) && defined(__swap32) && !defined(swap32) -# define swap32 __swap32 -# elif !defined(swap32) static inline uint32_t swap32(uint32_t x) { x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8); return (x << 16) | (x >> 16); } -# endif -# if defined(__ANDROID__) && defined(__swap64) && !defined(swap64) -# define swap64 __swap64 -# elif !defined(swap64) static inline uint64_t swap64(uint64_t x) { x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8); x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16); return (x << 32) | (x >> 32); } -# endif -#endif /* __OpenBSD__ */ #if defined(__GNUC__) #define UNUSED __attribute__((unused)) @@ -209,12 +162,6 @@ static inline void memcpy_swap64(void *dst, const void *src, size_t n) { } } -#ifdef _MSC_VER -# define LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -# define BYTE_ORDER LITTLE_ENDIAN -#endif - #if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"); #endif diff --git a/src/Native/libcryptonote/common/pod-class.h b/src/Native/libcryptonote/common/pod-class.h index 5f6709eef..c07edb208 100644 --- a/src/Native/libcryptonote/common/pod-class.h +++ b/src/Native/libcryptonote/common/pod-class.h @@ -1,43 +1,11 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once -// FIXME: Why is this ifdef needed? Hopefully making it struct won't break things. - -/* #if defined(_MSC_VER) #define POD_CLASS struct #else #define POD_CLASS class #endif -*/ - -#define POD_CLASS struct diff --git a/src/Native/libcryptonote/common/util.h b/src/Native/libcryptonote/common/util.h index d3ba47a4f..8a1f4b041 100644 --- a/src/Native/libcryptonote/common/util.h +++ b/src/Native/libcryptonote/common/util.h @@ -1,147 +1,37 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once -#include -#include +#include #include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include "windows.h" -#include "misc_log_ex.h" -#endif +#include +#include "crypto/crypto.h" #include "crypto/hash.h" +#include "misc_language.h" +#include "p2p/p2p_protocol_defs.h" -/*! \brief Various Tools - * - * - * - */ namespace tools { - //! Functional class for closing C file handles. - struct close_file - { - void operator()(std::FILE* handle) const noexcept - { - if (handle) - { - std::fclose(handle); - } - } - }; - - //! A file restricted to process owner AND process. Deletes file on destruction. - class private_file { - std::unique_ptr m_handle; - std::string m_filename; - - private_file(std::FILE* handle, std::string&& filename) noexcept; - public: - - //! `handle() == nullptr && filename.empty()`. - private_file() noexcept; - - /*! \return File only readable by owner and only used by this process - OR `private_file{}` on error. */ - static private_file create(std::string filename); - - private_file(private_file&&) = default; - private_file& operator=(private_file&&) = default; - - //! Deletes `filename()` and closes `handle()`. - ~private_file() noexcept; - - std::FILE* handle() const noexcept { return m_handle.get(); } - const std::string& filename() const noexcept { return m_filename; } - }; - - /*! \brief Returns the default data directory. - * - * \details Windows < Vista: C:\\Documents and Settings\\Username\\Application Data\\CRYPTONOTE_NAME - * - * Windows >= Vista: C:\\Users\\Username\\AppData\\Roaming\\CRYPTONOTE_NAME - * - * Mac: ~/Library/Application Support/CRYPTONOTE_NAME - * - * Unix: ~/.CRYPTONOTE_NAME - */ std::string get_default_data_dir(); - -#ifdef WIN32 - /** - * @brief - * - * @param nfolder - * @param iscreate - * - * @return - */ - std::string get_special_folder_path(int nfolder, bool iscreate); -#endif - - /*! \brief Returns the OS version string - * - * \details This is a wrapper around the primitives - * get_windows_version_display_string() and - * get_nix_version_display_string() - */ std::string get_os_version_string(); - - /*! \brief creates directories for a path - * - * wrapper around boost::filesyste::create_directories. - * (ensure-directory-exists): greenspun's tenth rule in action! - */ bool create_directories_if_necessary(const std::string& path); - /*! \brief std::rename wrapper for nix and something strange for windows. - */ std::error_code replace_file(const std::string& replacement_name, const std::string& replaced_name); - bool sanitize_locale(); + inline crypto::hash get_proof_of_trust_hash(const nodetool::proof_of_trust& pot) + { + std::string s; + s.append(reinterpret_cast(&pot.peer_id), sizeof(pot.peer_id)); + s.append(reinterpret_cast(&pot.time), sizeof(pot.time)); + return crypto::cn_fast_hash(s.data(), s.size()); + } - bool on_startup(); - /*! \brief Defines a signal handler for win32 and *nix - */ class signal_handler { public: - /*! \brief installs a signal handler */ template static bool install(T t) { @@ -153,14 +43,8 @@ namespace tools } return r; #else - static struct sigaction sa; - memset(&sa, 0, sizeof(struct sigaction)); - sa.sa_handler = posix_handler; - sa.sa_flags = 0; - /* Only blocks SIGINT, SIGTERM and SIGPIPE */ - sigaction(SIGINT, &sa, NULL); + signal(SIGINT, posix_handler); signal(SIGTERM, posix_handler); - signal(SIGPIPE, SIG_IGN); m_handler = t; return true; #endif @@ -168,48 +52,35 @@ namespace tools private: #if defined(WIN32) - /*! \brief Handler for win */ static BOOL WINAPI win_handler(DWORD type) { if (CTRL_C_EVENT == type || CTRL_BREAK_EVENT == type) { - handle_signal(type); + handle_signal(); + return TRUE; } else { - MGINFO_RED("Got control signal " << type << ". Exiting without saving..."); + LOG_PRINT_RED_L0("Got control signal " << type << ". Exiting without saving..."); return FALSE; } return TRUE; } #else - /*! \brief handler for NIX */ - static void posix_handler(int type) + static void posix_handler(int /*type*/) { - handle_signal(type); + handle_signal(); } #endif - /*! \brief calles m_handler */ - static void handle_signal(int type) + static void handle_signal() { - static boost::mutex m_mutex; - boost::unique_lock lock(m_mutex); - m_handler(type); + static std::mutex m_mutex; + std::unique_lock lock(m_mutex); + m_handler(); } - /*! \brief where the installed handler is stored */ - static std::function m_handler; + private: + static std::function m_handler; }; - - void set_strict_default_file_permissions(bool strict); - - void set_max_concurrency(unsigned n); - unsigned get_max_concurrency(); - - bool is_local_address(const std::string &address); - int vercmp(const char *v0, const char *v1); // returns < 0, 0, > 0, similar to strcmp, but more human friendly than lexical - does not attempt to validate - - bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash); - bool sha256sum(const std::string &filename, crypto::hash &hash); } diff --git a/src/Native/libcryptonote/common/varint.h b/src/Native/libcryptonote/common/varint.h index 151d13dbf..e62470fdf 100644 --- a/src/Native/libcryptonote/common/varint.h +++ b/src/Native/libcryptonote/common/varint.h @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once @@ -35,94 +9,54 @@ #include #include #include -/*! \file varint.h - * \brief provides the implementation of varint's - * - * The representation of varints is rather odd. The first bit of each - * octet is significant, it represents wheter there is another part - * waiting to be read. For example 0x8002 would return 0x200, even - * though 0x02 does not have its msb set. The actual way they are read - * is as follows: Strip the msb of each byte, then from left to right, - * read in what remains, placing it in reverse, into the buffer. Thus, - * the following bit stream: 0xff02 would return 0x027f. 0xff turns - * into 0x7f, is placed on the beginning of the buffer, then 0x02 is - * unchanged, since its msb is not set, and placed at the end of the - * buffer. - */ namespace tools { - /*! \brief Error codes for varint - */ - enum { - /* \brief Represents the overflow error */ - EVARINT_OVERFLOW = -1, - /* \brief Represents a non conical represnetation */ - EVARINT_REPRESENT = -2, - }; - - /*! \brief writes a varint to a stream. - */ - template - /* Requires T to be both an integral type and unsigned, should be a compile error if it is not */ - typename std::enable_if::value && std::is_unsigned::value, void>::type - write_varint(OutputIt &&dest, T i) { - /* Make sure that there is one after this */ - while (i >= 0x80) { - *dest = (static_cast(i) & 0x7f) | 0x80; - ++dest; - i >>= 7; /* I should be in multiples of 7, this should just get the next part */ + template + typename std::enable_if::value && std::is_unsigned::value, void>::type + write_varint(OutputIt &&dest, T i) { + while (i >= 0x80) { + *dest++ = (static_cast(i) & 0x7f) | 0x80; + i >>= 7; + } + *dest++ = static_cast(i); } - /* writes the last one to dest */ - *dest = static_cast(i); - dest++; /* Seems kinda pointless... */ - } - /*! \brief Returns the string that represents the varint - */ - template - std::string get_varint_data(const T& v) + template + std::string get_varint_data(const t_type& v) { std::stringstream ss; write_varint(std::ostreambuf_iterator(ss), v); return ss.str(); } - /*! \brief reads in the varint that is pointed to by InputIt into write - */ - template - typename std::enable_if::value && std::is_unsigned::value && 0 <= bits && bits <= std::numeric_limits::digits, int>::type - read_varint(InputIt &&first, InputIt &&last, T &write) { - int read = 0; - write = 0; - for (int shift = 0;; shift += 7) { - if (first == last) { - return read; - } - unsigned char byte = *first; - ++first; - ++read; - if (shift + 7 >= bits && byte >= 1 << (bits - shift)) { - return EVARINT_OVERFLOW; - } - if (byte == 0 && shift != 0) { - return EVARINT_REPRESENT; - } - - write |= static_cast(byte & 0x7f) << shift; /* Does the actually placing into write, stripping the first bit */ - /* If there is no next */ - if ((byte & 0x80) == 0) { - break; - } + template + typename std::enable_if::value && std::is_unsigned::value && 0 <= bits && bits <= std::numeric_limits::digits, int>::type + read_varint(InputIt &&first, InputIt &&last, T &i) { + int read = 0; + i = 0; + for (int shift = 0;; shift += 7) { + if (first == last) { + return read; // End of input. + } + unsigned char byte = *first++; + ++read; + if (shift + 7 >= bits && byte >= 1 << (bits - shift)) { + return -1; // Overflow. + } + if (byte == 0 && shift != 0) { + return -2; // Non-canonical representation. + } + i |= static_cast(byte & 0x7f) << shift; + if ((byte & 0x80) == 0) { + break; + } + } + return read; } - return read; - } - /*! \brief Wrapper around the other read_varint, - * Sets template parameters for you. - */ - template + template int read_varint(InputIt &&first, InputIt &&last, T &i) { - return read_varint::digits, InputIt, T>(std::move(first), std::move(last), i); - } + return read_varint::digits, InputIt, T>(std::move(first), std::move(last), i); + } } diff --git a/src/Native/libcryptonote/contrib/epee/LICENSE.txt b/src/Native/libcryptonote/contrib/epee/LICENSE.txt new file mode 100644 index 000000000..4a6b529e5 --- /dev/null +++ b/src/Native/libcryptonote/contrib/epee/LICENSE.txt @@ -0,0 +1,25 @@ +Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Andrey N. Sabelnikov nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Andrey N. Sabelnikov BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/Native/libcryptonote/contrib/epee/README.md b/src/Native/libcryptonote/contrib/epee/README.md new file mode 100644 index 000000000..a69884f57 --- /dev/null +++ b/src/Native/libcryptonote/contrib/epee/README.md @@ -0,0 +1 @@ +epee - is a small library of helpers, wrappers, tools and and so on, used to make my life easier. \ No newline at end of file diff --git a/src/Native/libcryptonote/contrib/epee/include/ado_db_helper.h b/src/Native/libcryptonote/contrib/epee/include/ado_db_helper.h deleted file mode 100644 index ed4e5b30f..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/ado_db_helper.h +++ /dev/null @@ -1,1095 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _DB_ADO_HELPER_H_ -#define _DB_ADO_HELPER_H_ - -#include -#include -#include "string_coding.h" -#include "math_helper.h" -#include "file_io_utils.h" -#include "global_stream_operators.h" - - - -#define BEGIN_TRY_SECTION() try { - -#define CATCH_TRY_SECTION(ret_val) CATCH_TRY_SECTION_MESS(ret_val, "") - -#define CATCH_TRY_SECTION_MESS(ret_val, mess_where) }\ - catch(const std::exception&ex)\ - {\ - LOG_PRINT_J("DB_ERROR: " << ex.what(), LOG_LEVEL_0);\ - return ret_val;\ - }\ - catch(const _com_error& comm_err)\ - {\ - const TCHAR* pstr = comm_err.Description();\ - std::string descr = string_encoding::convert_to_ansii(pstr?pstr:TEXT(""));\ - const TCHAR* pmessage = comm_err.ErrorMessage();\ - pstr = comm_err.Source();\ - std::string source = string_encoding::convert_to_ansii(pstr?pstr:TEXT(""));\ - LOG_PRINT_J("COM_ERROR " << mess_where << ":\n\tDescriprion:" << descr << ", \n\t Message: " << string_encoding::convert_to_ansii(pmessage) << "\n\t Source: " << source, LOG_LEVEL_0);\ - return ret_val;\ - }\ - catch(...)\ - {\ - LOG_PRINT_J("..._ERROR: Unknown error.", LOG_LEVEL_0);\ - return ret_val;\ - }\ - -namespace epee -{ -namespace ado_db_helper -{ - - struct profile_entry - { - profile_entry():m_call_count(0), m_max_time(0), m_min_time(0) - {} - //std::string m_sql; - math_helper::average m_avrg; - size_t m_call_count; - DWORD m_max_time; - DWORD m_min_time; - }; - - class profiler_manager - { - public: - typedef std::map sqls_map; - profiler_manager(){} - - static bool sort_by_timing(const sqls_map::iterator& a, const sqls_map::iterator& b) - { - return a->second.m_avrg.get_avg() > b->second.m_avrg.get_avg(); - } - - bool flush_log(const std::string& path) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - std::stringstream strm; - strm << "SQL PROFILE:\r\nStatements: " << m_sqls.size() << "\r\n"; - std::list m_sorted_by_time_sqls; - for(std::map::iterator it = m_sqls.begin();it!=m_sqls.end();it++) - m_sorted_by_time_sqls.push_back(it); - - m_sorted_by_time_sqls.sort(sort_by_timing); - - for(std::list::iterator it = m_sorted_by_time_sqls.begin();it!=m_sorted_by_time_sqls.end();it++) - { - strm << "---------------------------------------------------------------------------------------------------------\r\nSQL: " << (*it)->first << "\r\n"; - strm << "\tavrg: " << (*it)->second.m_avrg.get_avg() << "\r\n\tmax: " << (*it)->second.m_max_time << "\r\n\tmin: " << (*it)->second.m_min_time << "\r\n\tcount: " << (*it)->second.m_call_count << "\r\n"; - } - - return file_io_utils::save_string_to_file(path.c_str(), strm.str()); - CRITICAL_REGION_END(); - } - - bool push_entry(const std::string sql, DWORD time) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - profile_entry& entry_ref = m_sqls[sql]; - entry_ref.m_avrg.push(time); - entry_ref.m_call_count++; - if(time > entry_ref.m_max_time) entry_ref.m_max_time = time; - if(time < entry_ref.m_min_time || entry_ref.m_min_time == 0) entry_ref.m_min_time = time; - CRITICAL_REGION_END(); - return true; - } - - bool get_entry_avarege(const std::string sql, DWORD& time) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - sqls_map::iterator it = m_sqls.find(sql); - if(it==m_sqls.end()) - return false; - - time = static_cast(it->second.m_avrg.get_avg()); - CRITICAL_REGION_END(); - return true; - } - - private: - - sqls_map m_sqls; - critical_section m_sqls_lock; - }; -inline - profiler_manager* get_set_profiler(bool need_to_set = false, profiler_manager** pprofiler = NULL) - { - static profiler_manager* pmanager = NULL; - if(need_to_set) - pmanager = *pprofiler; - //else - // *pprofiler = pmanager; - - return pmanager; - } -inline - bool init() // INIT and DEINIT are NOT THREAD SAFE operations, CALL it BEFOR u start using this wrapper. - { - profiler_manager* pmanager = new profiler_manager(); - get_set_profiler(true, &pmanager); - return true; - } -inline - bool deinit() - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - delete pmanager; - return true; - } - inline bool push_timing(const std::string sql, DWORD time) - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - return pmanager->push_entry(sql, time); - return true; - } - - inline bool flush_profiler(const std::string path) - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - return pmanager->flush_log(path); - return true; - } - - class timing_guard - { - DWORD m_start_time; - std::string m_sql; - - public: - timing_guard(const std::string& sql) - { - m_start_time = ::GetTickCount(); - m_sql = sql; - } - - ~timing_guard() - { - DWORD timing = ::GetTickCount() - m_start_time; - push_timing(m_sql, timing); - } - }; -#define PROFILE_SQL(sql) timing_guard local_timing(sql) - - - typedef std::vector > table; - - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::string& parametr) - { - _variant_t param(parametr.c_str()); - ADODB::ADO_LONGPTR size = sizeof(parametr); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("", ADODB::adVarChar, ADODB::adParamInput, static_cast(parametr.size()+1), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::wstring& parametr) - { - _variant_t param(parametr.c_str()); - ADODB::ADO_LONGPTR size = sizeof(parametr); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("", ADODB::adVarWChar, ADODB::adParamInput, static_cast(parametr.size()+2), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const __int64 parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adBigInt, ADODB::adParamInput, static_cast(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const unsigned __int64 parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adUnsignedBigInt, ADODB::adParamInput, static_cast(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr(ADODB::_CommandPtr cmd, const int parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adInteger, ADODB::adParamInput, static_cast(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const unsigned int parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adUnsignedInt, ADODB::adParamInput, static_cast(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, float parametr) - { - _variant_t param; - param.ChangeType(VT_R4); - param.fltVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adSingle, ADODB::adParamInput, static_cast(sizeof(float)), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, bool parametr) - { - _variant_t param; - param = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adBoolean, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr(ADODB::_CommandPtr cmd, _variant_t parametr) - { - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDBTimeStamp, ADODB::adParamInput, sizeof(parametr), parametr); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr_as_double(ADODB::_CommandPtr cmd, const DATE parametr) - { - _variant_t param; - param.ChangeType(VT_R8); - param.dblVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDouble, ADODB::adParamInput, sizeof(float), param); - cmd->Parameters->Append(param_obj); - return true; - } - - template - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::list params) - { - for(std::list::const_iterator it = params.begin(); it!=params.end(); it++) - if(!add_parametr(cmd, *it)) - return false; - return true; - } - - /* - inline bool add_parametr(ADODB::_CommandPtr cmd, const size_t parametr) - { - _variant_t param; - param.ChangeType(VT_I4); - param.intVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adInteger, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - return true; - }*/ - - - inline bool add_parametr(ADODB::_CommandPtr cmd, const DATE parametr) - { - /*_variant_t param; - param.ChangeType(VT_R8); - param.dblVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDouble, ADODB::adParamInput, sizeof(float), param); - cmd->Parameters->Append(param_obj);*/ - - _variant_t param; - param.ChangeType(VT_DATE); - param.date = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDBDate, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - - return true; - } - - - inline bool execute_helper(ADODB::_CommandPtr cmd, _variant_t* pcount_processed = NULL) - { - //BEGIN_TRY_SECTION(); - - cmd->Execute(pcount_processed, NULL, ADODB::adExecuteNoRecords); - - - //CATCH_TRY_SECTION(false); - - return true; - } - - - inline bool select_helper(ADODB::_CommandPtr cmd, table& result_vector) - { - result_vector.clear(); - //BEGIN_TRY_SECTION(); - - ADODB::_RecordsetPtr precordset = cmd->Execute(NULL, NULL, NULL); - if(!precordset) - { - LOG_ERROR("DB_ERROR: cmd->Execute returned NULL!!!"); - return false; - } - - //if(precordset->EndOfFile == EOF) - //{ - // return true; - //} - /*try - { - if(precordset->MoveFirst()!= S_OK) - { - LOG_ERROR("DB_ERROR: Filed to move first!!!"); - return false; - } - } - catch (...) - { - return true; - }*/ - - size_t current_record_index = 0; - while(precordset->EndOfFile != EOF) - { - result_vector.push_back(table::value_type()); - size_t fields_count = precordset->Fields->Count; - result_vector[current_record_index].resize(fields_count); - for(size_t current_field_index = 0; current_field_index < fields_count; current_field_index++) - { - _variant_t var; - var.ChangeType(VT_I2); - var.intVal = static_cast(current_field_index); - result_vector[current_record_index][current_field_index] = precordset->Fields->GetItem(var)->Value; - } - precordset->MoveNext(); - current_record_index++; - } - //CATCH_TRY_SECTION(false); - return true; - } - - - template - struct adapter_zero - { - - }; - - template - struct adapter_single - { - TParam1 tparam1; - }; - template - struct adapter_double - { - TParam1 tparam1; - TParam2 tparam2; - }; - - - template - struct adapter_triple - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - }; - - template - struct adapter_quad - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - }; - - template - struct adapter_quanto - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - }; - - template - struct adapter_sixto - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - }; - - template - struct adapter_sevento - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - TParam7 tparam7; - }; - - template - struct adapter_nine - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - TParam7 tparam7; - TParam8 tparam8; - TParam9 tparam9; - }; - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_zero& params) - { - return true; - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_single& params) - { - return add_parametr(cmd, params.tparam1); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_double& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - return add_parametr(cmd, params.tparam2); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_triple& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - return add_parametr(cmd, params.tparam3); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_quad& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - return add_parametr(cmd, params.tparam4); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_quanto& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - return add_parametr(cmd, params.tparam5); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_sixto& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - return add_parametr(cmd, params.tparam6); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_sevento& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - if(!add_parametr(cmd, params.tparam6)) return false; - return add_parametr(cmd, params.tparam7); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_nine& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - if(!add_parametr(cmd, params.tparam6)) return false; - if(!add_parametr(cmd, params.tparam7)) return false; - if(!add_parametr(cmd, params.tparam8)) return false; - return add_parametr(cmd, params.tparam9); - } - - template - std::string print_parameters_multi(const adapter_sevento& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6 << ", " << params.tparam7; - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_nine& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6 << ", " << params.tparam7 << ", " << params.tparam8 << ", " << params.tparam9; - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_sixto& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6; - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_quanto& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5; - return strm.str(); - } - - - template - std::string print_parameters_multi(const adapter_quad& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4; - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_triple& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3; - return strm.str(); - } - - template - std::string get_str_param(const TParam& prm) - { - std::stringstream strm; - strm << prm; - return strm.str(); - } - - template - std::string get_str_param(const std::list& prm_lst) - { - std::stringstream strm; - for(std::list::const_iterator it = prm_lst.begin();it!=prm_lst.end();it++) - strm << get_str_param(*it) << ", "; - return strm.str(); - } - - - template - std::string print_parameters_multi(const adapter_double& params) - { - std::stringstream strm; - strm << get_str_param(params.tparam1) << ", " << get_str_param(params.tparam2); - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_single& params) - { - std::stringstream strm; - strm << get_str_param(params.tparam1); - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_zero& params) - { - std::stringstream strm; - strm << "(no parametrs)"; - return strm.str(); - } - - - template - bool execute_helper_multiparam(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, _variant_t* pcount_processed = NULL) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - if(!add_parametrs_multi(cmd, parametrs)) - return false; - - cmd->ActiveConnection = pconnection; - res = execute_helper(cmd, pcount_processed); - - CATCH_TRY_SECTION_MESS(false, "while statment: " << sql_statment << " [params]: " << print_parameters_multi(parametrs)); - return res; - } - - - template - inline - bool select_helper_multiparam(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, table& result_vector) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - - if(!add_parametrs_multi(cmd, parametrs)) - return false; - - cmd->ActiveConnection = pconnection; - res = select_helper(cmd, result_vector); - CATCH_TRY_SECTION_MESS(false, "while statment: " << sql_statment << " [params]: " << print_parameters_multi(parametrs)); - return res; - } - - - template - inline - bool select_helper_param_container(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, table& result_vector) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - - for(TParams::const_iterator it = parametrs.begin(); it!=parametrs.end(); it++) - { - add_parametr(cmd, *it); - } - - cmd->ActiveConnection = pconnection; - res = select_helper(cmd, result_vector); - - CATCH_TRY_SECTION(false); - return res; - } - - - inline - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, _variant_t* pvt = NULL) - { - adapter_zero params; - return execute_helper_multiparam(pconnection, sql_statment, params, pvt); - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam& parametr) - { - adapter_single params; - params.tparam1 = parametr; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2) - { - adapter_double params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - return execute_helper_multiparam(pconnection, sql_statment, params); - - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3) - { - adapter_triple params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4) - { - adapter_quad params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5) - { - adapter_quanto params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5, const TParam6& parametr6) - { - adapter_sixto params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5, const TParam6& parametr6, const TParam7& parametr7) - { - adapter_sevento params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - inline - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, table& result_vector) - { - adapter_zero params; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam& parametr, table& result_vector) - { - adapter_single params; - params.tparam1 = parametr; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, table& result_vector) - { - adapter_double params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, table& result_vector) - { - adapter_triple params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, table& result_vector) - { - adapter_quad params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, table& result_vector) - { - adapter_quanto params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, table& result_vector) - { - adapter_sixto params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, const TParam7 parametr7, table& result_vector) - { - adapter_sevento params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, const TParam7 parametr7,const TParam8 parametr8,const TParam9 parametr9, table& result_vector) - { - adapter_nine params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - params.tparam8 = parametr8; - params.tparam9 = parametr9; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - - - /************************************************************************/ - /* */ - /************************************************************************/ - - class per_thread_connection_pool - { - public: - bool init(const std::string& connection_string, const std::string& login, const std::string& pass) - { - m_connection_string = connection_string; - m_login = login; - m_password = pass; - if(!get_db_connection().GetInterfacePtr()) - return false; - - return true; - } - - ADODB::_ConnectionPtr& get_db_connection() - { - - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr& conn_ptr = m_db_connections[::GetCurrentThreadId()]; - m_db_connections_lock.unlock(); - if(!conn_ptr.get()) - { - conn_ptr.reset(new ADODB::_ConnectionPtr()); - ADODB::_ConnectionPtr& conn = *conn_ptr.get(); - //init new connection - - BEGIN_TRY_SECTION(); - //_bstr_t str = _bstr_t("Provider=SQLOLEDB;Data Source=SRV1;Integrated Security=SSPI;Initial Catalog=dispatcher;"); - - if(S_OK != conn.CreateInstance(__uuidof(ADODB::Connection))) - { - LOG_ERROR("Failed to Create, instance, was CoInitialize called ???!"); - return conn; - } - - HRESULT res = conn->Open(_bstr_t(m_connection_string.c_str()), _bstr_t(m_login.c_str()), _bstr_t(m_password.c_str()), NULL); - if(res != S_OK) - { - LOG_ERROR("Failed to connect do DB, connection str:" << m_connection_string); - return conn; - } - CATCH_TRY_SECTION_MESS(conn, "while creating another connection"); - LOG_PRINT("New DB Connection added for threadid=" << ::GetCurrentThreadId(), LOG_LEVEL_0); - ado_db_helper::execute_helper(conn, "set enable_seqscan=false;"); - return conn; - } - - return *conn_ptr.get(); - } - - //---------------------------------------------------------------------------------------------- - bool check_status() - { - ADODB::_ConnectionPtr& rconn = get_db_connection(); - if(!ado_db_helper::execute_helper(rconn, "SET CLIENT_ENCODING TO 'SQL_ASCII'")) - { - - try{ - HRESULT res = rconn->Close(); - } - catch(...) - { - - }; - BEGIN_TRY_SECTION(); - - HRESULT res = rconn->Open(_bstr_t(m_connection_string.c_str()), _bstr_t(m_login.c_str()), _bstr_t(m_password.c_str()), NULL); - if(res != S_OK) - { - LOG_PRINT("Failed to restore connection to local AI DB", LOG_LEVEL_1); - return false; - } - CATCH_TRY_SECTION(false); - } - - return true; - } - - protected: - private: - std::map > m_db_connections; - critical_section m_db_connections_lock; - std::string m_connection_string; - std::string m_login; - std::string m_password; - }; - - - template - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, t_conn& c) - { - ado_db_helper::adapter_single params; - params.tparam1 = parametr_1; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - - template - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, t_conn& c) - { - ado_db_helper::adapter_double params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - - template - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, TParam3 parametr_3, t_conn& c) - { - ado_db_helper::adapter_triple params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - params.tparam3 = parametr_3; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - template - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, TParam3 parametr_3, TParam4 parametr_4, t_conn& c) - { - ado_db_helper::adapter_quad params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - params.tparam3 = parametr_3; - params.tparam4 = parametr_4; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - template - bool find_or_add_t_multiparametred(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParams params, t_conn& c) - { - - //CHECK_CONNECTION(false); - - new_object_added = false; - ado_db_helper::table result_table; - - bool res = select_helper_multiparam(c.get_db_connection(), sql_select_statment, params, result_table); - if(!result_table.size()) - { - res = select_helper_multiparam(c.get_db_connection(), sql_insert_statment, params, result_table); - if(!res || !result_table.size()) - { - //last time try to select - res = select_helper_multiparam(c.get_db_connection(), sql_select_statment, params, result_table); - CHECK_AND_ASSERT_MES(res, false, "Failed to execute statment: " << sql_select_statment); - CHECK_AND_ASSERT_MES(result_table.size(), false, "No records returned from statment: " << sql_select_statment); - }else - { - new_object_added = true; - } - } - - BEGIN_TRY_SECTION() - id = result_table[0][0]; - CATCH_TRY_SECTION_MESS(false, "while converting returned value [find_or_add_t_multiparametred()]"); - - return true; - } - -} -} -#endif //!_DB_HELPER_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/console_handler.h b/src/Native/libcryptonote/contrib/epee/include/console_handler.h deleted file mode 100644 index 4ea3fa54b..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/console_handler.h +++ /dev/null @@ -1,581 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include "misc_log_ex.h" -#include "string_tools.h" -#include -#include -#include -#include -#include -#include -#ifdef __OpenBSD__ -#include -#endif -#include -#include -#include - -#ifdef HAVE_READLINE - #include "readline_buffer.h" -#endif - -namespace epee -{ - class async_stdin_reader - { - public: - async_stdin_reader() - : m_run(true) - , m_has_read_request(false) - , m_read_status(state_init) - { -#ifdef HAVE_READLINE - m_readline_buffer.start(); -#endif - m_reader_thread = boost::thread(std::bind(&async_stdin_reader::reader_thread_func, this)); - } - - ~async_stdin_reader() - { - stop(); - } - -#ifdef HAVE_READLINE - rdln::readline_buffer& get_readline_buffer() - { - return m_readline_buffer; - } -#endif - - // Not thread safe. Only one thread can call this method at once. - bool get_line(std::string& line) - { - if (!start_read()) - return false; - - if (state_eos == m_read_status) - return false; - - boost::unique_lock lock(m_response_mutex); - while (state_init == m_read_status) - { - m_response_cv.wait(lock); - } - - bool res = false; - if (state_success == m_read_status) - { - line = m_line; - res = true; - } - - if (!eos()) - m_read_status = state_init; - - return res; - } - - bool eos() const { return m_read_status == state_eos; } - - void stop() - { - if (m_run) - { - m_run.store(false, std::memory_order_relaxed); - -#if defined(WIN32) - ::CloseHandle(::GetStdHandle(STD_INPUT_HANDLE)); -#endif - - m_request_cv.notify_one(); - m_reader_thread.join(); -#ifdef HAVE_READLINE - m_readline_buffer.stop(); -#endif - } - } - - private: - bool start_read() - { - boost::unique_lock lock(m_request_mutex); - if (!m_run.load(std::memory_order_relaxed) || m_has_read_request) - return false; - - m_has_read_request = true; - m_request_cv.notify_one(); - return true; - } - - bool wait_read() - { - boost::unique_lock lock(m_request_mutex); - while (m_run.load(std::memory_order_relaxed) && !m_has_read_request) - { - m_request_cv.wait(lock); - } - - if (m_has_read_request) - { - m_has_read_request = false; - return true; - } - - return false; - } - - bool wait_stdin_data() - { -#if !defined(WIN32) - #if defined(__OpenBSD__) || defined(__ANDROID__) - int stdin_fileno = fileno(stdin); - #else - int stdin_fileno = ::fileno(stdin); - #endif - - while (m_run.load(std::memory_order_relaxed)) - { - fd_set read_set; - FD_ZERO(&read_set); - FD_SET(stdin_fileno, &read_set); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 100 * 1000; - - int retval = ::select(stdin_fileno + 1, &read_set, NULL, NULL, &tv); - if (retval < 0) - return false; - else if (0 < retval) - return true; - } -#else - while (m_run.load(std::memory_order_relaxed)) - { - int retval = ::WaitForSingleObject(::GetStdHandle(STD_INPUT_HANDLE), 100); - switch (retval) - { - case WAIT_FAILED: - return false; - case WAIT_OBJECT_0: - return true; - default: - break; - } - } -#endif - - return true; - } - - void reader_thread_func() - { - while (true) - { - if (!wait_read()) - break; - - std::string line; - bool read_ok = true; -#ifdef HAVE_READLINE -reread: -#endif - if (wait_stdin_data()) - { - if (m_run.load(std::memory_order_relaxed)) - { -#ifdef HAVE_READLINE - switch (m_readline_buffer.get_line(line)) - { - case rdln::empty: goto eof; - case rdln::partial: goto reread; - case rdln::full: break; - } -#else - std::getline(std::cin, line); -#endif - read_ok = !std::cin.eof() && !std::cin.fail(); - } - } - else - { - read_ok = false; - } - if (std::cin.eof()) { -#ifdef HAVE_READLINE -eof: -#endif - m_read_status = state_eos; - m_response_cv.notify_one(); - break; - } - else - { - boost::unique_lock lock(m_response_mutex); - if (m_run.load(std::memory_order_relaxed)) - { - m_line = std::move(line); - m_read_status = read_ok ? state_success : state_error; - } - else - { - m_read_status = state_cancelled; - } - m_response_cv.notify_one(); - } - } - } - - enum t_state - { - state_init, - state_success, - state_error, - state_cancelled, - state_eos - }; - - private: - boost::thread m_reader_thread; - std::atomic m_run; -#ifdef HAVE_READLINE - rdln::readline_buffer m_readline_buffer; -#endif - - std::string m_line; - bool m_has_read_request; - t_state m_read_status; - - boost::mutex m_request_mutex; - boost::mutex m_response_mutex; - boost::condition_variable m_request_cv; - boost::condition_variable m_response_cv; - }; - - - template - bool empty_commands_handler(t_server* psrv, const std::string& command) - { - return true; - } - - - class async_console_handler - { - public: - async_console_handler() - { - } - - template - bool run(t_server* psrv, chain_handler ch_handler, std::function prompt, const std::string& usage = "") - { - return run(prompt, usage, [&](const std::string& cmd) { return ch_handler(psrv, cmd); }, [&] { psrv->send_stop_signal(); }); - } - - template - bool run(chain_handler ch_handler, std::function prompt, const std::string& usage = "", std::function exit_handler = NULL) - { - return run(prompt, usage, [&](const std::string& cmd) { return ch_handler(cmd); }, exit_handler); - } - - void stop() - { - m_running = false; - m_stdin_reader.stop(); - } - - void print_prompt() - { - std::string prompt = m_prompt(); - if (!prompt.empty()) - { -#ifdef HAVE_READLINE - std::string color_prompt = "\001\033[1;33m\002" + prompt; - if (' ' != prompt.back()) - color_prompt += " "; - color_prompt += "\001\033[0m\002"; - m_stdin_reader.get_readline_buffer().set_prompt(color_prompt); -#else - epee::set_console_color(epee::console_color_yellow, true); - std::cout << prompt; - if (' ' != prompt.back()) - std::cout << ' '; - epee::reset_console_color(); - std::cout.flush(); -#endif - } - } - - private: - template - bool run(std::function prompt, const std::string& usage, const t_cmd_handler& cmd_handler, std::function exit_handler) - { - bool continue_handle = true; - m_prompt = prompt; - while(continue_handle) - { - try - { - if (!m_running) - { - break; - } - print_prompt(); - - std::string command; - bool get_line_ret = m_stdin_reader.get_line(command); - if (!m_running || m_stdin_reader.eos()) - { - break; - } - if (!get_line_ret) - { - MERROR("Failed to read line."); - } - string_tools::trim(command); - - LOG_PRINT_L2("Read command: " << command); - if (command.empty()) - { - continue; - } - else if(cmd_handler(command)) - { - continue; - } - else if(0 == command.compare("exit") || 0 == command.compare("q")) - { - continue_handle = false; - } - else - { -#ifdef HAVE_READLINE - rdln::suspend_readline pause_readline; -#endif - std::cout << "unknown command: " << command << std::endl; - std::cout << usage; - } - } - catch (const std::exception &ex) - { - LOG_ERROR("Exception at [console_handler], what=" << ex.what()); - } - } - if (exit_handler) - exit_handler(); - return true; - } - - private: - async_stdin_reader m_stdin_reader; - std::atomic m_running = {true}; - std::function m_prompt; - }; - - - template - bool start_default_console(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - std::shared_ptr console_handler = std::make_shared(); - boost::thread([=](){console_handler->run(ptsrv, handlr, prompt, usage);}).detach(); - return true; - } - - template - bool start_default_console(t_server* ptsrv, const std::string& prompt, const std::string& usage = "") - { - return start_default_console(ptsrv, empty_commands_handler, prompt, usage); - } - - template - bool no_srv_param_adapter(t_server* ptsrv, const std::string& cmd, t_handler handlr) - { - return handlr(cmd); - } - - template - bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - async_console_handler console_handler; - return console_handler.run(ptsrv, boost::bind(no_srv_param_adapter, _1, _2, handlr), prompt, usage); - } - - template - bool start_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - boost::thread( boost::bind(run_default_console_handler_no_srv_param, ptsrv, handlr, prompt, usage) ); - return true; - } - - /*template - bool f(int i, a l) - { - return true; - }*/ - /* - template - bool default_console_handler2(chain_handler ch_handler, const std::string usage) - */ - - - /*template - bool start_default_console2(t_handler handlr, const std::string& usage = "") - { - //std::string usage_local = usage; - boost::thread( boost::bind(default_console_handler2, handlr, usage) ); - //boost::function p__ = boost::bind(f, 1, handlr); - //boost::function p__ = boost::bind(default_console_handler2, handlr, usage); - //boost::thread tr(p__); - return true; - }*/ - - class command_handler { - public: - typedef boost::function &)> callback; - typedef std::map>> lookup; - - std::string get_usage() - { - std::stringstream ss; - - for(auto& x:m_command_handlers) - { - ss << x.second.second.first << ENDL; - } - return ss.str(); - } - - std::pair get_documentation(const std::vector& cmd) - { - if(cmd.empty()) - return std::make_pair("", ""); - auto it = m_command_handlers.find(cmd.front()); - if(it == m_command_handlers.end()) - return std::make_pair("", ""); - return it->second.second; - } - - void set_handler(const std::string& cmd, const callback& hndlr, const std::string& usage = "", const std::string& description = "") - { - lookup::mapped_type & vt = m_command_handlers[cmd]; - vt.first = hndlr; - vt.second.first = description.empty() ? cmd : usage; - vt.second.second = description.empty() ? usage : description; -#ifdef HAVE_READLINE - rdln::readline_buffer::add_completion(cmd); -#endif - } - - bool process_command_vec(const std::vector& cmd) - { - if(!cmd.size()) - return false; - auto it = m_command_handlers.find(cmd.front()); - if(it == m_command_handlers.end()) - return false; - std::vector cmd_local(cmd.begin()+1, cmd.end()); - return it->second.first(cmd_local); - } - - bool process_command_str(const std::string& cmd) - { - std::vector cmd_v; - boost::split(cmd_v,cmd,boost::is_any_of(" "), boost::token_compress_on); - return process_command_vec(cmd_v); - } - private: - lookup m_command_handlers; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class console_handlers_binder : public command_handler - { - typedef command_handler::callback console_command_handler; - typedef command_handler::lookup command_handlers_map; - std::unique_ptr m_console_thread; - async_console_handler m_console_handler; - public: - bool start_handling(std::function prompt, const std::string& usage_string = "", std::function exit_handler = NULL) - { - m_console_thread.reset(new boost::thread(boost::bind(&console_handlers_binder::run_handling, this, prompt, usage_string, exit_handler))); - m_console_thread->detach(); - return true; - } - bool start_handling(const std::string &prompt, const std::string& usage_string = "", std::function exit_handler = NULL) - { - return start_handling([prompt](){ return prompt; }, usage_string, exit_handler); - } - - void stop_handling() - { - m_console_handler.stop(); - } - - bool run_handling(std::function prompt, const std::string& usage_string, std::function exit_handler = NULL) - { - return m_console_handler.run(boost::bind(&console_handlers_binder::process_command_str, this, _1), prompt, usage_string, exit_handler); - } - - void print_prompt() - { - m_console_handler.print_prompt(); - } - }; - - ///* work around because of broken boost bind */ - //template - //class srv_console_handlers_binder: public command_handler - //{ - // async_console_handler m_console_handler; - //public: - // bool start_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string = "") - // { - // boost::thread(boost::bind(&srv_console_handlers_binder::run_handling, this, psrv, prompt, usage_string)).detach(); - // return true; - // } - - // bool run_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string) - // { - // return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder::process_command_str, this, _1, _2), prompt, usage_string); - // } - - // void stop_handling() - // { - // m_console_handler.stop(); - // } - //private: - // bool process_command_str(t_server* /*psrv*/, const std::string& cmd) - // { - // return console_handlers_binder::process_command_str(cmd); - // } - //}; -} diff --git a/src/Native/libcryptonote/contrib/epee/include/copyable_atomic.h b/src/Native/libcryptonote/contrib/epee/include/copyable_atomic.h deleted file mode 100644 index 00a5f484b..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/copyable_atomic.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include - -namespace epee -{ - class copyable_atomic: public std::atomic - { - public: - copyable_atomic() - {}; - copyable_atomic(uint32_t value) - { store(value); } - copyable_atomic(const copyable_atomic& a):std::atomic(a.load()) - {} - copyable_atomic& operator= (const copyable_atomic& a) - { - store(a.load()); - return *this; - } - uint32_t operator++() - { - return std::atomic::operator++(); - } - uint32_t operator++(int fake) - { - return std::atomic::operator++(fake); - } - }; -} diff --git a/src/Native/libcryptonote/contrib/epee/include/file_io_utils.h b/src/Native/libcryptonote/contrib/epee/include/file_io_utils.h index 196610674..25f8c648b 100644 --- a/src/Native/libcryptonote/contrib/epee/include/file_io_utils.h +++ b/src/Native/libcryptonote/contrib/epee/include/file_io_utils.h @@ -28,11 +28,12 @@ #ifndef _FILE_IO_UTILS_H_ #define _FILE_IO_UTILS_H_ -#include +#include #include #include #ifdef WIN32 #include +#include "string_tools.h" #endif // On Windows there is a problem with non-ASCII characters in path and file names @@ -72,11 +73,9 @@ namespace file_io_utils bool save_string_to_file(const std::string& path_to_file, const std::string& str) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; DWORD bytes_written; @@ -128,18 +127,16 @@ namespace file_io_utils inline - bool load_file_to_string(const std::string& path_to_file, std::string& target_str) + bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; DWORD file_size = GetFileSize(file_handle, NULL); - if ((file_size == INVALID_FILE_SIZE) || (file_size > 1000000000)) { + if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) { CloseHandle(file_handle); return false; } @@ -159,7 +156,7 @@ namespace file_io_utils std::ifstream::pos_type file_size = fstream.tellg(); - if(file_size > 1000000000) + if((uint64_t)file_size > (uint64_t)max_size) // ensure a large domain for comparison, and negative -> too large return false;//don't go crazy size_t file_size_t = static_cast(file_size); @@ -202,11 +199,9 @@ namespace file_io_utils bool get_file_size(const std::string& path_to_file, uint64_t &size) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; LARGE_INTEGER file_size; diff --git a/src/Native/libcryptonote/cryptonote_basic/blobdatatype.h b/src/Native/libcryptonote/contrib/epee/include/fnv1.h similarity index 84% rename from src/Native/libcryptonote/cryptonote_basic/blobdatatype.h rename to src/Native/libcryptonote/contrib/epee/include/fnv1.h index 7d6ff0187..c04389bca 100644 --- a/src/Native/libcryptonote/cryptonote_basic/blobdatatype.h +++ b/src/Native/libcryptonote/contrib/epee/include/fnv1.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2018, The Monero Project // // All rights reserved. // @@ -25,12 +25,21 @@ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #pragma once -namespace cryptonote +namespace epee +{ + +namespace fnv { - typedef std::string blobdata; + inline uint64_t FNV1a(const char *ptr, size_t sz) + { + uint64_t h = 0xcbf29ce484222325; + for (size_t i = 0; i < sz; ++i) + h = (h ^ *(const uint8_t*)ptr++) * 0x100000001b3; + return h; + } +} + } diff --git a/src/Native/libcryptonote/contrib/epee/include/global_stream_operators.h b/src/Native/libcryptonote/contrib/epee/include/global_stream_operators.h deleted file mode 100644 index 6fbdbc2ed..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/global_stream_operators.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -std::stringstream& operator<<(std::stringstream& out, const std::wstring& ws) -{ - std::string as = string_encoding::convert_to_ansii(ws); - out << as; - return out; -} diff --git a/src/Native/libcryptonote/contrib/epee/include/gzip_encoding.h b/src/Native/libcryptonote/contrib/epee/include/gzip_encoding.h deleted file mode 100644 index 2be51e77d..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/gzip_encoding.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _GZIP_ENCODING_H_ -#define _GZIP_ENCODING_H_ -#include "net/http_client_base.h" -#include "zlib/zlib.h" -//#include "http.h" - - -namespace epee -{ -namespace net_utils -{ - - - - class content_encoding_gzip: public i_sub_handler - { - public: - /*! \brief - * Function content_encoding_gzip : Constructor - * - */ - inline - content_encoding_gzip(i_target_handler* powner_filter, bool is_deflate_mode = false):m_powner_filter(powner_filter), - m_is_stream_ended(false), - m_is_deflate_mode(is_deflate_mode), - m_is_first_update_in(true) - { - memset(&m_zstream_in, 0, sizeof(m_zstream_in)); - memset(&m_zstream_out, 0, sizeof(m_zstream_out)); - int ret = 0; - if(is_deflate_mode) - { - ret = inflateInit(&m_zstream_in); - ret = deflateInit(&m_zstream_out, Z_DEFAULT_COMPRESSION); - }else - { - ret = inflateInit2(&m_zstream_in, 0x1F); - ret = deflateInit2(&m_zstream_out, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8, Z_DEFAULT_STRATEGY); - } - } - /*! \brief - * Function content_encoding_gzip : Destructor - * - */ - inline - ~content_encoding_gzip() - { - inflateEnd(& m_zstream_in ); - deflateEnd(& m_zstream_out ); - } - /*! \brief - * Function update_in : Entry point for income data - * - */ - inline - virtual bool update_in( std::string& piece_of_transfer) - { - - bool is_first_time_here = m_is_first_update_in; - m_is_first_update_in = false; - - if(m_pre_decode.size()) - m_pre_decode += piece_of_transfer; - else - m_pre_decode.swap(piece_of_transfer); - piece_of_transfer.clear(); - - std::string decode_summary_buff; - - size_t ungzip_size = m_pre_decode.size() * 0x30; - std::string current_decode_buff(ungzip_size, 'X'); - - //Here the cycle is introduced where we unpack the buffer, the cycle is required - //because of the case where if after unpacking the data will exceed the awaited size, we will not halt with error - bool continue_unpacking = true; - bool first_step = true; - while(m_pre_decode.size() && continue_unpacking) - { - - //fill buffers - m_zstream_in.next_in = (Bytef*)m_pre_decode.data(); - m_zstream_in.avail_in = (uInt)m_pre_decode.size(); - m_zstream_in.next_out = (Bytef*)current_decode_buff.data(); - m_zstream_in.avail_out = (uInt)ungzip_size; - - int flag = Z_SYNC_FLUSH; - int ret = inflate(&m_zstream_in, flag); - CHECK_AND_ASSERT_MES(ret>=0 || m_zstream_in.avail_out ||m_is_deflate_mode, false, "content_encoding_gzip::update_in() Failed to inflate. err = " << ret); - - if(Z_STREAM_END == ret) - m_is_stream_ended = true; - else if(Z_DATA_ERROR == ret && is_first_time_here && m_is_deflate_mode&& first_step) - { - // some servers (notably Apache with mod_deflate) don't generate zlib headers - // insert a dummy header and try again - static char dummy_head[2] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, - }; - inflateReset(&m_zstream_in); - m_zstream_in.next_in = (Bytef*) dummy_head; - m_zstream_in.avail_in = sizeof(dummy_head); - - ret = inflate(&m_zstream_in, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - m_pre_decode.swap(piece_of_transfer); - return false; - } - m_zstream_in.next_in = (Bytef*)m_pre_decode.data(); - m_zstream_in.avail_in = (uInt)m_pre_decode.size(); - - ret = inflate(&m_zstream_in, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - m_pre_decode.swap(piece_of_transfer); - return false; - } - } - - - //leave only unpacked part in the output buffer to start with it the next time - m_pre_decode.erase(0, m_pre_decode.size()-m_zstream_in.avail_in); - //if decoder gave nothing to return, then everything is ahead, now simply break - if(ungzip_size == m_zstream_in.avail_out) - break; - - //decode_buff currently stores data parts that were unpacked, fix this size - current_decode_buff.resize(ungzip_size - m_zstream_in.avail_out); - if(decode_summary_buff.size()) - decode_summary_buff += current_decode_buff; - else - current_decode_buff.swap(decode_summary_buff); - - current_decode_buff.resize(ungzip_size); - first_step = false; - } - - //Process these data if required - bool res = true; - - res = m_powner_filter->handle_target_data(decode_summary_buff); - - return true; - - } - /*! \brief - * Function stop : Entry point for stop signal and flushing cached data buffer. - * - */ - inline - virtual void stop(std::string& OUT collect_remains) - { - } - protected: - private: - /*! \brief - * Pointer to parent HTTP-parser - */ - i_target_handler* m_powner_filter; - /*! \brief - * ZLIB object for income stream - */ - z_stream m_zstream_in; - /*! \brief - * ZLIB object for outcome stream - */ - z_stream m_zstream_out; - /*! \brief - * Data that could not be unpacked immediately, left to wait for the next packet of data - */ - std::string m_pre_decode; - /*! \brief - * The data are accumulated for a package in the buffer to send the web client - */ - std::string m_pre_encode; - /*! \brief - * Signals that stream looks like ended - */ - bool m_is_stream_ended; - /*! \brief - * If this flag is set, income data is in HTTP-deflate mode - */ - bool m_is_deflate_mode; - /*! \brief - * Marks that it is a first data packet - */ - bool m_is_first_update_in; - }; -} -} - - - -#endif //_GZIP_ENCODING_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/hex.h b/src/Native/libcryptonote/contrib/epee/include/hex.h index e960da1d2..6e720f128 100644 --- a/src/Native/libcryptonote/contrib/epee/include/hex.h +++ b/src/Native/libcryptonote/contrib/epee/include/hex.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // @@ -32,7 +32,9 @@ #include #include #include +#include +#include "wipeable_string.h" #include "span.h" namespace epee @@ -41,6 +43,9 @@ namespace epee { //! \return A std::string containing hex of `src`. static std::string string(const span src); + //! \return A epee::wipeable_string containing hex of `src`. + static epee::wipeable_string wipeable_string(const span src); + template static epee::wipeable_string wipeable_string(const T &pod) { return wipeable_string(span((const uint8_t*)&pod, sizeof(pod))); } //! \return An array containing hex of `src`. template @@ -59,7 +64,15 @@ namespace epee static void formatted(std::ostream& out, const span src); private: + template T static convert(const span src); + //! Write `src` bytes as hex to `out`. `out` must be twice the length static void buffer_unchecked(char* out, const span src) noexcept; }; + + struct from_hex + { + //! \return An std::vector of unsigned integers from the `src` + static std::vector vector(boost::string_ref src); + }; } diff --git a/src/Native/libcryptonote/contrib/epee/include/hmac-md5.h b/src/Native/libcryptonote/contrib/epee/include/hmac-md5.h deleted file mode 100644 index 2a4e0d401..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/hmac-md5.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* hmac-md5.h -- HMAC_MD5 functions - */ - -/* - * $Id: hmac-md5.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $ - */ - -#ifndef HMAC_MD5_H -#define HMAC_MD5_H 1 - -namespace md5 -{ - - - -#define HMAC_MD5_SIZE 16 - - /* intermediate MD5 context */ - typedef struct HMAC_MD5_CTX_s { - MD5_CTX ictx, octx; - } HMAC_MD5_CTX; - - /* intermediate HMAC state - * values stored in network byte order (Big Endian) - */ - typedef struct HMAC_MD5_STATE_s { - UINT4 istate[4]; - UINT4 ostate[4]; - } HMAC_MD5_STATE; - - /* One step hmac computation - * - * digest may be same as text or key - */ - void hmac_md5(const unsigned char *text, int text_len, - const unsigned char *key, int key_len, - unsigned char digest[HMAC_MD5_SIZE]); - - /* create context from key - */ - void hmac_md5_init(HMAC_MD5_CTX *hmac, - const unsigned char *key, int key_len); - - /* precalculate intermediate state from key - */ - void hmac_md5_precalc(HMAC_MD5_STATE *hmac, - const unsigned char *key, int key_len); - - /* initialize context from intermediate state - */ - void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state); - -#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len)) - - /* finish hmac from intermediate result. Intermediate result is zeroed. - */ - void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], - HMAC_MD5_CTX *hmac); - -} - -#endif /* HMAC_MD5_H */ diff --git a/src/Native/libcryptonote/contrib/epee/include/int-util.h b/src/Native/libcryptonote/contrib/epee/include/int-util.h new file mode 100644 index 000000000..0ed6505ff --- /dev/null +++ b/src/Native/libcryptonote/contrib/epee/include/int-util.h @@ -0,0 +1,258 @@ +// Copyright (c) 2014-2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +#endif + +#if defined(__ANDROID__) +#include +#endif + +#if defined(__sun) && defined(__SVR4) +#include +#endif + +#if defined(_MSC_VER) +#include + +static inline uint32_t rol32(uint32_t x, int r) { + static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers"); + return _rotl(x, r); +} + +static inline uint64_t rol64(uint64_t x, int r) { + return _rotl64(x, r); +} + +#else + +static inline uint32_t rol32(uint32_t x, int r) { + return (x << (r & 31)) | (x >> (-r & 31)); +} + +static inline uint64_t rol64(uint64_t x, int r) { + return (x << (r & 63)) | (x >> (-r & 63)); +} + +#endif + +static inline uint64_t hi_dword(uint64_t val) { + return val >> 32; +} + +static inline uint64_t lo_dword(uint64_t val) { + return val & 0xFFFFFFFF; +} + +static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) { + // multiplier = ab = a * 2^32 + b + // multiplicand = cd = c * 2^32 + d + // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d + uint64_t a = hi_dword(multiplier); + uint64_t b = lo_dword(multiplier); + uint64_t c = hi_dword(multiplicand); + uint64_t d = lo_dword(multiplicand); + + uint64_t ac = a * c; + uint64_t ad = a * d; + uint64_t bc = b * c; + uint64_t bd = b * d; + + uint64_t adbc = ad + bc; + uint64_t adbc_carry = adbc < ad ? 1 : 0; + + // multiplier * multiplicand = product_hi * 2^64 + product_lo + uint64_t product_lo = bd + (adbc << 32); + uint64_t product_lo_carry = product_lo < bd ? 1 : 0; + *product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry; + assert(ac <= *product_hi); + + return product_lo; +} + +static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) { + dividend |= ((uint64_t)*remainder) << 32; + *remainder = dividend % divisor; + return dividend / divisor; +} + +// Long division with 2^32 base +static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) { + uint64_t dividend_dwords[4]; + uint32_t remainder = 0; + + dividend_dwords[3] = hi_dword(dividend_hi); + dividend_dwords[2] = lo_dword(dividend_hi); + dividend_dwords[1] = hi_dword(dividend_lo); + dividend_dwords[0] = lo_dword(dividend_lo); + + *quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32; + *quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder); + *quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32; + *quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder); + + return remainder; +} + +#define IDENT32(x) ((uint32_t) (x)) +#define IDENT64(x) ((uint64_t) (x)) + +#define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \ + (((uint32_t) (x) & 0x0000ff00) << 8) | \ + (((uint32_t) (x) & 0x00ff0000) >> 8) | \ + (((uint32_t) (x) & 0xff000000) >> 24)) +#define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \ + (((uint64_t) (x) & 0x000000000000ff00) << 40) | \ + (((uint64_t) (x) & 0x0000000000ff0000) << 24) | \ + (((uint64_t) (x) & 0x00000000ff000000) << 8) | \ + (((uint64_t) (x) & 0x000000ff00000000) >> 8) | \ + (((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \ + (((uint64_t) (x) & 0x00ff000000000000) >> 40) | \ + (((uint64_t) (x) & 0xff00000000000000) >> 56)) + +static inline uint32_t ident32(uint32_t x) { return x; } +static inline uint64_t ident64(uint64_t x) { return x; } + +#ifndef __OpenBSD__ +# if defined(__ANDROID__) && defined(__swap32) && !defined(swap32) +# define swap32 __swap32 +# elif !defined(swap32) +static inline uint32_t swap32(uint32_t x) { + x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8); + return (x << 16) | (x >> 16); +} +# endif +# if defined(__ANDROID__) && defined(__swap64) && !defined(swap64) +# define swap64 __swap64 +# elif !defined(swap64) +static inline uint64_t swap64(uint64_t x) { + x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8); + x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16); + return (x << 32) | (x >> 32); +} +# endif +#endif /* __OpenBSD__ */ + +#if defined(__GNUC__) +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif +static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { } +#undef UNUSED + +static inline void mem_inplace_swap32(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]); + } +} +static inline void mem_inplace_swap64(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]); + } +} + +static inline void memcpy_ident32(void *dst, const void *src, size_t n) { + memcpy(dst, src, 4 * n); +} +static inline void memcpy_ident64(void *dst, const void *src, size_t n) { + memcpy(dst, src, 8 * n); +} + +static inline void memcpy_swap32(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]); + } +} +static inline void memcpy_swap64(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]); + } +} + +#ifdef _MSC_VER +# define LITTLE_ENDIAN 1234 +# define BIG_ENDIAN 4321 +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) +static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"); +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +#define SWAP32LE IDENT32 +#define SWAP32BE SWAP32 +#define swap32le ident32 +#define swap32be swap32 +#define mem_inplace_swap32le mem_inplace_ident +#define mem_inplace_swap32be mem_inplace_swap32 +#define memcpy_swap32le memcpy_ident32 +#define memcpy_swap32be memcpy_swap32 +#define SWAP64LE IDENT64 +#define SWAP64BE SWAP64 +#define swap64le ident64 +#define swap64be swap64 +#define mem_inplace_swap64le mem_inplace_ident +#define mem_inplace_swap64be mem_inplace_swap64 +#define memcpy_swap64le memcpy_ident64 +#define memcpy_swap64be memcpy_swap64 +#endif + +#if BYTE_ORDER == BIG_ENDIAN +#define SWAP32BE IDENT32 +#define SWAP32LE SWAP32 +#define swap32be ident32 +#define swap32le swap32 +#define mem_inplace_swap32be mem_inplace_ident +#define mem_inplace_swap32le mem_inplace_swap32 +#define memcpy_swap32be memcpy_ident32 +#define memcpy_swap32le memcpy_swap32 +#define SWAP64BE IDENT64 +#define SWAP64LE SWAP64 +#define swap64be ident64 +#define swap64le swap64 +#define mem_inplace_swap64be mem_inplace_ident +#define mem_inplace_swap64le mem_inplace_swap64 +#define memcpy_swap64be memcpy_ident64 +#define memcpy_swap64le memcpy_swap64 +#endif diff --git a/src/Native/libcryptonote/contrib/epee/include/math_helper.h b/src/Native/libcryptonote/contrib/epee/include/math_helper.h index ef839f609..ddc1f7f4b 100644 --- a/src/Native/libcryptonote/contrib/epee/include/math_helper.h +++ b/src/Native/libcryptonote/contrib/epee/include/math_helper.h @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include @@ -230,35 +230,57 @@ namespace math_helper } } - template - class once_a_time_seconds + template + class once_a_time { + uint64_t get_time() const + { +#ifdef _WIN32 + FILETIME fileTime; + GetSystemTimeAsFileTime(&fileTime); + unsigned __int64 present = 0; + present |= fileTime.dwHighDateTime; + present = present << 32; + present |= fileTime.dwLowDateTime; + present /= 10; // mic-sec + return present; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +#endif + } + public: - once_a_time_seconds():m_interval(default_interval) + once_a_time():m_interval(default_interval * scale) { m_last_worked_time = 0; if(!start_immediate) - time(&m_last_worked_time); + m_last_worked_time = get_time(); } template bool do_call(functor_t functr) { - time_t current_time = 0; - time(¤t_time); + uint64_t current_time = get_time(); if(current_time - m_last_worked_time > m_interval) { bool res = functr(); - time(&m_last_worked_time); + m_last_worked_time = get_time(); return res; } return true; } private: - time_t m_last_worked_time; - time_t m_interval; + uint64_t m_last_worked_time; + uint64_t m_interval; }; + + template + class once_a_time_seconds: public once_a_time<1000000, default_interval, start_immediate> {}; + template + class once_a_time_milliseconds: public once_a_time<1000, default_interval, start_immediate> {}; } } diff --git a/src/Native/libcryptonote/contrib/epee/include/md5_l.h b/src/Native/libcryptonote/contrib/epee/include/md5_l.h deleted file mode 100644 index a45d91bc8..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/md5_l.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * $Id: md5.h,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $ - */ - -/* MD5.H - header file for MD5C.C - */ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. -These notices must be retained in any copies of any part of this -documentation and/or software. - */ -#ifndef MD5_H -#define MD5_H - - -#include "md5global.h" - -namespace md5 -{ - /* MD5 context. */ - typedef struct { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ - } MD5_CTX; - - static void MD5Init(MD5_CTX * context); - static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen ); - static void MD5Final ( unsigned char digest[16], MD5_CTX *context ); - static inline void hmac_md5(const unsigned char* text, int text_len, const unsigned char* key, int key_len, unsigned char *digest); - - - inline bool md5( unsigned char *input, int ilen, unsigned char output[16] ) - { - MD5_CTX ctx; - - MD5Init( &ctx ); - MD5Update( &ctx, input, ilen ); - MD5Final( output, &ctx); - - memset( &ctx, 0, sizeof( MD5_CTX) ); - return true; - } - - -} - -#include "md5_l.inl" - -#endif diff --git a/src/Native/libcryptonote/contrib/epee/include/md5_l.inl b/src/Native/libcryptonote/contrib/epee/include/md5_l.inl deleted file mode 100644 index 8e339e006..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/md5_l.inl +++ /dev/null @@ -1,560 +0,0 @@ -/* -* libEtPan! -- a mail stuff library -* -* Copyright (C) 2001, 2005 - DINH Viet Hoa -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the libEtPan! project nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -* SUCH DAMAGE. -*/ - -/* -* $Id: md5.c,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $ -*/ - -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm -*/ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. -*/ - -#ifdef _WIN32 -# include -#else -# include -#endif -#include "md5global.h" -#include "md5_l.h" -#include "hmac-md5.h" - -namespace md5 -{ - /* Constants for MD5Transform routine. - */ - -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - - /* - static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); - static void Encode PROTO_LIST - ((unsigned char *, UINT4 *, unsigned int)); - static void Decode PROTO_LIST - ((UINT4 *, unsigned char *, unsigned int)); - static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); - static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); - */ - - static void MD5_memcpy (POINTER output, POINTER input, unsigned int len) - { - unsigned int i; - - for (i = 0; i < len; i++) - output[i] = input[i]; - } - - /* Note: Replace "for loop" with standard memset if possible. - */ - - static void MD5_memset (POINTER output, int value, unsigned int len) - { - unsigned int i; - - for (i = 0; i < len; i++) - ((char *)output)[i] = (char)value; - } - - static void MD5Transform (UINT4 state[4], unsigned char block[64]); - - static unsigned char* PADDING() - { - static unsigned char local_PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - return local_PADDING; - - } - - - - /* F, G, H and I are basic MD5 functions. - - */ -#ifdef I - /* This might be defined via NANA */ -#undef I -#endif - -#define MD5_M_F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define MD5_M_G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define MD5_M_H(x, y, z) ((x) ^ (y) ^ (z)) -#define MD5_M_I(x, y, z) ((y) ^ ((x) | (~z))) - - /* ROTATE_LEFT rotates x left n bits. - - */ - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - - /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. - Rotation is separate from addition to prevent recomputation. - */ - -#define FF(a, b, c, d, x, s, ac) { (a) += MD5_M_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define GG(a, b, c, d, x, s, ac) { (a) += MD5_M_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define HH(a, b, c, d, x, s, ac) { (a) += MD5_M_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define II(a, b, c, d, x, s, ac) { (a) += MD5_M_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } - - /* MD5 initialization. Begins an MD5 operation, writing a new context. - */ - - static void MD5Init(MD5_CTX * context) - { - context->count[0] = context->count[1] = 0; - - /* Load magic initialization constants. - - */ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; - } - - /* MD5 block update operation. Continues an MD5 message-digest - operation, processing another message block, and updating the context. - */ - - static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen ) - { - unsigned int i, index, partLen; - - /* Compute number of bytes mod 64 */ - index = (unsigned int)((context->count[0] >> 3) & 0x3F); - - /* Update number of bits */ - if ((context->count[0] += ((UINT4)inputLen << 3)) - < ((UINT4)inputLen << 3)) - context->count[1]++; - context->count[1] += ((UINT4)inputLen >> 29); - - partLen = 64 - index; - - /* Transform as many times as possible. - - */ - if (inputLen >= partLen) - { - MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)input, partLen ); - MD5Transform( context->state, context->buffer ); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform (context->state, (unsigned char*)&input[i]); - - index = 0; - } - else - i = 0; - - /* Buffer remaining input */ - MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i ); - - } - - /* Encodes input (UINT4) into output (unsigned char). Assumes len is - a multiple of 4. - - */ - - static void Encode (unsigned char *output, UINT4 *input, unsigned int len) - { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } - } - - /* Decodes input (unsigned char) into output (UINT4). Assumes len is - a multiple of 4. - - */ - - static void Decode (UINT4 *output, unsigned char *input, unsigned int len) - { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) - | (((UINT4)input[j+3]) << 24); - } - - /* MD5 finalization. Ends an MD5 message-digest operation, writing the - the message digest and zeroizing the context. - - */ - - static void MD5Final ( unsigned char digest[16], MD5_CTX *context ) - { - unsigned char bits[8]; - unsigned int index, padLen; - - /* Save number of bits */ - Encode (bits, context->count, 8); - - /* Pad out to 56 mod 64. - - */ - index = (unsigned int)((context->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - MD5Update (context, PADDING(), padLen); - - /* Append length (before padding) */ - MD5Update (context, bits, 8); - - /* Store state in digest */ - Encode (digest, context->state, 16); - - /* Zeroize sensitive information. - - */ - MD5_memset ((POINTER)context, 0, sizeof (*context)); - } - - /* MD5 basic transformation. Transforms state based on block. - - */ - - static void MD5Transform (UINT4 state[4], unsigned char block[64]) - { - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - Decode (x, block, 64); - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - /* Zeroize sensitive information. - */ - MD5_memset ((POINTER)x, 0, sizeof (x)); - } - - /* Note: Replace "for loop" with standard memcpy if possible. - - */ - inline - void hmac_md5_init(HMAC_MD5_CTX *hmac, - const unsigned char *key, - int key_len) - { - unsigned char k_ipad[65]; /* inner padding - - * key XORd with ipad - */ - unsigned char k_opad[65]; /* outer padding - - * key XORd with opad - */ - unsigned char tk[16]; - int i; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - - MD5_CTX tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - MD5_memset(k_ipad, '\0', sizeof k_ipad); - MD5_memset(k_opad, '\0', sizeof k_opad); - MD5_memcpy( k_ipad, (POINTER)key, key_len); - MD5_memcpy( k_opad, (POINTER)key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - MD5Init(&hmac->ictx); /* init inner context */ - MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */ - - MD5Init(&hmac->octx); /* init outer context */ - MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */ - - /* scrub the pads and key context (if used) */ - MD5_memset( (POINTER)&k_ipad, 0, sizeof(k_ipad)); - MD5_memset( (POINTER)&k_opad, 0, sizeof(k_opad)); - MD5_memset( (POINTER)&tk, 0, sizeof(tk)); - - /* and we're done. */ - } - - /* The precalc and import routines here rely on the fact that we pad - * the key out to 64 bytes and use that to initialize the md5 - * contexts, and that updating an md5 context with 64 bytes of data - * leaves nothing left over; all of the interesting state is contained - * in the state field, and none of it is left over in the count and - * buffer fields. So all we have to do is save the state field; we - * can zero the others when we reload it. Which is why the decision - * was made to pad the key out to 64 bytes in the first place. */ - inline - void hmac_md5_precalc(HMAC_MD5_STATE *state, - const unsigned char *key, - int key_len) - { - HMAC_MD5_CTX hmac; - unsigned lupe; - - hmac_md5_init(&hmac, key, key_len); - for (lupe = 0; lupe < 4; lupe++) { - state->istate[lupe] = htonl(hmac.ictx.state[lupe]); - state->ostate[lupe] = htonl(hmac.octx.state[lupe]); - } - MD5_memset( (POINTER)&hmac, 0, sizeof(hmac)); - } - - - inline - void hmac_md5_import(HMAC_MD5_CTX *hmac, - HMAC_MD5_STATE *state) - { - unsigned lupe; - MD5_memset( (POINTER)hmac, 0, sizeof(HMAC_MD5_CTX)); - for (lupe = 0; lupe < 4; lupe++) { - hmac->ictx.state[lupe] = ntohl(state->istate[lupe]); - hmac->octx.state[lupe] = ntohl(state->ostate[lupe]); - } - /* Init the counts to account for our having applied - * 64 bytes of key; this works out to 0x200 (64 << 3; see - * MD5Update above...) */ - hmac->ictx.count[0] = hmac->octx.count[0] = 0x200; - } - - inline - void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], - HMAC_MD5_CTX *hmac) - { - MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */ - MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */ - MD5Final(digest, &hmac->octx); /* Finalize outer md5 */ - } - - - void hmac_md5(const unsigned char* text, int text_len, const unsigned char* key, int key_len, unsigned char *digest) - { - MD5_CTX context; - - unsigned char k_ipad[65]; /* inner padding - - * key XORd with ipad - */ - unsigned char k_opad[65]; /* outer padding - - * key XORd with opad - */ - unsigned char tk[16]; - int i; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - - MD5_CTX tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - MD5_memset(k_ipad, '\0', sizeof k_ipad); - MD5_memset(k_opad, '\0', sizeof k_opad); - MD5_memcpy( k_ipad, (POINTER)key, key_len); - MD5_memcpy( k_opad, (POINTER)key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - /* - * perform inner MD5 - */ - - MD5Init(&context); /* init context for 1st - * pass */ - MD5Update(&context, k_ipad, 64); /* start with inner pad */ - MD5Update(&context, text, text_len); /* then text of datagram */ - MD5Final(digest, &context); /* finish up 1st pass */ - - /* - * perform outer MD5 - */ - MD5Init(&context); /* init context for 2nd - * pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, digest, 16); /* then results of 1st - * hash */ - MD5Final(digest, &context); /* finish up 2nd pass */ - - } -} diff --git a/src/Native/libcryptonote/contrib/epee/include/md5global.h b/src/Native/libcryptonote/contrib/epee/include/md5global.h deleted file mode 100644 index afc229019..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/md5global.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * $Id: md5global.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $ - */ - -/* GLOBAL.H - RSAREF types and constants - */ - -#ifndef MD5GLOBAL_H -#define MD5GLOBAL_H - -namespace md5 -{ - - - /* PROTOTYPES should be set to one if and only if the compiler supports - function argument prototyping. - The following makes PROTOTYPES default to 0 if it has not already - been defined with C compiler flags. - */ -#ifndef PROTOTYPES -#define PROTOTYPES 0 -#endif - - /* POINTER defines a generic pointer type */ - typedef unsigned char *POINTER; - - /* UINT2 defines a two byte word */ - typedef unsigned short int UINT2; - - /* UINT4 defines a four byte word */ - //typedef unsigned long int UINT4; - typedef unsigned int UINT4; - - /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. - If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it - returns an empty list. - */ -#if PROTOTYPES -#define PROTO_LIST(list) list -#else -#define PROTO_LIST(list) () -#endif - -} - -#endif diff --git a/src/Native/libcryptonote/contrib/epee/include/memwipe.h b/src/Native/libcryptonote/contrib/epee/include/memwipe.h index 0d8f491b7..d586608cb 100644 --- a/src/Native/libcryptonote/contrib/epee/include/memwipe.h +++ b/src/Native/libcryptonote/contrib/epee/include/memwipe.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/src/Native/libcryptonote/contrib/epee/include/misc_language.h b/src/Native/libcryptonote/contrib/epee/include/misc_language.h index d5157365c..5f7202150 100644 --- a/src/Native/libcryptonote/contrib/epee/include/misc_language.h +++ b/src/Native/libcryptonote/contrib/epee/include/misc_language.h @@ -147,7 +147,8 @@ namespace misc_utils {} ~call_befor_die() { - m_func(); + try { m_func(); } + catch (...) { /* ignore */ } } }; @@ -158,5 +159,10 @@ namespace misc_utils return slc; } + template struct struct_init: T + { + struct_init(): T{} {} + }; + } } diff --git a/src/Native/libcryptonote/contrib/epee/include/misc_log_ex.h b/src/Native/libcryptonote/contrib/epee/include/misc_log_ex.h index e738c6714..3c5169d9e 100644 --- a/src/Native/libcryptonote/contrib/epee/include/misc_log_ex.h +++ b/src/Native/libcryptonote/contrib/epee/include/misc_log_ex.h @@ -28,47 +28,27 @@ #ifndef _MISC_LOG_EX_H_ #define _MISC_LOG_EX_H_ -#include "static_initializer.h" -#include "string_tools.h" -#include "time_helper.h" -#include "misc_os_dependent.h" - -#include "syncobj.h" - -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -// OW: #include "easylogging++.h" +//#include "easylogging++.h" +#undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "default" -// OW: -//#define MCFATAL(cat,x) CLOG(FATAL,cat) << x -//#define MCERROR(cat,x) CLOG(ERROR,cat) << x -//#define MCWARNING(cat,x) CLOG(WARNING,cat) << x -//#define MCINFO(cat,x) CLOG(INFO,cat) << x -//#define MCDEBUG(cat,x) CLOG(DEBUG,cat) << x -//#define MCTRACE(cat,x) CLOG(TRACE,cat) << x -//#define MCLOG(level,cat,x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::NormalLog, cat) << x - -#define MCFATAL(cat,x) -#define MCERROR(cat,x) -#define MCWARNING(cat,x) -#define MCINFO(cat,x) -#define MCDEBUG(cat,x) -#define MCTRACE(cat,x) -#define MCLOG(level,cat,x) +#define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes +#define MAX_LOG_FILES 50 + +#define MCLOG_TYPE(level, cat, type, x) + +#define MCLOG(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::NormalLog, x) +#define MCLOG_FILE(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::FileOnlyLog, x) + +#define MCFATAL(cat,x) MCLOG(el::Level::Fatal,cat, x) +#define MCERROR(cat,x) MCLOG(el::Level::Error,cat, x) +#define MCWARNING(cat,x) MCLOG(el::Level::Warning,cat, x) +#define MCINFO(cat,x) MCLOG(el::Level::Info,cat, x) +#define MCDEBUG(cat,x) MCLOG(el::Level::Debug,cat, x) +#define MCTRACE(cat,x) MCLOG(el::Level::Trace,cat, x) #define MCLOG_COLOR(level,cat,color,x) MCLOG(level,cat,"\033[1;" color "m" << x << "\033[0m") #define MCLOG_RED(level,cat,x) MCLOG_COLOR(level,cat,"31",x) @@ -101,6 +81,16 @@ #define MGINFO_MAGENTA(x) MCLOG_MAGENTA(el::Level::Info, "global",x) #define MGINFO_CYAN(x) MCLOG_CYAN(el::Level::Info, "global",x) +#define IFLOG(level, cat, type, init, x) \ + do { \ + if (ELPP->vRegistry()->allowed(level, cat)) { \ + init; \ + el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \ + } \ + } while(0) +#define MIDEBUG(init, x) IFLOG(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY, el::base::DispatchAction::NormalLog, init, x) + + #define LOG_ERROR(x) MERROR(x) #define LOG_PRINT_L0(x) MWARNING(x) #define LOG_PRINT_L1(x) MINFO(x) @@ -112,9 +102,9 @@ #define _dbg2(x) MDEBUG(x) #define _dbg1(x) MDEBUG(x) #define _info(x) MINFO(x) -#define _note(x) MINFO(x) -#define _fact(x) MINFO(x) -#define _mark(x) MINFO(x) +#define _note(x) MDEBUG(x) +#define _fact(x) MDEBUG(x) +#define _mark(x) MDEBUG(x) #define _warn(x) MWARNING(x) #define _erro(x) MERROR(x) @@ -131,8 +121,9 @@ #endif std::string mlog_get_default_log_path(const char *default_filename); -void mlog_configure(const std::string &filename_base, bool console); +void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size = MAX_LOG_FILE_SIZE, const std::size_t max_log_files = MAX_LOG_FILES); void mlog_set_categories(const char *categories); +std::string mlog_get_categories(); void mlog_set_log_level(int level); void mlog_set_log(const char *log); @@ -175,7 +166,7 @@ namespace debug #define ASSERT_MES_AND_THROW(message) {LOG_ERROR(message); std::stringstream ss; ss << message; throw std::runtime_error(ss.str());} -#define CHECK_AND_ASSERT_THROW_MES(expr, message) {if(!(expr)) ASSERT_MES_AND_THROW(message);} +#define CHECK_AND_ASSERT_THROW_MES(expr, message) do {if(!(expr)) ASSERT_MES_AND_THROW(message);} while(0) #ifndef CHECK_AND_ASSERT diff --git a/src/Native/libcryptonote/contrib/epee/include/misc_os_dependent.h b/src/Native/libcryptonote/contrib/epee/include/misc_os_dependent.h index ffe575501..7ad63ad2a 100644 --- a/src/Native/libcryptonote/contrib/epee/include/misc_os_dependent.h +++ b/src/Native/libcryptonote/contrib/epee/include/misc_os_dependent.h @@ -24,7 +24,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #ifdef _WIN32 -#include +#include #endif #ifdef WIN32 @@ -91,37 +91,21 @@ namespace misc_utils } - inline int call_sys_cmd(const std::string& cmd) - { - std::cout << "# " << cmd << std::endl; - - FILE * fp ; - //char tstCommand[] ="ls *"; - char path[1000] = {0}; -#if !defined(__GNUC__) - fp = _popen(cmd.c_str(), "r"); -#else - fp = popen(cmd.c_str(), "r"); -#endif - while ( fgets( path, 1000, fp ) != NULL ) - std::cout << path; - -#if !defined(__GNUC__) - _pclose(fp); -#else - pclose(fp); -#endif - return 0; - - } - - inline std::string get_thread_string_id() { #if defined(_WIN32) return boost::lexical_cast(GetCurrentThreadId()); #elif defined(__GNUC__) return boost::lexical_cast(pthread_self()); +#endif + } + + inline bool get_gmt_time(time_t t, struct tm &tm) + { +#ifdef _WIN32 + return gmtime_s(&tm, &t); +#else + return gmtime_r(&t, &tm); #endif } } diff --git a/src/Native/libcryptonote/contrib/epee/include/mlocker.h b/src/Native/libcryptonote/contrib/epee/include/mlocker.h new file mode 100644 index 000000000..a6d94b3d2 --- /dev/null +++ b/src/Native/libcryptonote/contrib/epee/include/mlocker.h @@ -0,0 +1,87 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#include +#include + +namespace epee +{ + class mlocker + { + public: + mlocker(void *ptr, size_t len); + ~mlocker(); + + static size_t get_page_size(); + static size_t get_num_locked_pages(); + static size_t get_num_locked_objects(); + + static void lock(void *ptr, size_t len); + static void unlock(void *ptr, size_t len); + + private: + static size_t page_size; + static size_t num_locked_objects; + + static boost::mutex &mutex(); + static std::map &map(); + static void lock_page(size_t page); + static void unlock_page(size_t page); + + void *ptr; + size_t len; + }; + + /// Locks memory while in scope + /// + /// Primarily useful for making sure that private keys don't get swapped out + // to disk + template + struct mlocked : public T { + using type = T; + + mlocked(): T() { mlocker::lock(this, sizeof(T)); } + mlocked(const T &t): T(t) { mlocker::lock(this, sizeof(T)); } + mlocked(const mlocked &mt): T(mt) { mlocker::lock(this, sizeof(T)); } + mlocked(const T &&t): T(t) { mlocker::lock(this, sizeof(T)); } + mlocked(const mlocked &&mt): T(mt) { mlocker::lock(this, sizeof(T)); } + mlocked &operator=(const mlocked &mt) { T::operator=(mt); return *this; } + ~mlocked() { try { mlocker::unlock(this, sizeof(T)); } catch (...) { /* do not propagate */ } } + }; + + template + T& unwrap(mlocked& src) { return src; } + + template + const T& unwrap(mlocked const& src) { return src; } + + template + using mlocked_arr = mlocked>; +} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server.h b/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server.h deleted file mode 100644 index cbad1717c..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server.h +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _ABSTRACT_TCP_SERVER_H_ -#define _ABSTRACT_TCP_SERVER_H_ - -#include -#include -#include -#include "winobj.h" -//#include "threads_helper.h" -#include "net_utils_base.h" - -#pragma comment(lib, "Ws2_32.lib") - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace net_utils -{ - /************************************************************************/ - /* */ - /************************************************************************/ - class soket_sender: public i_service_endpoint - { - public: - soket_sender(SOCKET sock):m_sock(sock){} - private: - virtual bool handle_send(const void* ptr, size_t cb) - { - if(cb != send(m_sock, (char*)ptr, (int)cb, 0)) - { - int sock_err = WSAGetLastError(); - LOG_ERROR("soket_sender: Failed to send " << cb << " bytes, Error=" << sock_err); - return false; - } - return true; - - } - - SOCKET m_sock; - }; - - - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class abstract_tcp_server - { - public: - abstract_tcp_server(); - - bool init_server(int port_no); - bool deinit_server(); - bool run_server(); - bool send_stop_signal(); - - typename THandler::config_type& get_config_object(){return m_config;} - - private: - bool invoke_connection(SOCKET hnew_sock, long ip_from, int post_from); - static unsigned __stdcall ConnectionHandlerProc(void* lpParameter); - - class thread_context; - typedef std::list connections_container; - typedef typename connections_container::iterator connections_iterator; - - struct thread_context - { - HANDLE m_htread; - SOCKET m_socket; - abstract_tcp_server* powner; - connection_context m_context; - typename connections_iterator m_self_it; - }; - - SOCKET m_listen_socket; - int m_port; - bool m_initialized; - volatile LONG m_stop_server; - volatile LONG m_threads_count; - typename THandler::config_type m_config; - connections_container m_connections; - critical_section m_connections_lock; - }; - - template - unsigned __stdcall abstract_tcp_server::ConnectionHandlerProc(void* lpParameter) - { - - thread_context* pthread_context = (thread_context*)lpParameter; - if(!pthread_context) - return 0; - abstract_tcp_server* pthis = pthread_context->powner; - - ::InterlockedIncrement(&pthis->m_threads_count); - - ::CoInitialize(NULL); - - - LOG_PRINT("Handler thread STARTED with socket=" << pthread_context->m_socket, LOG_LEVEL_2); - int res = 0; - - soket_sender sndr(pthread_context->m_socket); - THandler srv(&sndr, pthread_context->powner->m_config, pthread_context->m_context); - - - srv.after_init_connection(); - - char buff[1000] = {0}; - std::string ansver; - while ( (res = recv(pthread_context->m_socket, (char*)buff, 1000, 0)) > 0) - { - LOG_PRINT("Data in, " << res << " bytes", LOG_LEVEL_3); - if(!srv.handle_recv(buff, res)) - break; - } - shutdown(pthread_context->m_socket, SD_BOTH); - closesocket(pthread_context->m_socket); - - abstract_tcp_server* powner = pthread_context->powner; - LOG_PRINT("Handler thread with socket=" << pthread_context->m_socket << " STOPPED", LOG_LEVEL_2); - powner->m_connections_lock.lock(); - ::CloseHandle(pthread_context->m_htread); - pthread_context->powner->m_connections.erase(pthread_context->m_self_it); - powner->m_connections_lock.unlock(); - CoUninitialize(); - ::InterlockedDecrement(&pthis->m_threads_count); - return 1; - } - //---------------------------------------------------------------------------------------- - template - abstract_tcp_server::abstract_tcp_server():m_listen_socket(INVALID_SOCKET), - m_initialized(false), - m_stop_server(0), m_port(0), m_threads_count(0) - { - - } - - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::init_server(int port_no) - { - m_port = port_no; - WSADATA wsad = {0}; - int err = ::WSAStartup(MAKEWORD(2,2), &wsad); - if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 ) - { - LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - m_initialized = true; - - m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); - if(INVALID_SOCKET == m_listen_socket) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - int opt = 1; - setsockopt (m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast(&opt), sizeof(int)); - - sockaddr_in adr = {0}; - adr.sin_family = AF_INET; - adr.sin_addr.s_addr = htonl(INADDR_ANY); - adr.sin_port = (u_short)htons(port_no); - - err = bind(m_listen_socket, (const sockaddr*)&adr, sizeof(adr )); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - deinit_server(); - return false; - } - - ::InterlockedExchange(&m_stop_server, 0); - - return true; - } - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::deinit_server() - { - - if(!m_initialized) - return true; - - if(INVALID_SOCKET != m_listen_socket) - { - shutdown(m_listen_socket, SD_BOTH); - int res = closesocket(m_listen_socket); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_listen_socket = INVALID_SOCKET; - } - - int res = ::WSACleanup(); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_initialized = false; - - return true; - } - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::send_stop_signal() - { - InterlockedExchange(&m_stop_server, 1); - return true; - } - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::run_server() - { - int err = listen(m_listen_socket, 10000); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - LOG_PRINT("Listening port "<< m_port << "...." , LOG_LEVEL_2); - - while(!m_stop_server) - { - sockaddr_in adr_from = {0}; - int adr_len = sizeof(adr_from); - fd_set read_fs = {0}; - read_fs.fd_count = 1; - read_fs.fd_array[0] = m_listen_socket; - TIMEVAL tv = {0}; - tv.tv_usec = 100; - int select_res = select(0, &read_fs, NULL, NULL, &tv); - if(!select_res) - continue; - SOCKET new_sock = WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, NULL, NULL); - LOG_PRINT("Accepted connection on socket=" << new_sock, LOG_LEVEL_2); - invoke_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); - } - - deinit_server(); - -#define ABSTR_TCP_SRV_WAIT_COUNT_MAX 5000 -#define ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL 1000 - - int wait_count = 0; - - while(m_threads_count && wait_count*1000 < ABSTR_TCP_SRV_WAIT_COUNT_MAX) - { - ::Sleep(ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL); - wait_count++; - } - LOG_PRINT("abstract_tcp_server exit with wait count=" << wait_count*ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL << "(max=" << ABSTR_TCP_SRV_WAIT_COUNT_MAX <<")", LOG_LEVEL_0); - - return true; - } - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::invoke_connection(SOCKET hnew_sock, const network_address &remote_address) - { - m_connections_lock.lock(); - m_connections.push_back(thread_context()); - m_connections_lock.unlock(); - m_connections.back().m_socket = hnew_sock; - m_connections.back().powner = this; - m_connections.back().m_self_it = --m_connections.end(); - m_connections.back().m_context.m_remote_address = remote_address; - m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back()); // ugh, seems very risky - - return true; - } - //---------------------------------------------------------------------------------------- - - //---------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------- -} -} -#endif //_ABSTRACT_TCP_SERVER_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server2.h b/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server2.h deleted file mode 100644 index ccde928ba..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server2.h +++ /dev/null @@ -1,326 +0,0 @@ -/** -@file -@author from CrypoNote (see copyright below; Andrey N. Sabelnikov) -@monero rfree -@brief the connection templated-class for one peer connection -*/ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _ABSTRACT_TCP_SERVER2_H_ -#define _ABSTRACT_TCP_SERVER2_H_ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "net_utils_base.h" -#include "syncobj.h" -#include "connection_basic.hpp" -#include "network_throttle-detail.hpp" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -#define ABSTRACT_SERVER_SEND_QUE_MAX_COUNT 1000 - -namespace epee -{ -namespace net_utils -{ - - struct i_connection_filter - { - virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address)=0; - protected: - virtual ~i_connection_filter(){} - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - /// Represents a single connection from a client. - template - class connection - : public boost::enable_shared_from_this >, - private boost::noncopyable, - public i_service_endpoint, - public connection_basic - { - public: - typedef typename t_protocol_handler::connection_context t_connection_context; - /// Construct a connection with the given io_service. - - explicit connection( boost::asio::io_service& io_service, - typename t_protocol_handler::config_type& config, - std::atomic &ref_sock_count, // the ++/-- counter - std::atomic &sock_number, // the only increasing ++ number generator - i_connection_filter * &pfilter - ,t_connection_type connection_type); - - virtual ~connection() noexcept(false); - /// Get the socket associated with the connection. - boost::asio::ip::tcp::socket& socket(); - - /// Start the first asynchronous operation for the connection. - bool start(bool is_income, bool is_multithreaded); - - void get_context(t_connection_context& context_){context_ = context;} - - void call_back_starter(); - - void save_dbg_log(); - - - bool speed_limit_is_enabled() const; ///< tells us should we be sleeping here (e.g. do not sleep on RPC connections) - - bool cancel(); - - private: - //----------------- i_service_endpoint --------------------- - virtual bool do_send(const void* ptr, size_t cb); ///< (see do_send from i_service_endpoint) - virtual bool do_send_chunk(const void* ptr, size_t cb); ///< will send (or queue) a part of data - virtual bool close(); - virtual bool call_run_once_service_io(); - virtual bool request_callback(); - virtual boost::asio::io_service& get_io_service(); - virtual bool add_ref(); - virtual bool release(); - //------------------------------------------------------ - boost::shared_ptr > safe_shared_from_this(); - bool shutdown(); - /// Handle completion of a read operation. - void handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred); - - /// Handle completion of a write operation. - void handle_write(const boost::system::error_code& e, size_t cb); - - /// Buffer for incoming data. - boost::array buffer_; - //boost::array buffer_; - - t_connection_context context; - i_connection_filter* &m_pfilter; - - // TODO what do they mean about wait on destructor?? --rfree : - //this should be the last one, because it could be wait on destructor, while other activities possible on other threads - t_protocol_handler m_protocol_handler; - //typename t_protocol_handler::config_type m_dummy_config; - std::list > > m_self_refs; // add_ref/release support - critical_section m_self_refs_lock; - critical_section m_chunking_lock; // held while we add small chunks of the big do_send() to small do_send_chunk() - - t_connection_type m_connection_type; - - // for calculate speed (last 60 sec) - network_throttle m_throttle_speed_in; - network_throttle m_throttle_speed_out; - boost::mutex m_throttle_speed_in_mutex; - boost::mutex m_throttle_speed_out_mutex; - - public: - void setRpcStation(); - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class boosted_tcp_server - : private boost::noncopyable - { - public: - typedef boost::shared_ptr > connection_ptr; - typedef typename t_protocol_handler::connection_context t_connection_context; - /// Construct the server to listen on the specified TCP address and port, and - /// serve up files from the given directory. - - boosted_tcp_server(t_connection_type connection_type); - explicit boosted_tcp_server(boost::asio::io_service& external_io_service, t_connection_type connection_type); - ~boosted_tcp_server(); - - std::map server_type_map; - void create_server_type_map(); - - bool init_server(uint32_t port, const std::string address = "0.0.0.0"); - bool init_server(const std::string port, const std::string& address = "0.0.0.0"); - - /// Run the server's io_service loop. - bool run_server(size_t threads_count, bool wait = true, const boost::thread::attributes& attrs = boost::thread::attributes()); - - /// wait for service workers stop - bool timed_wait_server_stop(uint64_t wait_mseconds); - - /// Stop the server. - void send_stop_signal(); - - bool is_stop_signal_sent(); - - void set_threads_prefix(const std::string& prefix_name); - - bool deinit_server(){return true;} - - size_t get_threads_count(){return m_threads_count;} - - void set_connection_filter(i_connection_filter* pfilter); - - bool connect(const std::string& adr, const std::string& port, uint32_t conn_timeot, t_connection_context& cn, const std::string& bind_ip = "0.0.0.0"); - template - bool connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeot, const t_callback &cb, const std::string& bind_ip = "0.0.0.0"); - - typename t_protocol_handler::config_type& get_config_object(){return m_config;} - - int get_binded_port(){return m_port;} - - long get_connections_count() const - { - auto connections_count = (m_sock_count > 0) ? (m_sock_count - 1) : 0; // Socket count minus listening socket - return connections_count; - } - - boost::asio::io_service& get_io_service(){return io_service_;} - - struct idle_callback_conext_base - { - virtual ~idle_callback_conext_base(){} - - virtual bool call_handler(){return true;} - - idle_callback_conext_base(boost::asio::io_service& io_serice): - m_timer(io_serice) - {} - boost::asio::deadline_timer m_timer; - uint64_t m_period; - }; - - template - struct idle_callback_conext: public idle_callback_conext_base - { - idle_callback_conext(boost::asio::io_service& io_serice, t_handler& h, uint64_t period): - idle_callback_conext_base(io_serice), - m_handler(h) - {this->m_period = period;} - - t_handler m_handler; - virtual bool call_handler() - { - return m_handler(); - } - }; - - template - bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms) - { - boost::shared_ptr ptr(new idle_callback_conext(io_service_, t_callback, timeout_ms)); - //needed call handler here ?... - ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); - return true; - } - - bool global_timer_handler(/*const boost::system::error_code& err, */boost::shared_ptr ptr) - { - //if handler return false - he don't want to be called anymore - if(!ptr->call_handler()) - return true; - ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); - return true; - } - - template - bool async_call(t_handler t_callback) - { - io_service_.post(t_callback); - return true; - } - - protected: - typename t_protocol_handler::config_type m_config; - - private: - /// Run the server's io_service loop. - bool worker_thread(); - /// Handle completion of an asynchronous accept operation. - void handle_accept(const boost::system::error_code& e); - - bool is_thread_worker(); - - /// The io_service used to perform asynchronous operations. - std::unique_ptr m_io_service_local_instance; - boost::asio::io_service& io_service_; - - /// Acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor acceptor_; - - std::atomic m_stop_signal_sent; - uint32_t m_port; - std::atomic m_sock_count; - std::atomic m_sock_number; - std::string m_address; - std::string m_thread_name_prefix; //TODO: change to enum server_type, now used - size_t m_threads_count; - i_connection_filter* m_pfilter; - std::vector > m_threads; - boost::thread::id m_main_thread_id; - critical_section m_threads_lock; - volatile uint32_t m_thread_index; // TODO change to std::atomic - - t_connection_type m_connection_type; - - /// The next connection to be accepted - connection_ptr new_connection_; - - boost::mutex connections_mutex; - std::set connections_; - - }; // class <>boosted_tcp_server - - -} // namespace -} // namespace - -#include "abstract_tcp_server2.inl" - -#endif diff --git a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server2.inl b/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server2.inl deleted file mode 100644 index 195ee2f0c..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server2.inl +++ /dev/null @@ -1,1148 +0,0 @@ -/** -@file -@author from CrypoNote (see copyright below; Andrey N. Sabelnikov) -@monero rfree -@brief the connection templated-class for one peer connection -*/ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -//#include "net_utils_base.h" -#include -#include -#include -#include -#include -#include -#include -#include // TODO -#include // TODO -#include "misc_language.h" -#include "pragma_comp_defs.h" - -#include -#include -#include - -#include "../../../../src/cryptonote_core/cryptonote_core.h" // e.g. for the send_stop_signal() - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -PRAGMA_WARNING_PUSH -namespace epee -{ -namespace net_utils -{ - /************************************************************************/ - /* */ - /************************************************************************/ -PRAGMA_WARNING_DISABLE_VS(4355) - - template - connection::connection( boost::asio::io_service& io_service, - typename t_protocol_handler::config_type& config, - std::atomic &ref_sock_count, // the ++/-- counter - std::atomic &sock_number, // the only increasing ++ number generator - i_connection_filter* &pfilter - ,t_connection_type connection_type - ) - : - connection_basic(io_service, ref_sock_count, sock_number), - m_protocol_handler(this, config, context), - m_pfilter( pfilter ), - m_connection_type( connection_type ), - m_throttle_speed_in("speed_in", "throttle_speed_in"), - m_throttle_speed_out("speed_out", "throttle_speed_out") - { - MDEBUG("test, connection constructor set m_connection_type="< - connection::~connection() noexcept(false) - { - if(!m_was_shutdown) - { - _dbg3("[sock " << socket_.native_handle() << "] Socket destroyed without shutdown."); - shutdown(); - } - - _dbg3("[sock " << socket_.native_handle() << "] Socket destroyed"); - } - //--------------------------------------------------------------------------------- - template - boost::asio::ip::tcp::socket& connection::socket() - { - return socket_; - } - //--------------------------------------------------------------------------------- - template - boost::shared_ptr > connection::safe_shared_from_this() - { - try - { - return connection::shared_from_this(); - } - catch (const boost::bad_weak_ptr&) - { - // It happens when the connection is being deleted - return boost::shared_ptr >(); - } - } - //--------------------------------------------------------------------------------- - template - bool connection::start(bool is_income, bool is_multithreaded) - { - TRY_ENTRY(); - - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - - m_is_multithreaded = is_multithreaded; - - boost::system::error_code ec; - auto remote_ep = socket_.remote_endpoint(ec); - CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get remote endpoint: " << ec.message() << ':' << ec.value()); - CHECK_AND_NO_ASSERT_MES(remote_ep.address().is_v4(), false, "IPv6 not supported here"); - - auto local_ep = socket_.local_endpoint(ec); - CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get local endpoint: " << ec.message() << ':' << ec.value()); - - context = boost::value_initialized(); - const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())}; - - // create a random uuid - boost::uuids::uuid random_uuid; - // that stuff turns out to be included, even though it's from src... Taking advantage - random_uuid = crypto::rand(); - - context.set_details(random_uuid, epee::net_utils::ipv4_network_address(ip_, remote_ep.port()), is_income); - _dbg3("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) << - " to " << local_ep.address().to_string() << ':' << local_ep.port() << - ", total sockets objects " << m_ref_sock_count); - - if(m_pfilter && !m_pfilter->is_remote_host_allowed(context.m_remote_address)) - { - _dbg2("[sock " << socket_.native_handle() << "] host denied " << context.m_remote_address.host_str() << ", shutdowning connection"); - close(); - return false; - } - - m_protocol_handler.after_init_connection(); - - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, self, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); -#if !defined(_WIN32) || !defined(__i686) - // not supported before Windows7, too lazy for runtime check - // Just exclude for 32bit windows builds - //set ToS flag - int tos = get_tos_flag(); - boost::asio::detail::socket_option::integer< IPPROTO_IP, IP_TOS > - optionTos( tos ); - socket_.set_option( optionTos ); - //_dbg1("Set ToS flag to " << tos); -#endif - - boost::asio::ip::tcp::no_delay noDelayOption(false); - socket_.set_option(noDelayOption); - - return true; - - CATCH_ENTRY_L0("connection::start()", false); - } - //--------------------------------------------------------------------------------- - template - bool connection::request_callback() - { - TRY_ENTRY(); - _dbg2("[" << print_connection_context_short(context) << "] request_callback"); - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - - strand_.post(boost::bind(&connection::call_back_starter, self)); - CATCH_ENTRY_L0("connection::request_callback()", false); - return true; - } - //--------------------------------------------------------------------------------- - template - boost::asio::io_service& connection::get_io_service() - { - return socket_.get_io_service(); - } - //--------------------------------------------------------------------------------- - template - bool connection::add_ref() - { - TRY_ENTRY(); - - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - //_dbg3("[sock " << socket_.native_handle() << "] add_ref, m_peer_number=" << mI->m_peer_number); - CRITICAL_REGION_LOCAL(self->m_self_refs_lock); - //_dbg3("[sock " << socket_.native_handle() << "] add_ref 2, m_peer_number=" << mI->m_peer_number); - if(m_was_shutdown) - return false; - m_self_refs.push_back(self); - return true; - CATCH_ENTRY_L0("connection::add_ref()", false); - } - //--------------------------------------------------------------------------------- - template - bool connection::release() - { - TRY_ENTRY(); - boost::shared_ptr > back_connection_copy; - LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] release"); - CRITICAL_REGION_BEGIN(m_self_refs_lock); - CHECK_AND_ASSERT_MES(m_self_refs.size(), false, "[sock " << socket_.native_handle() << "] m_self_refs empty at connection::release() call"); - //erasing from container without additional copy can cause start deleting object, including m_self_refs - back_connection_copy = m_self_refs.back(); - m_self_refs.pop_back(); - CRITICAL_REGION_END(); - return true; - CATCH_ENTRY_L0("connection::release()", false); - } - //--------------------------------------------------------------------------------- - template - void connection::call_back_starter() - { - TRY_ENTRY(); - _dbg2("[" << print_connection_context_short(context) << "] fired_callback"); - m_protocol_handler.handle_qued_callback(); - CATCH_ENTRY_L0("connection::call_back_starter()", void()); - } - //--------------------------------------------------------------------------------- - template - void connection::save_dbg_log() - { - std::string address, port; - boost::system::error_code e; - - boost::asio::ip::tcp::endpoint endpoint = socket_.remote_endpoint(e); - if (e) - { - address = ""; - port = ""; - } - else - { - address = endpoint.address().to_string(); - port = boost::lexical_cast(endpoint.port()); - } - MDEBUG(" connection type " << to_string( m_connection_type ) << " " - << socket_.local_endpoint().address().to_string() << ":" << socket_.local_endpoint().port() - << " <--> " << address << ":" << port); - } - //--------------------------------------------------------------------------------- - template - void connection::handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred) - { - TRY_ENTRY(); - //_info("[sock " << socket_.native_handle() << "] Async read calledback."); - - if (!e) - { - { - CRITICAL_REGION_LOCAL(m_throttle_speed_in_mutex); - m_throttle_speed_in.handle_trafic_exact(bytes_transferred); - context.m_current_speed_down = m_throttle_speed_in.get_current_speed(); - } - - { - CRITICAL_REGION_LOCAL( epee::net_utils::network_throttle_manager::network_throttle_manager::m_lock_get_global_throttle_in ); - epee::net_utils::network_throttle_manager::network_throttle_manager::get_global_throttle_in().handle_trafic_exact(bytes_transferred); - } - - double delay=0; // will be calculated - how much we should sleep to obey speed limit etc - - - if (speed_limit_is_enabled()) { - do // keep sleeping if we should sleep - { - { //_scope_dbg1("CRITICAL_REGION_LOCAL"); - CRITICAL_REGION_LOCAL( epee::net_utils::network_throttle_manager::m_lock_get_global_throttle_in ); - delay = epee::net_utils::network_throttle_manager::get_global_throttle_in().get_sleep_time_after_tick( bytes_transferred ); - } - - delay *= 0.5; - if (delay > 0) { - long int ms = (long int)(delay * 100); - boost::this_thread::sleep_for(boost::chrono::milliseconds(ms)); - } - } while(delay > 0); - } // any form of sleeping - - //_info("[sock " << socket_.native_handle() << "] RECV " << bytes_transferred); - logger_handle_net_read(bytes_transferred); - context.m_last_recv = time(NULL); - context.m_recv_cnt += bytes_transferred; - bool recv_res = m_protocol_handler.handle_recv(buffer_.data(), bytes_transferred); - if(!recv_res) - { - //_info("[sock " << socket_.native_handle() << "] protocol_want_close"); - - //some error in protocol, protocol handler ask to close connection - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); - bool do_shutdown = false; - CRITICAL_REGION_BEGIN(m_send_que_lock); - if(!m_send_que.size()) - do_shutdown = true; - CRITICAL_REGION_END(); - if(do_shutdown) - shutdown(); - }else - { - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, connection::shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - //_info("[sock " << socket_.native_handle() << "]Async read requested."); - } - }else - { - _dbg3("[sock " << socket_.native_handle() << "] Some not success at read: " << e.message() << ':' << e.value()); - if(e.value() != 2) - { - _dbg3("[sock " << socket_.native_handle() << "] Some problems at read: " << e.message() << ':' << e.value()); - shutdown(); - } - } - // If an error occurs then no new asynchronous operations are started. This - // means that all shared_ptr references to the connection object will - // disappear and the object will be destroyed automatically after this - // handler returns. The connection class's destructor closes the socket. - CATCH_ENTRY_L0("connection::handle_read", void()); - } - //--------------------------------------------------------------------------------- - template - bool connection::call_run_once_service_io() - { - TRY_ENTRY(); - if(!m_is_multithreaded) - { - //single thread model, we can wait in blocked call - size_t cnt = socket_.get_io_service().run_one(); - if(!cnt)//service is going to quit - return false; - }else - { - //multi thread model, we can't(!) wait in blocked call - //so we make non blocking call and releasing CPU by calling sleep(0); - //if no handlers were called - //TODO: Maybe we need to have have critical section + event + callback to upper protocol to - //ask it inside(!) critical region if we still able to go in event wait... - size_t cnt = socket_.get_io_service().poll_one(); - if(!cnt) - misc_utils::sleep_no_w(0); - } - - return true; - CATCH_ENTRY_L0("connection::call_run_once_service_io", false); - } - //--------------------------------------------------------------------------------- - template - bool connection::do_send(const void* ptr, size_t cb) { - TRY_ENTRY(); - - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if (!self) return false; - if (m_was_shutdown) return false; - // TODO avoid copy - - const double factor = 32; // TODO config - typedef long long signed int t_safe; // my t_size to avoid any overunderflow in arithmetic - const t_safe chunksize_good = (t_safe)( 1024 * std::max(1.0,factor) ); - const t_safe chunksize_max = chunksize_good * 2 ; - const bool allow_split = (m_connection_type == e_connection_type_RPC) ? false : true; // do not split RPC data - - CHECK_AND_ASSERT_MES(! (chunksize_max<0), false, "Negative chunksize_max" ); // make sure it is unsigned before removin sign with cast: - long long unsigned int chunksize_max_unsigned = static_cast( chunksize_max ) ; - - if (allow_split && (cb > chunksize_max_unsigned)) { - { // LOCK: chunking - epee::critical_region_t send_guard(m_chunking_lock); // *** critical *** - - MDEBUG("do_send() will SPLIT into small chunks, from packet="<( len ); - CHECK_AND_ASSERT_MES(len>0, false, "len not strictly positive"); // (redundant) - CHECK_AND_ASSERT_MES(len_unsigned < std::numeric_limits::max(), false, "Invalid len_unsigned"); // yeap we want strong < then max size, to be sure - - void *chunk_start = ((char*)ptr) + pos; - MDEBUG("chunk_start="<0, false, "pos <= 0"); - - // (in catch block, or uniq pointer) delete buf; - } // each chunk - - MDEBUG("do_send() DONE SPLIT from packet="<::do_send", false); - } // do_send() - - //--------------------------------------------------------------------------------- - template - bool connection::do_send_chunk(const void* ptr, size_t cb) - { - TRY_ENTRY(); - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - if(m_was_shutdown) - return false; - { - CRITICAL_REGION_LOCAL(m_throttle_speed_out_mutex); - m_throttle_speed_out.handle_trafic_exact(cb); - context.m_current_speed_up = m_throttle_speed_out.get_current_speed(); - } - - //_info("[sock " << socket_.native_handle() << "] SEND " << cb); - context.m_last_send = time(NULL); - context.m_send_cnt += cb; - //some data should be wrote to stream - //request complete - - // No sleeping here; sleeping is done once and for all in "handle_write" - - m_send_que_lock.lock(); // *** critical *** - epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){m_send_que_lock.unlock();}); - - long int retry=0; - const long int retry_limit = 5*4; - while (m_send_que.size() > ABSTRACT_SERVER_SEND_QUE_MAX_COUNT) - { - retry++; - - /* if ( ::cryptonote::core::get_is_stopping() ) { // TODO re-add fast stop - _fact("ABORT queue wait due to stopping"); - return false; // aborted - }*/ - - long int ms = 250 + (rand()%50); - MDEBUG("Sleeping because QUEUE is FULL, in " << __FUNCTION__ << " for " << ms << " ms before packet_size="< retry_limit) { - MWARNING("send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection"); - shutdown(); - return false; - } - } - - m_send_que.resize(m_send_que.size()+1); - m_send_que.back().assign((const char*)ptr, cb); - - if(m_send_que.size() > 1) - { // active operation should be in progress, nothing to do, just wait last operation callback - auto size_now = cb; - MDEBUG("do_send() NOW just queues: packet="<::handle_write, self, _1, _2) - //) - ); - //_dbg3("(chunk): " << size_now); - //logger_handle_net_write(size_now); - //_info("[sock " << socket_.native_handle() << "] Async send requested " << m_send_que.front().size()); - } - - //do_send_handler_stop( ptr , cb ); // empty function - - return true; - - CATCH_ENTRY_L0("connection::do_send", false); - } // do_send_chunk - //--------------------------------------------------------------------------------- - template - bool connection::shutdown() - { - // Initiate graceful connection closure. - boost::system::error_code ignored_ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - m_was_shutdown = true; - m_protocol_handler.release_protocol(); - return true; - } - //--------------------------------------------------------------------------------- - template - bool connection::close() - { - TRY_ENTRY(); - //_info("[sock " << socket_.native_handle() << "] Que Shutdown called."); - size_t send_que_size = 0; - CRITICAL_REGION_BEGIN(m_send_que_lock); - send_que_size = m_send_que.size(); - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); - if(!send_que_size) - { - shutdown(); - } - - return true; - CATCH_ENTRY_L0("connection::close", false); - } - //--------------------------------------------------------------------------------- - template - bool connection::cancel() - { - return close(); - } - //--------------------------------------------------------------------------------- - template - void connection::handle_write(const boost::system::error_code& e, size_t cb) - { - TRY_ENTRY(); - LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] Async send calledback " << cb); - - if (e) - { - _dbg1("[sock " << socket_.native_handle() << "] Some problems at write: " << e.message() << ':' << e.value()); - shutdown(); - return; - } - logger_handle_net_write(cb); - - // The single sleeping that is needed for correctly handling "out" speed throttling - if (speed_limit_is_enabled()) { - sleep_before_packet(cb, 1, 1); - } - - bool do_shutdown = false; - CRITICAL_REGION_BEGIN(m_send_que_lock); - if(m_send_que.empty()) - { - _erro("[sock " << socket_.native_handle() << "] m_send_que.size() == 0 at handle_write!"); - return; - } - - m_send_que.pop_front(); - if(m_send_que.empty()) - { - if(boost::interprocess::ipcdetail::atomic_read32(&m_want_close_connection)) - { - do_shutdown = true; - } - }else - { - //have more data to send - auto size_now = m_send_que.front().size(); - MDEBUG("handle_write() NOW SENDS: packet="<::handle_write, connection::shared_from_this(), _1, _2) - // ) - ); - //_dbg3("(normal)" << size_now); - } - CRITICAL_REGION_END(); - - if(do_shutdown) - { - shutdown(); - } - CATCH_ENTRY_L0("connection::handle_write", void()); - } - - //--------------------------------------------------------------------------------- - template - void connection::setRpcStation() - { - m_connection_type = e_connection_type_RPC; - MDEBUG("set m_connection_type = RPC "); - } - - - template - bool connection::speed_limit_is_enabled() const { - return m_connection_type != e_connection_type_RPC ; - } - - /************************************************************************/ - /* */ - /************************************************************************/ - - template - boosted_tcp_server::boosted_tcp_server( t_connection_type connection_type ) : - m_io_service_local_instance(new boost::asio::io_service()), - io_service_(*m_io_service_local_instance.get()), - acceptor_(io_service_), - m_stop_signal_sent(false), m_port(0), - m_sock_count(0), m_sock_number(0), m_threads_count(0), - m_pfilter(NULL), m_thread_index(0), - m_connection_type( connection_type ), - new_connection_() - { - create_server_type_map(); - m_thread_name_prefix = "NET"; - } - - template - boosted_tcp_server::boosted_tcp_server(boost::asio::io_service& extarnal_io_service, t_connection_type connection_type) : - io_service_(extarnal_io_service), - acceptor_(io_service_), - m_stop_signal_sent(false), m_port(0), - m_sock_count(0), m_sock_number(0), m_threads_count(0), - m_pfilter(NULL), m_thread_index(0), - m_connection_type(connection_type), - new_connection_() - { - create_server_type_map(); - m_thread_name_prefix = "NET"; - } - //--------------------------------------------------------------------------------- - template - boosted_tcp_server::~boosted_tcp_server() - { - this->send_stop_signal(); - timed_wait_server_stop(10000); - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::create_server_type_map() - { - server_type_map["NET"] = e_connection_type_NET; - server_type_map["RPC"] = e_connection_type_RPC; - server_type_map["P2P"] = e_connection_type_P2P; - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::init_server(uint32_t port, const std::string address) - { - TRY_ENTRY(); - m_stop_signal_sent = false; - m_port = port; - m_address = address; - // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast(port), boost::asio::ip::tcp::resolver::query::canonical_name); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptor_.bind(endpoint); - acceptor_.listen(); - boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint(); - m_port = binded_endpoint.port(); - MDEBUG("start accept"); - new_connection_.reset(new connection(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&boosted_tcp_server::handle_accept, this, - boost::asio::placeholders::error)); - - return true; - } - catch (const std::exception &e) - { - MFATAL("Error starting server: " << e.what()); - return false; - } - catch (...) - { - MFATAL("Error starting server"); - return false; - } - } - //----------------------------------------------------------------------------- -PUSH_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) - template - bool boosted_tcp_server::init_server(const std::string port, const std::string& address) - { - uint32_t p = 0; - - if (port.size() && !string_tools::get_xtype_from_string(p, port)) { - MERROR("Failed to convert port no = " << port); - return false; - } - return this->init_server(p, address); - } -POP_WARNINGS - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::worker_thread() - { - TRY_ENTRY(); - uint32_t local_thr_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); - std::string thread_name = std::string("[") + m_thread_name_prefix; - thread_name += boost::to_string(local_thr_index) + "]"; - MLOG_SET_THREAD_NAME(thread_name); - // _fact("Thread name: " << m_thread_name_prefix); - while(!m_stop_signal_sent) - { - try - { - io_service_.run(); - } - catch(const std::exception& ex) - { - _erro("Exception at server worker thread, what=" << ex.what()); - } - catch(...) - { - _erro("Exception at server worker thread, unknown execption"); - } - } - //_info("Worker thread finished"); - return true; - CATCH_ENTRY_L0("boosted_tcp_server::worker_thread", false); - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::set_threads_prefix(const std::string& prefix_name) - { - m_thread_name_prefix = prefix_name; - auto it = server_type_map.find(m_thread_name_prefix); - if (it==server_type_map.end()) throw std::runtime_error("Unknown prefix/server type:" + std::string(prefix_name)); - auto connection_type = it->second; // the value of type - MINFO("Set server type to: " << connection_type << " from name: " << m_thread_name_prefix << ", prefix_name = " << prefix_name); - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::set_connection_filter(i_connection_filter* pfilter) - { - m_pfilter = pfilter; - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::run_server(size_t threads_count, bool wait, const boost::thread::attributes& attrs) - { - TRY_ENTRY(); - m_threads_count = threads_count; - m_main_thread_id = boost::this_thread::get_id(); - MLOG_SET_THREAD_NAME("[SRV_MAIN]"); - while(!m_stop_signal_sent) - { - - // Create a pool of threads to run all of the io_services. - CRITICAL_REGION_BEGIN(m_threads_lock); - for (std::size_t i = 0; i < threads_count; ++i) - { - boost::shared_ptr thread(new boost::thread( - attrs, boost::bind(&boosted_tcp_server::worker_thread, this))); - _note("Run server thread name: " << m_thread_name_prefix); - m_threads.push_back(thread); - } - CRITICAL_REGION_END(); - // Wait for all threads in the pool to exit. - if (wait) - { - _fact("JOINING all threads"); - for (std::size_t i = 0; i < m_threads.size(); ++i) { - m_threads[i]->join(); - } - _fact("JOINING all threads - almost"); - m_threads.clear(); - _fact("JOINING all threads - DONE"); - - } - else { - _dbg1("Reiniting OK."); - return true; - } - - if(wait && !m_stop_signal_sent) - { - //some problems with the listening socket ?.. - _dbg1("Net service stopped without stop request, restarting..."); - if(!this->init_server(m_port, m_address)) - { - _dbg1("Reiniting service failed, exit."); - return false; - }else - { - _dbg1("Reiniting OK."); - } - } - } - return true; - CATCH_ENTRY_L0("boosted_tcp_server::run_server", false); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::is_thread_worker() - { - TRY_ENTRY(); - CRITICAL_REGION_LOCAL(m_threads_lock); - BOOST_FOREACH(boost::shared_ptr& thp, m_threads) - { - if(thp->get_id() == boost::this_thread::get_id()) - return true; - } - if(m_threads_count == 1 && boost::this_thread::get_id() == m_main_thread_id) - return true; - return false; - CATCH_ENTRY_L0("boosted_tcp_server::is_thread_worker", false); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::timed_wait_server_stop(uint64_t wait_mseconds) - { - TRY_ENTRY(); - boost::chrono::milliseconds ms(wait_mseconds); - for (std::size_t i = 0; i < m_threads.size(); ++i) - { - if(m_threads[i]->joinable() && !m_threads[i]->try_join_for(ms)) - { - _dbg1("Interrupting thread " << m_threads[i]->native_handle()); - m_threads[i]->interrupt(); - } - } - return true; - CATCH_ENTRY_L0("boosted_tcp_server::timed_wait_server_stop", false); - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::send_stop_signal() - { - m_stop_signal_sent = true; - TRY_ENTRY(); - connections_mutex.lock(); - for (auto &c: connections_) - { - c->cancel(); - } - connections_.clear(); - connections_mutex.unlock(); - io_service_.stop(); - CATCH_ENTRY_L0("boosted_tcp_server::send_stop_signal()", void()); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::is_stop_signal_sent() - { - return m_stop_signal_sent; - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::handle_accept(const boost::system::error_code& e) - { - MDEBUG("handle_accept"); - TRY_ENTRY(); - if (!e) - { - if (m_connection_type == e_connection_type_RPC) { - MDEBUG("New server for RPC connections"); - new_connection_->setRpcStation(); // hopefully this is not needed actually - } - connection_ptr conn(std::move(new_connection_)); - new_connection_.reset(new connection(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&boosted_tcp_server::handle_accept, this, - boost::asio::placeholders::error)); - - boost::asio::socket_base::keep_alive opt(true); - conn->socket().set_option(opt); - - conn->start(true, 1 < m_threads_count); - conn->save_dbg_log(); - }else - { - _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count); - } - CATCH_ENTRY_L0("boosted_tcp_server::handle_accept", void()); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::connect(const std::string& adr, const std::string& port, uint32_t conn_timeout, t_connection_context& conn_context, const std::string& bind_ip) - { - TRY_ENTRY(); - - connection_ptr new_connection_l(new connection(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type) ); - connections_mutex.lock(); - connections_.insert(new_connection_l); - MDEBUG("connections_ size now " << connections_.size()); - connections_mutex.unlock(); - epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ CRITICAL_REGION_LOCAL(connections_mutex); connections_.erase(new_connection_l); }); - boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket(); - - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - _erro("Failed to resolve " << adr); - return false; - } - ////////////////////////////////////////////////////////////////////////// - - - //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - sock_.open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(adr.c_str()), 0); - sock_.bind(local_endpoint); - } - - /* - NOTICE: be careful to make sync connection from event handler: in case if all threads suddenly do sync connect, there will be no thread to dispatch events from io service. - */ - - boost::system::error_code ec = boost::asio::error::would_block; - - //have another free thread(s), work in wait mode, without event handling - struct local_async_context - { - boost::system::error_code ec; - boost::mutex connect_mut; - boost::condition_variable cond; - }; - - boost::shared_ptr local_shared_context(new local_async_context()); - local_shared_context->ec = boost::asio::error::would_block; - boost::unique_lock lock(local_shared_context->connect_mut); - auto connect_callback = [](boost::system::error_code ec_, boost::shared_ptr shared_context) - { - shared_context->connect_mut.lock(); shared_context->ec = ec_; shared_context->cond.notify_one(); shared_context->connect_mut.unlock(); - }; - - sock_.async_connect(remote_endpoint, boost::bind(connect_callback, _1, local_shared_context)); - while(local_shared_context->ec == boost::asio::error::would_block) - { - bool r = local_shared_context->cond.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(conn_timeout)); - if (m_stop_signal_sent) - { - if (sock_.is_open()) - sock_.close(); - return false; - } - if(local_shared_context->ec == boost::asio::error::would_block && !r) - { - //timeout - sock_.close(); - _dbg3("Failed to connect to " << adr << ":" << port << ", because of timeout (" << conn_timeout << ")"); - return false; - } - } - ec = local_shared_context->ec; - - if (ec || !sock_.is_open()) - { - _dbg3("Some problems at connect, message: " << ec.message()); - if (sock_.is_open()) - sock_.close(); - return false; - } - - _dbg3("Connected success to " << adr << ':' << port); - - // start adds the connection to the config object's list, so we don't need to have it locally anymore - connections_mutex.lock(); - connections_.erase(new_connection_l); - connections_mutex.unlock(); - bool r = new_connection_l->start(false, 1 < m_threads_count); - if (r) - { - new_connection_l->get_context(conn_context); - //new_connection_l.reset(new connection(io_service_, m_config, m_sock_count, m_pfilter)); - } - else - { - _erro("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection, connections_count = " << m_sock_count); - } - - new_connection_l->save_dbg_log(); - - return r; - - CATCH_ENTRY_L0("boosted_tcp_server::connect", false); - } - //--------------------------------------------------------------------------------- - template template - bool boosted_tcp_server::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip) - { - TRY_ENTRY(); - connection_ptr new_connection_l(new connection(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type) ); - connections_mutex.lock(); - connections_.insert(new_connection_l); - MDEBUG("connections_ size now " << connections_.size()); - connections_mutex.unlock(); - epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ CRITICAL_REGION_LOCAL(connections_mutex); connections_.erase(new_connection_l); }); - boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket(); - - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - _erro("Failed to resolve " << adr); - return false; - } - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - sock_.open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(adr.c_str()), 0); - sock_.bind(local_endpoint); - } - - boost::shared_ptr sh_deadline(new boost::asio::deadline_timer(io_service_)); - //start deadline - sh_deadline->expires_from_now(boost::posix_time::milliseconds(conn_timeout)); - sh_deadline->async_wait([=](const boost::system::error_code& error) - { - if(error != boost::asio::error::operation_aborted) - { - _dbg3("Failed to connect to " << adr << ':' << port << ", because of timeout (" << conn_timeout << ")"); - new_connection_l->socket().close(); - } - }); - //start async connect - sock_.async_connect(remote_endpoint, [=](const boost::system::error_code& ec_) - { - t_connection_context conn_context = AUTO_VAL_INIT(conn_context); - boost::system::error_code ignored_ec; - boost::asio::ip::tcp::socket::endpoint_type lep = new_connection_l->socket().local_endpoint(ignored_ec); - if(!ec_) - {//success - if(!sh_deadline->cancel()) - { - cb(conn_context, boost::asio::error::operation_aborted);//this mean that deadline timer already queued callback with cancel operation, rare situation - }else - { - _dbg3("[sock " << new_connection_l->socket().native_handle() << "] Connected success to " << adr << ':' << port << - " from " << lep.address().to_string() << ':' << lep.port()); - - // start adds the connection to the config object's list, so we don't need to have it locally anymore - connections_mutex.lock(); - connections_.erase(new_connection_l); - connections_mutex.unlock(); - bool r = new_connection_l->start(false, 1 < m_threads_count); - if (r) - { - new_connection_l->get_context(conn_context); - cb(conn_context, ec_); - } - else - { - _dbg3("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection to " << adr << ':' << port); - cb(conn_context, boost::asio::error::fault); - } - } - }else - { - _dbg3("[sock " << new_connection_l->socket().native_handle() << "] Failed to connect to " << adr << ':' << port << - " from " << lep.address().to_string() << ':' << lep.port() << ": " << ec_.message() << ':' << ec_.value()); - cb(conn_context, ec_); - } - }); - return true; - CATCH_ENTRY_L0("boosted_tcp_server::connect_async", false); - } - -} // namespace -} // namespace -PRAGMA_WARNING_POP diff --git a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server_cp.h b/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server_cp.h deleted file mode 100644 index f10f4203f..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server_cp.h +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _LEVIN_CP_SERVER_H_ -#define _LEVIN_CP_SERVER_H_ - -#include -#include -#include -#include -#include - -#include "misc_log_ex.h" -//#include "threads_helper.h" -#include "syncobj.h" -#define ENABLE_PROFILING -#include "profile_tools.h" -#include "net_utils_base.h" -#include "pragma_comp_defs.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -#define LEVIN_DEFAULT_DATA_BUFF_SIZE 2000 - -namespace epee -{ -namespace net_utils -{ - - template - class cp_server_impl//: public abstract_handler - { - public: - cp_server_impl(/*abstract_handler* phandler = NULL*/); - virtual ~cp_server_impl(); - - bool init_server(int port_no); - bool deinit_server(); - bool run_server(int threads_count = 0); - bool send_stop_signal(); - bool is_stop_signal(); - virtual bool on_net_idle(){return true;} - size_t get_active_connections_num(); - typename TProtocol::config_type& get_config_object(){return m_config;} - private: - enum overlapped_operation_type - { - op_type_recv, - op_type_send, - op_type_stop - }; - - struct io_data_base - { - OVERLAPPED m_overlapped; - WSABUF DataBuf; - overlapped_operation_type m_op_type; - DWORD TotalBuffBytes; - volatile LONG m_is_in_use; - char Buffer[1]; - }; - -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4355) - template - struct connection: public net_utils::i_service_endpoint - { - connection(typename TProtocol::config_type& ref_config):m_sock(INVALID_SOCKET), m_tprotocol_handler(this, ref_config, context), m_psend_data(NULL), m_precv_data(NULL), m_asked_to_shutdown(0), m_connection_shutwoned(0) - { - } - - //connection():m_sock(INVALID_SOCKET), m_tprotocol_handler(this, m_dummy_config, context), m_psend_data(NULL), m_precv_data(NULL), m_asked_to_shutdown(0), m_connection_shutwoned(0) - //{ - //} - - connection& operator=(const connection& obj) - { - return *this; - } - - bool init_buffers() - { - m_psend_data = (io_data_base*)new char[sizeof(io_data_base) + LEVIN_DEFAULT_DATA_BUFF_SIZE-1]; - m_psend_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - m_precv_data = (io_data_base*)new char[sizeof(io_data_base) + LEVIN_DEFAULT_DATA_BUFF_SIZE-1]; - m_precv_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - return true; - } - - bool query_shutdown() - { - if(!::InterlockedCompareExchange(&m_asked_to_shutdown, 1, 0)) - { - m_psend_data->m_op_type = op_type_stop; - ::PostQueuedCompletionStatus(m_completion_port, 0, (ULONG_PTR)this, &m_psend_data->m_overlapped); - } - return true; - } - - //bool set_config(typename TProtocol::config_type& config) - //{ - // this->~connection(); - // new(this) connection(config); - // return true; - //} - ~connection() - { - if(m_psend_data) - delete m_psend_data; - - if(m_precv_data) - delete m_precv_data; - } - virtual bool handle_send(const void* ptr, size_t cb) - { - PROFILE_FUNC("[handle_send]"); - if(m_psend_data->TotalBuffBytes < cb) - resize_send_buff((DWORD)cb); - - ZeroMemory(&m_psend_data->m_overlapped, sizeof(OVERLAPPED)); - m_psend_data->DataBuf.len = (u_long)cb;//m_psend_data->TotalBuffBytes; - m_psend_data->DataBuf.buf = m_psend_data->Buffer; - memcpy(m_psend_data->DataBuf.buf, ptr, cb); - m_psend_data->m_op_type = op_type_send; - InterlockedExchange(&m_psend_data->m_is_in_use, 1); - DWORD bytes_sent = 0; - DWORD flags = 0; - int res = 0; - { - PROFILE_FUNC("[handle_send] ::WSASend"); - res = ::WSASend(m_sock, &(m_psend_data->DataBuf), 1, &bytes_sent, flags, &(m_psend_data->m_overlapped), NULL); - } - - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - return true; - } - LOG_ERROR("BIG FAIL: WSASend error code not correct, res=" << res << " last_err=" << err); - ::InterlockedExchange(&m_psend_data->m_is_in_use, 0); - query_shutdown(); - //closesocket(m_psend_data); - return false; - }else if(0 == res) - { - ::InterlockedExchange(&m_psend_data->m_is_in_use, 0); - if(!bytes_sent || bytes_sent != cb) - { - int err = ::WSAGetLastError(); - LOG_ERROR("BIG FAIL: WSASend immediatly complete? but bad results, res=" << res << " last_err=" << err); - query_shutdown(); - return false; - }else - { - return true; - } - } - - return true; - } - bool resize_send_buff(DWORD new_size) - { - if(m_psend_data->TotalBuffBytes >= new_size) - return true; - - delete m_psend_data; - m_psend_data = (io_data_base*)new char[sizeof(io_data_base) + new_size-1]; - m_psend_data->TotalBuffBytes = new_size; - LOG_PRINT("Connection buffer resized up to " << new_size, LOG_LEVEL_3); - return true; - } - - - SOCKET m_sock; - net_utils::connection_context_base context; - TProtocol m_tprotocol_handler; - typename TProtocol::config_type m_dummy_config; - io_data_base* m_precv_data; - io_data_base* m_psend_data; - HANDLE m_completion_port; - volatile LONG m_asked_to_shutdown; - volatile LONG m_connection_shutwoned; - }; -PRAGMA_WARNING_POP - - bool worker_thread_member(); - static unsigned CALLBACK worker_thread(void* param); - - bool add_new_connection(SOCKET new_sock, long ip_from, int port_from); - bool shutdown_connection(connection* pconn); - - - typedef std::map > > connections_container; - SOCKET m_listen_socket; - HANDLE m_completion_port; - connections_container m_connections; - critical_section m_connections_lock; - int m_port; - volatile LONG m_stop; - //abstract_handler* m_phandler; - bool m_initialized; - volatile LONG m_worker_thread_counter; - typename TProtocol::config_type m_config; - }; -} -} -#include "abstract_tcp_server_cp.inl" - - -#endif //_LEVIN_SERVER_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server_cp.inl b/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server_cp.inl deleted file mode 100644 index e0ef6470e..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/abstract_tcp_server_cp.inl +++ /dev/null @@ -1,607 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma comment(lib, "Ws2_32.lib") - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace net_utils -{ -template -cp_server_impl::cp_server_impl(): - m_port(0), m_stop(false), - m_worker_thread_counter(0), m_listen_socket(INVALID_SOCKET) -{ -} -//------------------------------------------------------------- -template -cp_server_impl::~cp_server_impl() -{ - deinit_server(); -} -//------------------------------------------------------------- -template -bool cp_server_impl::init_server(int port_no) -{ - m_port = port_no; - - WSADATA wsad = {0}; - int err = ::WSAStartup(MAKEWORD(2,2), &wsad); - if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 ) - { - LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - m_initialized = true; - - m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); - if(INVALID_SOCKET == m_listen_socket) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - - int opt = 1; - err = setsockopt (m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast(&opt), sizeof(int)); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to setsockopt(SO_REUSEADDR), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - sockaddr_in adr = {0}; - adr.sin_family = AF_INET; - adr.sin_addr.s_addr = htonl(INADDR_ANY); - adr.sin_port = (u_short)htons(m_port); - - //binding - err = bind(m_listen_socket, (const sockaddr*)&adr, sizeof(adr )); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - m_completion_port = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); - if(INVALID_HANDLE_VALUE == m_completion_port) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to CreateIoCompletionPort, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - return true; -} -//------------------------------------------------------------- - -//------------------------------------------------------------- -static int CALLBACK CPConditionFunc( - IN LPWSABUF lpCallerId, - IN LPWSABUF lpCallerData, - IN OUT LPQOS lpSQOS, - IN OUT LPQOS lpGQOS, - IN LPWSABUF lpCalleeId, - OUT LPWSABUF lpCalleeData, - OUT GROUP FAR *g, - IN DWORD_PTR dwCallbackData - ) -{ - - /*cp_server_impl* pthis = (cp_server_impl*)dwCallbackData; - if(!pthis) - return CF_REJECT;*/ - /*if(pthis->get_active_connections_num()>=FD_SETSIZE-1) - { - LOG_PRINT("Maximum connections count overfull.", LOG_LEVEL_2); - return CF_REJECT; - }*/ - - return CF_ACCEPT; -} -//------------------------------------------------------------- -template -size_t cp_server_impl::get_active_connections_num() -{ - return m_connections.size(); -} -//------------------------------------------------------------- -template -unsigned CALLBACK cp_server_impl::worker_thread(void* param) -{ - if(!param) - return 0; - - cp_server_impl* pthis = (cp_server_impl*)param; - pthis->worker_thread_member(); - return 1; -} -//------------------------------------------------------------- -template -bool cp_server_impl::worker_thread_member() -{ - LOG_PRINT("Worker thread STARTED", LOG_LEVEL_1); - bool stop_handling = false; - while(!stop_handling) - { - PROFILE_FUNC("[worker_thread]Worker Loop"); - DWORD bytes_transfered = 0; - connection* pconnection = 0; - io_data_base* pio_data = 0; - - { - PROFILE_FUNC("[worker_thread]GetQueuedCompletionStatus"); - BOOL res = ::GetQueuedCompletionStatus (m_completion_port, &bytes_transfered , (PULONG_PTR)&pconnection, (LPOVERLAPPED *)&pio_data, INFINITE); - if (res == 0) - { - // check return code for error - int err = GetLastError(); - LOG_PRINT("GetQueuedCompletionStatus failed with error " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_1); - - if(pio_data) - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - - - continue; - } - } - - if(pio_data) - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - - - - if(!bytes_transfered && !pconnection && !pio_data) - { - //signal to stop - break; - } - if(!pconnection || !pio_data) - { - LOG_PRINT("BIG FAIL: pconnection or pio_data is empty: pconnection=" << pconnection << " pio_data=" << pio_data, LOG_LEVEL_0); - break; - } - - - - if(::InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)) - { - LOG_ERROR("InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)"); - //DebugBreak(); - } - - if(pio_data->m_op_type == op_type_stop) - { - if(!pconnection) - { - LOG_ERROR("op_type=op_type_stop, but pconnection is empty!!!"); - continue; - } - shutdown_connection(pconnection); - continue;// - } - else if(pio_data->m_op_type == op_type_send) - { - continue; - //do nothing, just queuing request - }else if(pio_data->m_op_type == op_type_recv) - { - PROFILE_FUNC("[worker_thread]m_tprotocol_handler.handle_recv"); - if(bytes_transfered) - { - bool res = pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_transfered); - if(!res) - pconnection->query_shutdown(); - } - else - { - pconnection->query_shutdown(); - continue; - } - - } - - //preparing new request, - - { - PROFILE_FUNC("[worker_thread]RECV Request small loop"); - int res = 0; - while(true) - { - LOG_PRINT("Prepearing data for WSARecv....", LOG_LEVEL_3); - ZeroMemory(&pio_data->m_overlapped, sizeof(OVERLAPPED)); - pio_data->DataBuf.len = pio_data->TotalBuffBytes; - pio_data->DataBuf.buf = pio_data->Buffer; - pio_data->m_op_type = op_type_recv; - //calling WSARecv() and go to completion waiting - DWORD bytes_recvd = 0; - DWORD flags = 0; - - LOG_PRINT("Calling WSARecv....", LOG_LEVEL_3); - ::InterlockedExchange(&pio_data->m_is_in_use, 1); - res = WSARecv(pconnection->m_sock, &(pio_data->DataBuf), 1, &bytes_recvd , &flags, &(pio_data->m_overlapped), NULL); - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - {//go pending, ok - LOG_PRINT("WSARecv return WSA_IO_PENDING", LOG_LEVEL_3); - break; - } - LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err); - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - pconnection->query_shutdown(); - break; - } - break; - /*else if(0 == res) - { - if(!bytes_recvd) - { - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - LOG_PRINT("WSARecv return 0, bytes_recvd=0, graceful close.", LOG_LEVEL_3); - int err = ::WSAGetLastError(); - //LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err); - //pconnection->query_shutdown(); - break; - }else - { - LOG_PRINT("WSARecv return immediatily 0, bytes_recvd=" << bytes_recvd, LOG_LEVEL_3); - //pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_recvd); - } - }*/ - } - } - } - - - LOG_PRINT("Worker thread STOPED", LOG_LEVEL_1); - ::InterlockedDecrement(&m_worker_thread_counter); - return true; -} -//------------------------------------------------------------- -template -bool cp_server_impl::shutdown_connection(connection* pconn) -{ - PROFILE_FUNC("[shutdown_connection]"); - - if(!pconn) - { - LOG_ERROR("Attempt to remove null pptr connection!"); - return false; - } - else - { - LOG_PRINT("Shutting down connection ("<< pconn << ")", LOG_LEVEL_3); - } - m_connections_lock.lock(); - connections_container::iterator it = m_connections.find(pconn->m_sock); - m_connections_lock.unlock(); - if(it == m_connections.end()) - { - LOG_ERROR("Failed to find closing socket=" << pconn->m_sock); - return false; - } - SOCKET sock = it->second->m_sock; - { - PROFILE_FUNC("[shutdown_connection] shutdown, close"); - ::shutdown(it->second->m_sock, SD_SEND ); - } - size_t close_sock_wait_count = 0; - { - LOG_PRINT("Entered to 'in_use wait zone'", LOG_LEVEL_3); - PROFILE_FUNC("[shutdown_connection] wait for in_use"); - while(::InterlockedCompareExchange(&it->second->m_precv_data->m_is_in_use, 1, 1)) - { - - Sleep(100); - close_sock_wait_count++; - } - LOG_PRINT("First step to 'in_use wait zone'", LOG_LEVEL_3); - - - while(::InterlockedCompareExchange(&it->second->m_psend_data->m_is_in_use, 1, 1)) - { - Sleep(100); - close_sock_wait_count++; - } - LOG_PRINT("Leaved 'in_use wait zone'", LOG_LEVEL_3); - } - - ::closesocket(it->second->m_sock); - - ::InterlockedExchange(&it->second->m_connection_shutwoned, 1); - m_connections_lock.lock(); - m_connections.erase(it); - m_connections_lock.unlock(); - LOG_PRINT("Socked " << sock << " closed, wait_count=" << close_sock_wait_count, LOG_LEVEL_2); - return true; -} -//------------------------------------------------------------- -template -bool cp_server_impl::run_server(int threads_count = 0) -{ - int err = listen(m_listen_socket, 100); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - if(!threads_count) - { - SYSTEM_INFO si = {0}; - ::GetSystemInfo(&si); - threads_count = si.dwNumberOfProcessors + 2; - } - for(int i = 0; i != threads_count; i++) - { - boost::thread(boost::bind(&cp_server_impl::worker_thread_member, this)); - //HANDLE h_thread = threads_helper::create_thread(worker_thread, this); - InterlockedIncrement(&m_worker_thread_counter); - //::CloseHandle(h_thread); - } - - LOG_PRINT("Numbers of worker threads started: " << threads_count, LOG_LEVEL_1); - - m_stop = false; - while(!m_stop) - { - PROFILE_FUNC("[run_server] main_loop"); - TIMEVAL tv = {0}; - tv.tv_sec = 0; - tv.tv_usec = 100; - fd_set sock_set; - sock_set.fd_count = 1; - sock_set.fd_array[0] = m_listen_socket; - int select_res = 0; - { - PROFILE_FUNC("[run_server] select"); - select_res = select(0, &sock_set, &sock_set, NULL, &tv); - } - - if(SOCKET_ERROR == select_res) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to select, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - if(!select_res) - { - on_net_idle(); - continue; - } - else - { - sockaddr_in adr_from = {0}; - int adr_len = sizeof(adr_from); - SOCKET new_sock = INVALID_SOCKET; - { - PROFILE_FUNC("[run_server] WSAAccept"); - new_sock = ::WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, CPConditionFunc, (DWORD_PTR)this); - } - - if(INVALID_SOCKET == new_sock) - { - if(m_stop) - break; - int err = ::WSAGetLastError(); - LOG_PRINT("Failed to WSAAccept, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - continue; - } - LOG_PRINT("Accepted connection (new socket=" << new_sock << ")", LOG_LEVEL_2); - { - PROFILE_FUNC("[run_server] Add new connection"); - add_new_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); - } - - } - - } - LOG_PRINT("Closing connections("<< m_connections.size() << ") and waiting...", LOG_LEVEL_2); - m_connections_lock.lock(); - for(connections_container::iterator it = m_connections.begin(); it != m_connections.end(); it++) - { - ::shutdown(it->second->m_sock, SD_BOTH); - ::closesocket(it->second->m_sock); - } - m_connections_lock.unlock(); - size_t wait_count = 0; - while(m_connections.size() && wait_count < 100) - { - ::Sleep(100); - wait_count++; - } - LOG_PRINT("Connections closed OK (wait_count=" << wait_count << ")", LOG_LEVEL_2); - - - LOG_PRINT("Stopping worker threads("<< m_worker_thread_counter << ").", LOG_LEVEL_2); - for(int i = 0; i > ptr; - ptr.reset(new connection(m_config)); - - connection& conn = *ptr.get(); - m_connections[new_sock] = ptr; - LOG_PRINT("Add new connection zone: leaving lock", LOG_LEVEL_3); - m_connections_lock.unlock(); - conn.init_buffers(); - conn.m_sock = new_sock; - conn.context.m_remote_address = address_from; - conn.m_completion_port = m_completion_port; - { - PROFILE_FUNC("[add_new_connection] CreateIoCompletionPort"); - ::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0); - } - - //if(NULL == ::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0)) - //{ - // int err = ::GetLastError(); - // LOG_PRINT("Failed to CreateIoCompletionPort(associate socket and completion port), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - // return false; - //} - - conn.m_tprotocol_handler.after_init_connection(); - { - PROFILE_FUNC("[add_new_connection] starting loop"); - int res = 0; - while(true)//res!=SOCKET_ERROR) - { - PROFILE_FUNC("[add_new_connection] in loop time"); - conn.m_precv_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - ZeroMemory(&conn.m_precv_data->m_overlapped, sizeof(OVERLAPPED)); - conn.m_precv_data->DataBuf.len = conn.m_precv_data->TotalBuffBytes; - conn.m_precv_data->DataBuf.buf = conn.m_precv_data->Buffer; - conn.m_precv_data->m_op_type = op_type_recv; - InterlockedExchange(&conn.m_precv_data->m_is_in_use, 1); - DWORD bytes_recvd = 0; - DWORD flags = 0; - - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 1); - { - PROFILE_FUNC("[add_new_connection] ::WSARecv"); - res = ::WSARecv(conn.m_sock, &(conn.m_precv_data->DataBuf), 1, &bytes_recvd , &flags, &(conn.m_precv_data->m_overlapped), NULL); - } - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - { - break; - } - LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err << " " << log_space::get_win32_err_descr(err)); - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0); - conn.query_shutdown(); - //shutdown_connection(&conn); - break; - } - - - break; - /*else if(0 == res) - { - if(!bytes_recvd) - { - PROFILE_FUNC("[add_new_connection] shutdown_connection"); - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0); - conn.query_shutdown(); - //shutdown_connection(&conn); - break; - }else - { - PROFILE_FUNC("[add_new_connection] handle_recv"); - } - }*/ - } - } - - - - return true; -} -//------------------------------------------------------------- -template -bool cp_server_impl::deinit_server() -{ - if(!m_initialized) - return true; - - if(INVALID_SOCKET != m_listen_socket) - { - shutdown(m_listen_socket, SD_BOTH); - int res = closesocket(m_listen_socket); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_listen_socket = INVALID_SOCKET; - } - - int res = ::WSACleanup(); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_initialized = false; - - return true; -} - -//------------------------------------------------------------- -template -bool cp_server_impl::send_stop_signal() -{ - ::InterlockedExchange(&m_stop, 1); - return true; -} -//------------------------------------------------------------- -template -bool cp_server_impl::is_stop_signal() -{ - return m_stop?true:false; -} -//------------------------------------------------------------- -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/connection_basic.hpp b/src/Native/libcryptonote/contrib/epee/include/net/connection_basic.hpp deleted file mode 100644 index 095e747a5..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/connection_basic.hpp +++ /dev/null @@ -1,141 +0,0 @@ -/// @file -/// @author rfree (current maintainer in monero.cc project) -/// @brief base for connection, contains e.g. the ratelimit hooks - -// ! This file might contain variable names same as in template class connection<> -// ! from files contrib/epee/include/net/abstract_tcp_server2.* -// ! I am not a lawyer; afaik APIs, var names etc are not copyrightable ;) -// ! (how ever if in some wonderful juristdictions that is not the case, then why not make another sub-class withat that members and licence it as epee part) -// ! Working on above premise, IF this is valid in your juristdictions, then consider this code as released as: - -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* rfree: place for hanlers for the non-template base, can be used by connection<> template class in abstract_tcp_server2 file */ - -#ifndef INCLUDED_p2p_connection_basic_hpp -#define INCLUDED_p2p_connection_basic_hpp - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "net/net_utils_base.h" -#include "syncobj.h" - -namespace epee -{ -namespace net_utils -{ - - /************************************************************************/ - /* */ - /************************************************************************/ - /// Represents a single connection from a client. - -class connection_basic_pimpl; // PIMPL for this class - - enum t_connection_type { // type of the connection (of this server), e.g. so that we will know how to limit it - e_connection_type_NET = 0, // default (not used?) - e_connection_type_RPC = 1, // the rpc commands (probably not rate limited, not chunked, etc) - e_connection_type_P2P = 2 // to other p2p node (probably limited) - }; - - std::string to_string(t_connection_type type); - -class connection_basic { // not-templated base class for rapid developmet of some code parts - public: - std::unique_ptr< connection_basic_pimpl > mI; // my Implementation - - // moved here from orginal connecton<> - common member variables that do not depend on template in connection<> - volatile uint32_t m_want_close_connection; - std::atomic m_was_shutdown; - critical_section m_send_que_lock; - std::list m_send_que; - volatile bool m_is_multithreaded; - double m_start_time; - /// Strand to ensure the connection's handlers are not called concurrently. - boost::asio::io_service::strand strand_; - /// Socket for the connection. - boost::asio::ip::tcp::socket socket_; - - std::atomic &m_ref_sock_count; // reference to external counter of existing sockets that we will ++/-- - public: - // first counter is the ++/-- count of current sockets, the other socket_number is only-increasing ++ number generator - connection_basic(boost::asio::io_service& io_service, std::atomic &ref_sock_count, std::atomic &sock_number); - - virtual ~connection_basic() noexcept(false); - - // various handlers to be called from connection class: - void do_send_handler_write(const void * ptr , size_t cb); - void do_send_handler_write_from_queue(const boost::system::error_code& e, size_t cb , int q_len); // from handle_write, sending next part - - void logger_handle_net_write(size_t size); // network data written - void logger_handle_net_read(size_t size); // network data read - - void set_start_time(); - - // config for rate limit - - static void set_rate_up_limit(uint64_t limit); - static void set_rate_down_limit(uint64_t limit); - static uint64_t get_rate_up_limit(); - static uint64_t get_rate_down_limit(); - - // config misc - static void set_tos_flag(int tos); // ToS / QoS flag - static int get_tos_flag(); - - // handlers and sleep - void sleep_before_packet(size_t packet_size, int phase, int q_len); // execute a sleep ; phase is not really used now(?) - static void save_limit_to_file(int limit); ///< for dr-monero - static double get_sleep_time(size_t cb); - - static void set_save_graph(bool save_graph); -}; - -} // nameserver -} // nameserver - -#endif - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_auth.h b/src/Native/libcryptonote/contrib/epee/include/net/http_auth.h deleted file mode 100644 index 4324c41fd..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_auth.h +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#pragma once - -#include -#include -#include -#include -#include -#include -#include "wipeable_string.h" -#include "http_base.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - namespace http - { - struct login - { - login() : username(), password() {} - login(std::string username_, wipeable_string password_) - : username(std::move(username_)), password(std::move(password_)) - {} - - std::string username; - wipeable_string password; - }; - - //! Implements RFC 2617 digest auth. Digests from RFC 7616 can be added. - class http_server_auth - { - public: - struct session - { - session(login credentials_) - : credentials(std::move(credentials_)), nonce(), counter(0) - {} - - login credentials; - std::string nonce; - std::uint32_t counter; - }; - - http_server_auth() : user(), rng() {} - http_server_auth(login credentials, std::function r); - - //! \return Auth response, or `boost::none` iff `request` had valid auth. - boost::optional get_response(const http_request_info& request) - { - if (user) - return do_get_response(request); - return boost::none; - } - - private: - boost::optional do_get_response(const http_request_info& request); - - boost::optional user; - - std::function rng; - }; - - //! Implements RFC 2617 digest auth. Digests from RFC 7616 can be added. - class http_client_auth - { - public: - enum status : std::uint8_t { kSuccess = 0, kBadPassword, kParseFailure }; - - struct session - { - session(login credentials_) - : credentials(std::move(credentials_)), server(), counter(0) - {} - - struct keys - { - using algorithm = - std::function; - - keys() : nonce(), opaque(), realm(), generator() {} - keys(std::string nonce_, std::string opaque_, std::string realm_, algorithm generator_) - : nonce(std::move(nonce_)) - , opaque(std::move(opaque_)) - , realm(std::move(realm_)) - , generator(std::move(generator_)) - {} - - std::string nonce; - std::string opaque; - std::string realm; - algorithm generator; - }; - - login credentials; - keys server; - std::uint32_t counter; - }; - - http_client_auth() : user() {} - http_client_auth(login credentials); - - /*! - Clients receiving a 401 response code from the server should call this - function to process the server auth. Then, before every client request, - `get_auth_field()` should be called to retrieve the newest - authorization request. - - \return `kBadPassword` if client will never be able to authenticate, - `kParseFailure` if all server authentication responses were invalid, - and `kSuccess` if `get_auth_field` is ready to generate authorization - fields. - */ - status handle_401(const http_response_info& response) - { - if (user) - return do_handle_401(response); - return kBadPassword; - } - - /*! - After calling `handle_401`, clients should call this function to - generate an authentication field for every request. - - \return A HTTP "Authorization" field if `handle_401(...)` previously - returned `kSuccess`. - */ - boost::optional> get_auth_field( - const boost::string_ref method, const boost::string_ref uri) - { - if (user) - return do_get_auth_field(method, uri); - return boost::none; - } - - private: - status do_handle_401(const http_response_info&); - boost::optional> do_get_auth_field(boost::string_ref, boost::string_ref); - - boost::optional user; - }; - } -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_base.h b/src/Native/libcryptonote/contrib/epee/include/net/http_base.h deleted file mode 100644 index a66fb7c23..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_base.h +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include -#include -#include -#include - -#include "string_tools.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - namespace http - { - - enum http_method{ - http_method_options, - http_method_get, - http_method_post, - http_method_put, - http_method_head, - http_method_etc, - http_method_unknown - }; - - enum http_content_type - { - http_content_type_text_html, - http_content_type_image_gif, - http_content_type_other, - http_content_type_not_set - }; - - typedef std::list > fields_list; - - inline - std::string get_value_from_fields_list(const std::string& param_name, const net_utils::http::fields_list& fields) - { - fields_list::const_iterator it = fields.begin(); - for(; it != fields.end(); it++) - if(!string_tools::compare_no_case(param_name, it->first)) - break; - - if(it==fields.end()) - return std::string(); - - return it->second; - } - - - inline - std::string get_value_from_uri_line(const std::string& param_name, const std::string& uri) - { - std::string buff = "([\\?|&])"; - buff += param_name + "=([^&]*)"; - boost::regex match_param(buff.c_str(), boost::regex::icase | boost::regex::normal); - boost::smatch result; - if(boost::regex_search(uri, result, match_param, boost::match_default) && result[0].matched) - { - return result[2]; - } - return std::string(); - } - - static inline void add_field(std::string& out, const boost::string_ref name, const boost::string_ref value) - { - out.append(name.data(), name.size()).append(": "); - out.append(value.data(), value.size()).append("\r\n"); - } - static inline void add_field(std::string& out, const std::pair& field) - { - add_field(out, field.first, field.second); - } - - - struct http_header_info - { - std::string m_connection; //"Connection:" - std::string m_referer; //"Referer:" - std::string m_content_length; //"Content-Length:" - std::string m_content_type; //"Content-Type:" - std::string m_transfer_encoding;//"Transfer-Encoding:" - std::string m_content_encoding; //"Content-Encoding:" - std::string m_host; //"Host:" - std::string m_cookie; //"Cookie:" - std::string m_user_agent; //"User-Agent:" - std::string m_origin; //"Origin:" - fields_list m_etc_fields; - - void clear() - { - m_connection.clear(); - m_referer.clear(); - m_content_length.clear(); - m_content_type.clear(); - m_transfer_encoding.clear(); - m_content_encoding.clear(); - m_host.clear(); - m_cookie.clear(); - m_user_agent.clear(); - m_origin.clear(); - m_etc_fields.clear(); - } - }; - - struct uri_content - { - std::string m_path; - std::string m_query; - std::string m_fragment; - std::list > m_query_params; - }; - - struct url_content - { - std::string schema; - std::string host; - std::string uri; - uint64_t port; - uri_content m_uri_content; - }; - - - struct http_request_info - { - http_request_info():m_http_method(http_method_unknown), - m_http_ver_hi(0), - m_http_ver_lo(0), - m_have_to_block(false), - m_full_request_buf_size(0) - {} - - http_method m_http_method; - std::string m_URI; - std::string m_http_method_str; - std::string m_full_request_str; - std::string m_replace_html; - std::string m_request_head; - int m_http_ver_hi; - int m_http_ver_lo; - bool m_have_to_block; - http_header_info m_header_info; - uri_content m_uri_content; - size_t m_full_request_buf_size; - std::string m_body; - - void clear() - { - this->~http_request_info(); - new(this) http_request_info(); - } - }; - - - struct http_response_info - { - int m_response_code; - std::string m_response_comment; - fields_list m_additional_fields; - std::string m_body; - std::string m_mime_tipe; - http_header_info m_header_info; - int m_http_ver_hi;// OUT paramter only - int m_http_ver_lo;// OUT paramter only - - void clear() - { - this->~http_response_info(); - new(this) http_response_info(); - } - }; - } -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_client.h b/src/Native/libcryptonote/contrib/epee/include/net/http_client.h deleted file mode 100644 index 1edf65928..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_client.h +++ /dev/null @@ -1,994 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include - -#include "net_helper.h" -#include "http_client_base.h" - -#ifdef HTTP_ENABLE_GZIP -#include "gzip_encoding.h" -#endif - -#include "string_tools.h" -#include "reg_exp_definer.h" -#include "http_base.h" -#include "http_auth.h" -#include "to_nonconst_iterator.h" -#include "net_parse_helpers.h" -#include "syncobj.h" - -//#include "shlwapi.h" - -//#pragma comment(lib, "shlwapi.lib") - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -extern epee::critical_section gregexp_lock; - - -namespace epee -{ -namespace net_utils -{ - - /*struct url - { - public: - void parse(const std::string& url_s) - { - const string prot_end("://"); - string::const_iterator prot_i = search(url_s.begin(), url_s.end(), - prot_end.begin(), prot_end.end()); - protocol_.reserve(distance(url_s.begin(), prot_i)); - transform(url_s.begin(), prot_i, - back_inserter(protocol_), - ptr_fun(tolower)); // protocol is icase - if( prot_i == url_s.end() ) - return; - advance(prot_i, prot_end.length()); - string::const_iterator path_i = find(prot_i, url_s.end(), '/'); - host_.reserve(distance(prot_i, path_i)); - transform(prot_i, path_i, - back_inserter(host_), - ptr_fun(tolower)); // host is icase - string::const_iterator query_i = find(path_i, url_s.end(), '?'); - path_.assign(path_i, query_i); - if( query_i != url_s.end() ) - ++query_i; - query_.assign(query_i, url_s.end()); - } - - std::string protocol_; - std::string host_; - std::string path_; - std::string query_; - };*/ - - - - - //--------------------------------------------------------------------------- - static inline const char* get_hex_vals() - { - static const char hexVals[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - return hexVals; - } - - static inline const char* get_unsave_chars() - { - //static char unsave_chars[] = "\"<>%\\^[]`+$,@:;/!#?=&"; - static const char unsave_chars[] = "\"<>%\\^[]`+$,@:;!#&"; - return unsave_chars; - } - - static inline bool is_unsafe(unsigned char compare_char) - { - if(compare_char <= 32 || compare_char >= 123) - return true; - - const char* punsave = get_unsave_chars(); - - for(int ichar_pos = 0; 0!=punsave[ichar_pos] ;ichar_pos++) - if(compare_char == punsave[ichar_pos]) - return true; - - return false; - } - - static inline - std::string dec_to_hex(char num, int radix) - { - int temp=0; - std::string csTmp; - int num_char; - - num_char = (int) num; - if (num_char < 0) - num_char = 256 + num_char; - - while (num_char >= radix) - { - temp = num_char % radix; - num_char = (int)floor((float)num_char / (float)radix); - csTmp = get_hex_vals()[temp]; - } - - csTmp += get_hex_vals()[num_char]; - - if(csTmp.size() < 2) - { - csTmp += '0'; - } - - std::reverse(csTmp.begin(), csTmp.end()); - //_mbsrev((unsigned char*)csTmp.data()); - - return csTmp; - } - static inline int get_index(const char *s, char c) { const char *ptr = (const char*)memchr(s, c, 16); return ptr ? ptr-s : -1; } - static inline - std::string hex_to_dec_2bytes(const char *s) - { - const char *hex = get_hex_vals(); - int i0 = get_index(hex, toupper(s[0])); - int i1 = get_index(hex, toupper(s[1])); - if (i0 < 0 || i1 < 0) - return std::string("%") + std::string(1, s[0]) + std::string(1, s[1]); - return std::string(1, i0 * 16 | i1); - } - - static inline std::string convert(char val) - { - std::string csRet; - csRet += "%"; - csRet += dec_to_hex(val, 16); - return csRet; - } - static inline std::string conver_to_url_format(const std::string& uri) - { - - std::string result; - - for(size_t i = 0; i!= uri.size(); i++) - { - if(is_unsafe(uri[i])) - result += convert(uri[i]); - else - result += uri[i]; - - } - - return result; - } - static inline std::string convert_from_url_format(const std::string& uri) - { - - std::string result; - - for(size_t i = 0; i!= uri.size(); i++) - { - if(uri[i] == '%' && i + 2 < uri.size()) - { - result += hex_to_dec_2bytes(uri.c_str() + i + 1); - i += 2; - } - else - result += uri[i]; - - } - - return result; - } - - static inline std::string convert_to_url_format_force_all(const std::string& uri) - { - - std::string result; - - for(size_t i = 0; i!= uri.size(); i++) - { - result += convert(uri[i]); - } - - return result; - } - - - - - - namespace http - { - - template - class http_simple_client_template: public i_target_handler - { - private: - enum reciev_machine_state - { - reciev_machine_state_header, - reciev_machine_state_body_content_len, - reciev_machine_state_body_connection_close, - reciev_machine_state_body_chunked, - reciev_machine_state_done, - reciev_machine_state_error - }; - - - - enum chunked_state{ - http_chunked_state_chunk_head, - http_chunked_state_chunk_body, - http_chunked_state_done, - http_chunked_state_undefined - }; - - - net_client_type m_net_client; - std::string m_host_buff; - std::string m_port; - http_client_auth m_auth; - std::string m_header_cache; - http_response_info m_response_info; - size_t m_len_in_summary; - size_t m_len_in_remain; - //std::string* m_ptarget_buffer; - boost::shared_ptr m_pcontent_encoding_handler; - reciev_machine_state m_state; - chunked_state m_chunked_state; - std::string m_chunked_cache; - critical_section m_lock; - bool m_ssl; - - public: - explicit http_simple_client_template() - : i_target_handler() - , m_net_client() - , m_host_buff() - , m_port() - , m_auth() - , m_header_cache() - , m_response_info() - , m_len_in_summary(0) - , m_len_in_remain(0) - , m_pcontent_encoding_handler(nullptr) - , m_state() - , m_chunked_state() - , m_chunked_cache() - , m_lock() - , m_ssl(false) - {} - - const std::string &get_host() const { return m_host_buff; }; - const std::string &get_port() const { return m_port; }; - - bool set_server(const std::string& address, boost::optional user, bool ssl = false) - { - http::url_content parsed{}; - const bool r = parse_url(address, parsed); - CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address); - set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), ssl); - return true; - } - - void set_server(std::string host, std::string port, boost::optional user, bool ssl = false) - { - CRITICAL_REGION_LOCAL(m_lock); - disconnect(); - m_host_buff = std::move(host); - m_port = std::move(port); - m_auth = user ? http_client_auth{std::move(*user)} : http_client_auth{}; - m_ssl = ssl; - } - - bool connect(std::chrono::milliseconds timeout) - { - CRITICAL_REGION_LOCAL(m_lock); - return m_net_client.connect(m_host_buff, m_port, timeout, m_ssl); - } - //--------------------------------------------------------------------------- - bool disconnect() - { - CRITICAL_REGION_LOCAL(m_lock); - return m_net_client.disconnect(); - } - //--------------------------------------------------------------------------- - bool is_connected() - { - CRITICAL_REGION_LOCAL(m_lock); - return m_net_client.is_connected(); - } - //--------------------------------------------------------------------------- - virtual bool handle_target_data(std::string& piece_of_transfer) - { - CRITICAL_REGION_LOCAL(m_lock); - m_response_info.m_body += piece_of_transfer; - piece_of_transfer.clear(); - return true; - } - //--------------------------------------------------------------------------- - virtual bool on_header(const http_response_info &headers) - { - return true; - } - //--------------------------------------------------------------------------- - inline - bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - return invoke(uri, "GET", body, timeout, ppresponse_info, additional_params); - } - - //--------------------------------------------------------------------------- - inline bool invoke(const boost::string_ref uri, const boost::string_ref method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!is_connected()) - { - MDEBUG("Reconnecting..."); - if(!connect(timeout)) - { - MDEBUG("Failed to connect to " << m_host_buff << ":" << m_port); - return false; - } - } - - std::string req_buff{}; - req_buff.reserve(2048); - req_buff.append(method.data(), method.size()).append(" ").append(uri.data(), uri.size()).append(" HTTP/1.1\r\n"); - add_field(req_buff, "Host", m_host_buff); - add_field(req_buff, "Content-Length", std::to_string(body.size())); - - //handle "additional_params" - for(const auto& field : additional_params) - add_field(req_buff, field); - - for (unsigned sends = 0; sends < 2; ++sends) - { - const std::size_t initial_size = req_buff.size(); - const auto auth = m_auth.get_auth_field(method, uri); - if (auth) - add_field(req_buff, *auth); - - req_buff += "\r\n"; - //-- - - bool res = m_net_client.send(req_buff, timeout); - CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); - if(body.size()) - res = m_net_client.send(body, timeout); - CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); - - m_response_info.clear(); - m_state = reciev_machine_state_header; - if (!handle_reciev(timeout)) - return false; - if (m_response_info.m_response_code != 401) - { - if(ppresponse_info) - *ppresponse_info = std::addressof(m_response_info); - return true; - } - - switch (m_auth.handle_401(m_response_info)) - { - case http_client_auth::kSuccess: - break; - case http_client_auth::kBadPassword: - sends = 2; - break; - default: - case http_client_auth::kParseFailure: - LOG_ERROR("Bad server response for authentication"); - return false; - } - req_buff.resize(initial_size); // rollback for new auth generation - } - LOG_ERROR("Client has incorrect username/password for server requiring authentication"); - return false; - } - //--------------------------------------------------------------------------- - inline bool invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params); - } - //--------------------------------------------------------------------------- - bool test(const std::string &s, std::chrono::milliseconds timeout) // TEST FUNC ONLY - { - CRITICAL_REGION_LOCAL(m_lock); - m_net_client.set_test_data(s); - m_state = reciev_machine_state_header; - return handle_reciev(timeout); - } - //--------------------------------------------------------------------------- - private: - //--------------------------------------------------------------------------- - inline bool handle_reciev(std::chrono::milliseconds timeout) - { - CRITICAL_REGION_LOCAL(m_lock); - bool keep_handling = true; - bool need_more_data = true; - std::string recv_buffer; - while(keep_handling) - { - if(need_more_data) - { - if(!m_net_client.recv(recv_buffer, timeout)) - { - MERROR("Unexpected recv fail"); - m_state = reciev_machine_state_error; - } - if(!recv_buffer.size()) - { - //connection is going to be closed - if(reciev_machine_state_body_connection_close != m_state) - { - m_state = reciev_machine_state_error; - } - } - need_more_data = false; - } - switch(m_state) - { - case reciev_machine_state_header: - keep_handling = handle_header(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_content_len: - keep_handling = handle_body_content_len(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_connection_close: - keep_handling = handle_body_connection_close(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_chunked: - keep_handling = handle_body_body_chunked(recv_buffer, need_more_data); - break; - case reciev_machine_state_done: - keep_handling = false; - break; - case reciev_machine_state_error: - keep_handling = false; - break; - } - - } - m_header_cache.clear(); - if(m_state != reciev_machine_state_error) - { - if(m_response_info.m_header_info.m_connection.size() && !string_tools::compare_no_case("close", m_response_info.m_header_info.m_connection)) - disconnect(); - - return true; - } - else - { - LOG_PRINT_L3("Returning false because of wrong state machine. state: " << m_state); - return false; - } - } - //--------------------------------------------------------------------------- - inline - bool handle_header(std::string& recv_buff, bool& need_more_data) - { - - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - LOG_ERROR("Connection closed at handle_header"); - m_state = reciev_machine_state_error; - return false; - } - - m_header_cache += recv_buff; - recv_buff.clear(); - std::string::size_type pos = m_header_cache.find("\r\n\r\n"); - if(pos != std::string::npos) - { - recv_buff.assign(m_header_cache.begin()+pos+4, m_header_cache.end()); - m_header_cache.erase(m_header_cache.begin()+pos+4, m_header_cache.end()); - - analize_cached_header_and_invoke_state(); - if (!on_header(m_response_info)) - { - MDEBUG("Connection cancelled by on_header"); - m_state = reciev_machine_state_done; - return false; - } - m_header_cache.clear(); - if(!recv_buff.size() && (m_state != reciev_machine_state_error && m_state != reciev_machine_state_done)) - need_more_data = true; - - return true; - }else - need_more_data = true; - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_content_len(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - MERROR("Warning: Content-Len mode, but connection unexpectedly closed"); - m_state = reciev_machine_state_done; - return true; - } - CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()"); - m_len_in_remain -= recv_buff.size(); - if (!m_pcontent_encoding_handler->update_in(recv_buff)) - { - m_state = reciev_machine_state_done; - return false; - } - - if(m_len_in_remain == 0) - m_state = reciev_machine_state_done; - else - need_more_data = true; - - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_connection_close(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - m_state = reciev_machine_state_done; - return true; - } - need_more_data = true; - m_pcontent_encoding_handler->update_in(recv_buff); - - - return true; - } - //--------------------------------------------------------------------------- - inline bool is_hex_symbol(char ch) - { - - if( (ch >= '0' && ch <='9')||(ch >= 'A' && ch <='F')||(ch >= 'a' && ch <='f')) - return true; - else - return false; - } - //--------------------------------------------------------------------------- - inline - bool get_len_from_chunk_head(const std::string &chunk_head, size_t& result_size) - { - std::stringstream str_stream; - str_stream << std::hex; - if(!(str_stream << chunk_head && str_stream >> result_size)) - return false; - - return true; - } - //--------------------------------------------------------------------------- - inline - bool get_chunk_head(std::string& buff, size_t& chunk_size, bool& is_matched) - { - is_matched = false; - size_t offset = 0; - for(std::string::iterator it = buff.begin(); it!= buff.end(); it++, offset++) - { - if(!is_hex_symbol(*it)) - { - if(*it == '\r' || *it == ' ' ) - { - offset--; - continue; - } - else if(*it == '\n') - { - std::string chunk_head = buff.substr(0, offset); - if(!get_len_from_chunk_head(chunk_head, chunk_size)) - return false; - - if(0 == chunk_size) - { - //Here is a small confusion - //In brief - if the chunk is the last one we need to get terminating sequence - //along with the cipher, generally in the "ddd\r\n\r\n" form - - for(it++;it != buff.end(); it++) - { - if('\r' == *it) - continue; - else if('\n' == *it) - break; - else - { - LOG_ERROR("http_stream_filter: Wrong last chunk terminator"); - return false; - } - } - - if(it == buff.end()) - return true; - } - - buff.erase(buff.begin(), ++it); - - is_matched = true; - return true; - } - else - return false; - } - } - - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_body_chunked(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - MERROR("Warning: CHUNKED mode, but connection unexpectedly closed"); - m_state = reciev_machine_state_done; - return true; - } - m_chunked_cache += recv_buff; - recv_buff.clear(); - bool is_matched = false; - - while(true) - { - if(!m_chunked_cache.size()) - { - need_more_data = true; - break; - } - - switch(m_chunked_state) - { - case http_chunked_state_chunk_head: - if(m_chunked_cache[0] == '\n' || m_chunked_cache[0] == '\r') - { - //optimize a bit - if(m_chunked_cache[0] == '\r' && m_chunked_cache.size()>1 && m_chunked_cache[1] == '\n') - m_chunked_cache.erase(0, 2); - else - m_chunked_cache.erase(0, 1); - break; - } - if(!get_chunk_head(m_chunked_cache, m_len_in_remain, is_matched)) - { - LOG_ERROR("http_stream_filter::handle_chunked(*) Failed to get length from chunked head:" << m_chunked_cache); - m_state = reciev_machine_state_error; - return false; - } - - if(!is_matched) - { - need_more_data = true; - return true; - }else - { - m_chunked_state = http_chunked_state_chunk_body; - if(m_len_in_remain == 0) - {//last chunk, let stop the stream and fix the chunk queue. - m_state = reciev_machine_state_done; - return true; - } - m_chunked_state = http_chunked_state_chunk_body; - break; - } - break; - case http_chunked_state_chunk_body: - { - std::string chunk_body; - if(m_len_in_remain >= m_chunked_cache.size()) - { - m_len_in_remain -= m_chunked_cache.size(); - chunk_body.swap(m_chunked_cache); - }else - { - chunk_body.assign(m_chunked_cache, 0, m_len_in_remain); - m_chunked_cache.erase(0, m_len_in_remain); - m_len_in_remain = 0; - } - - if (!m_pcontent_encoding_handler->update_in(chunk_body)) - { - m_state = reciev_machine_state_error; - return false; - } - - if(!m_len_in_remain) - m_chunked_state = http_chunked_state_chunk_head; - } - break; - case http_chunked_state_done: - m_state = reciev_machine_state_done; - return true; - case http_chunked_state_undefined: - default: - LOG_ERROR("http_stream_filter::handle_chunked(): Wrong state" << m_chunked_state); - return false; - } - } - - return true; - } - //--------------------------------------------------------------------------- - inline bool parse_header(http_header_info& body_info, const std::string& m_cache_to_process) - { - MTRACE("http_stream_filter::parse_cached_header(*)"); - - const char *ptr = m_cache_to_process.c_str(); - while (ptr[0] != '\r' || ptr[1] != '\n') - { - // optional \n - if (*ptr == '\n') - ++ptr; - // an identifier composed of letters or - - const char *key_pos = ptr; - while (isalnum(*ptr) || *ptr == '_' || *ptr == '-') - ++ptr; - const char *key_end = ptr; - // optional space (not in RFC, but in previous code) - if (*ptr == ' ') - ++ptr; - CHECK_AND_ASSERT_MES(*ptr == ':', true, "http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process); - ++ptr; - // optional whitespace, but not newlines - line folding is obsolete, let's ignore it - while (isblank(*ptr)) - ++ptr; - const char *value_pos = ptr; - while (*ptr != '\r' && *ptr != '\n') - ++ptr; - const char *value_end = ptr; - // optional trailing whitespace - while (value_end > value_pos && isblank(*(value_end-1))) - --value_end; - if (*ptr == '\r') - ++ptr; - CHECK_AND_ASSERT_MES(*ptr == '\n', true, "http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process); - ++ptr; - - const std::string key = std::string(key_pos, key_end - key_pos); - const std::string value = std::string(value_pos, value_end - value_pos); - if (!key.empty()) - { - if (!string_tools::compare_no_case(key, "Connection")) - body_info.m_connection = value; - else if(!string_tools::compare_no_case(key, "Referrer")) - body_info.m_referer = value; - else if(!string_tools::compare_no_case(key, "Content-Length")) - body_info.m_content_length = value; - else if(!string_tools::compare_no_case(key, "Content-Type")) - body_info.m_content_type = value; - else if(!string_tools::compare_no_case(key, "Transfer-Encoding")) - body_info.m_transfer_encoding = value; - else if(!string_tools::compare_no_case(key, "Content-Encoding")) - body_info.m_content_encoding = value; - else if(!string_tools::compare_no_case(key, "Host")) - body_info.m_host = value; - else if(!string_tools::compare_no_case(key, "Cookie")) - body_info.m_cookie = value; - else if(!string_tools::compare_no_case(key, "User-Agent")) - body_info.m_user_agent = value; - else if(!string_tools::compare_no_case(key, "Origin")) - body_info.m_origin = value; - else - body_info.m_etc_fields.emplace_back(key, value); - } - } - return true; - } - //--------------------------------------------------------------------------- - inline bool analize_first_response_line() - { - //First line response, look like this: "HTTP/1.1 200 OK" - const char *ptr = m_header_cache.c_str(); - CHECK_AND_ASSERT_MES(!memcmp(ptr, "HTTP/", 5), false, "Invalid first response line: " + m_header_cache); - ptr += 5; - CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache); - unsigned long ul; - char *end; - ul = strtoul(ptr, &end, 10); - CHECK_AND_ASSERT_MES(ul <= INT_MAX && *end =='.', false, "Invalid first response line: " + m_header_cache); - m_response_info.m_http_ver_hi = ul; - ptr = end + 1; - CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr); - ul = strtoul(ptr, &end, 10); - CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(*end), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr); - m_response_info.m_http_ver_lo = ul; - ptr = end + 1; - while (isblank(*ptr)) - ++ptr; - CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache); - ul = strtoul(ptr, &end, 10); - CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 && isspace(*end), false, "Invalid first response line: " + m_header_cache); - m_response_info.m_response_code = ul; - ptr = end; - // ignore the optional text, till the end - while (*ptr != '\r' && *ptr != '\n') - ++ptr; - if (*ptr == '\r') - ++ptr; - CHECK_AND_ASSERT_MES(*ptr == '\n', false, "Invalid first response line: " << m_header_cache); - ++ptr; - - m_header_cache.erase(0, ptr - m_header_cache.c_str()); - return true; - } - inline - bool set_reply_content_encoder() - { - STATIC_REGEXP_EXPR_1(rexp_match_gzip, "^.*?((gzip)|(deflate))", boost::regex::icase | boost::regex::normal); - boost::smatch result; // 12 3 - if(boost::regex_search( m_response_info.m_header_info.m_content_encoding, result, rexp_match_gzip, boost::match_default) && result[0].matched) - { -#ifdef HTTP_ENABLE_GZIP - m_pcontent_encoding_handler.reset(new content_encoding_gzip(this, result[3].matched)); -#else - m_pcontent_encoding_handler.reset(new do_nothing_sub_handler(this)); - LOG_ERROR("GZIP encoding not supported in this build, please add zlib to your project and define HTTP_ENABLE_GZIP"); - return false; -#endif - } - else - { - m_pcontent_encoding_handler.reset(new do_nothing_sub_handler(this)); - } - - return true; - } - inline - bool analize_cached_header_and_invoke_state() - { - m_response_info.clear(); - analize_first_response_line(); - std::string fake_str; //gcc error workaround - - bool res = parse_header(m_response_info.m_header_info, m_header_cache); - CHECK_AND_ASSERT_MES(res, false, "http_stream_filter::analize_cached_reply_header_and_invoke_state(): failed to anilize reply header: " << m_header_cache); - - set_reply_content_encoder(); - - m_len_in_summary = 0; - bool content_len_valid = false; - if(m_response_info.m_header_info.m_content_length.size()) - content_len_valid = string_tools::get_xtype_from_string(m_len_in_summary, m_response_info.m_header_info.m_content_length); - - - - if(!m_len_in_summary && ((m_response_info.m_response_code>=100&&m_response_info.m_response_code<200) - || 204 == m_response_info.m_response_code - || 304 == m_response_info.m_response_code) ) - {//There will be no response body, server will display the local page with error - m_state = reciev_machine_state_done; - return true; - }else if(m_response_info.m_header_info.m_transfer_encoding.size()) - { - string_tools::trim(m_response_info.m_header_info.m_transfer_encoding); - if(string_tools::compare_no_case(m_response_info.m_header_info.m_transfer_encoding, "chunked")) - { - LOG_ERROR("Wrong Transfer-Encoding:" << m_response_info.m_header_info.m_transfer_encoding); - m_state = reciev_machine_state_error; - return false; - } - m_state = reciev_machine_state_body_chunked; - m_chunked_state = http_chunked_state_chunk_head; - return true; - } - else if(!m_response_info.m_header_info.m_content_length.empty()) - { - //In the response header the length was specified - if(!content_len_valid) - { - LOG_ERROR("http_stream_filter::analize_cached_reply_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="<update_in(collect_remains); - if(res) - this->stop(collect_remains); - return res; - } - }; - - - struct i_target_handler - { - virtual ~i_target_handler(){} - virtual bool handle_target_data( std::string& piece_of_transfer)=0; - }; - - - class do_nothing_sub_handler: public i_sub_handler - { - public: - do_nothing_sub_handler(i_target_handler* powner_filter):m_powner_filter(powner_filter) - {} - virtual bool update_in( std::string& piece_of_transfer) - { - return m_powner_filter->handle_target_data(piece_of_transfer); - } - virtual void stop(std::string& collect_remains) - { - - } - i_target_handler* m_powner_filter; - }; - } -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_client_via_api_helper.h b/src/Native/libcryptonote/contrib/epee/include/net/http_client_via_api_helper.h deleted file mode 100644 index 3242e4162..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_client_via_api_helper.h +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include -#include -#pragma comment(lib, "Wininet.lib") - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - inline - bool http_ssl_invoke(const std::string& url, const std::string usr, const std::string psw, std::string& http_response_body, bool use_post = false) - { - bool final_res = false; - - ATL::CUrl url_obj; - BOOL crack_rss = url_obj.CrackUrl(string_encoding::convert_to_t >(url).c_str()); - - HINTERNET hinet = ::InternetOpenA(SHARED_JOBSCOMMON_HTTP_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); - if(!hinet) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenA, \nError: " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - return false; - } - - DWORD dwFlags = 0; - DWORD dwBuffLen = sizeof(dwFlags); - - if(usr.size()) - { - dwFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID| - INTERNET_FLAG_PRAGMA_NOCACHE | SECURITY_FLAG_IGNORE_UNKNOWN_CA|INTERNET_FLAG_SECURE; - }else - { - dwFlags |= INTERNET_FLAG_PRAGMA_NOCACHE; - } - - - int port = url_obj.GetPortNumber(); - BOOL res = FALSE; - - HINTERNET hsession = ::InternetConnectA(hinet, string_encoding::convert_to_ansii(url_obj.GetHostName()).c_str(), port/*INTERNET_DEFAULT_HTTPS_PORT*/, usr.c_str(), psw.c_str(), INTERNET_SERVICE_HTTP, dwFlags, NULL); - if(hsession) - { - const std::string uri = string_encoding::convert_to_ansii(url_obj.GetUrlPath()) + string_encoding::convert_to_ansii(url_obj.GetExtraInfo()); - - HINTERNET hrequest = ::HttpOpenRequestA(hsession, use_post?"POST":NULL, uri.c_str(), NULL, NULL,NULL, dwFlags, NULL); - if(hrequest) - { - while(true) - { - res = ::HttpSendRequestA(hrequest, NULL, 0, NULL, 0); - if(!res) - { - //ERROR_INTERNET_INVALID_CA 45 - //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) - int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpSendRequestA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - - DWORD code = 0; - DWORD buf_len = sizeof(code); - DWORD index = 0; - res = ::HttpQueryInfo(hrequest, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &code, &buf_len, &index); - if(!res) - { - //ERROR_INTERNET_INVALID_CA 45 - //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) - int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpQueryInfo, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - if(code < 200 || code > 299) - { - LOG_PRINT("Wrong server response, HttpQueryInfo returned statuse code" << code , LOG_LEVEL_0); - break; - } - - - char buff[100000] = {0}; - DWORD readed = 0; - while(true) - { - res = ::InternetReadFile(hrequest, buff, sizeof(buff), &readed); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetReadFile, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - if(readed) - { - http_response_body.append(buff, readed); - } - else - break; - } - - if(!res) - break; - - - //we success - final_res = true; - - res = ::InternetCloseHandle(hrequest); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - - break; - } - } - else - { - //ERROR_INTERNET_INVALID_CA - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenUrlA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - return false; - } - - res = ::InternetCloseHandle(hsession); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - }else - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetConnectA(" << string_encoding::convert_to_ansii(url_obj.GetHostName()) << ", port " << port << " \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - - - - res = ::InternetCloseHandle(hinet); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - return final_res; - } -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_protocol_handler.h b/src/Native/libcryptonote/contrib/epee/include/net/http_protocol_handler.h deleted file mode 100644 index b4485d1cd..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_protocol_handler.h +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_H_ -#define _HTTP_SERVER_H_ - -#include -#include -#include "net_utils_base.h" -#include "to_nonconst_iterator.h" -#include "http_auth.h" -#include "http_base.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - namespace http - { - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct http_server_config - { - std::string m_folder; - std::vector m_access_control_origins; - boost::optional m_user; - critical_section m_lock; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class simple_http_connection_handler - { - public: - typedef t_connection_context connection_context;//t_connection_context net_utils::connection_context_base connection_context; - typedef http_server_config config_type; - - simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config); - virtual ~simple_http_connection_handler(){} - - bool release_protocol() - { - return true; - } - - virtual bool thread_init() - { - return true; - } - - virtual bool thread_deinit() - { - return true; - } - bool after_init_connection() - { - return true; - } - virtual bool handle_recv(const void* ptr, size_t cb); - virtual bool handle_request(const http::http_request_info& query_info, http_response_info& response); - - private: - enum machine_state{ - http_state_retriving_comand_line, - http_state_retriving_header, - http_state_retriving_body, - http_state_connection_close, - http_state_error - }; - - enum body_transfer_type{ - http_body_transfer_chunked, - http_body_transfer_measure,//mean "Content-Length" valid - http_body_transfer_chunked_instead_measure, - http_body_transfer_connection_close, - http_body_transfer_multipart, - http_body_transfer_undefined - }; - - bool handle_buff_in(std::string& buf); - - bool analize_cached_request_header_and_invoke_state(size_t pos); - - bool handle_invoke_query_line(); - bool parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos); - std::string::size_type match_end_of_header(const std::string& buf); - bool get_len_from_content_lenght(const std::string& str, size_t& len); - bool handle_retriving_query_body(); - bool handle_query_measure(); - bool set_ready_state(); - bool slash_to_back_slash(std::string& str); - std::string get_file_mime_tipe(const std::string& path); - std::string get_response_header(const http_response_info& response); - - //major function - inline bool handle_request_and_send_response(const http::http_request_info& query_info); - - - std::string get_not_found_response_body(const std::string& URI); - - std::string m_root_path; - std::string m_cache; - machine_state m_state; - body_transfer_type m_body_transfer_type; - bool m_is_stop_handling; - http::http_request_info m_query_info; - size_t m_len_summary, m_len_remain; - config_type& m_config; - bool m_want_close; - protected: - i_service_endpoint* m_psnd_hndlr; - }; - - template - struct i_http_server_handler - { - virtual ~i_http_server_handler(){} - virtual bool handle_http_request(const http_request_info& query_info, - http_response_info& response, - t_connection_context& m_conn_context) = 0; - virtual bool init_server_thread(){return true;} - virtual bool deinit_server_thread(){return true;} - }; - - template - struct custum_handler_config: public http_server_config - { - i_http_server_handler* m_phandler; - std::function rng; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - - template - class http_custom_handler: public simple_http_connection_handler - { - public: - typedef custum_handler_config config_type; - - http_custom_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context) - : simple_http_connection_handler(psnd_hndlr, config), - m_config(config), - m_conn_context(conn_context), - m_auth(m_config.m_user ? http_server_auth{*m_config.m_user, config.rng} : http_server_auth{}) - {} - inline bool handle_request(const http_request_info& query_info, http_response_info& response) - { - CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!"); - - const auto auth_response = m_auth.get_response(query_info); - if (auth_response) - { - response = std::move(*auth_response); - return true; - } - - //fill with default values - response.m_mime_tipe = "text/plain"; - response.m_response_code = 200; - response.m_response_comment = "OK"; - response.m_body.clear(); - - return m_config.m_phandler->handle_http_request(query_info, response, m_conn_context); - } - - virtual bool thread_init() - { - return m_config.m_phandler->init_server_thread();; - } - - virtual bool thread_deinit() - { - return m_config.m_phandler->deinit_server_thread(); - } - void handle_qued_callback() - {} - bool after_init_connection() - { - return true; - } - - private: - //simple_http_connection_handler::config_type m_stub_config; - config_type& m_config; - t_connection_context& m_conn_context; - http_server_auth m_auth; - }; - } -} -} - -#include "http_protocol_handler.inl" - -#endif //_HTTP_SERVER_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_protocol_handler.inl b/src/Native/libcryptonote/contrib/epee/include/net/http_protocol_handler.inl deleted file mode 100644 index c18f7f706..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_protocol_handler.inl +++ /dev/null @@ -1,720 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#include -#include -#include "http_protocol_handler.h" -#include "reg_exp_definer.h" -#include "string_tools.h" -#include "file_io_utils.h" -#include "net_parse_helpers.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -#define HTTP_MAX_URI_LEN 9000 -#define HTTP_MAX_HEADER_LEN 100000 - -namespace epee -{ -namespace net_utils -{ - namespace http - { - - struct multipart_entry - { - std::list > m_etc_header_fields; - std::string m_content_disposition; - std::string m_content_type; - std::string m_body; - }; - - inline - bool match_boundary(const std::string& content_type, std::string& boundary) - { - STATIC_REGEXP_EXPR_1(rexp_match_boundary, "boundary=(.*?)(($)|([;\\s,]))", boost::regex::icase | boost::regex::normal); - // 1 - boost::smatch result; - if(boost::regex_search(content_type, result, rexp_match_boundary, boost::match_default) && result[0].matched) - { - boundary = result[1]; - return true; - } - - return false; - } - - inline - bool parse_header(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry& entry) - { - STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Content-Disposition)|(Content-Type)" - // 12 3 - "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //4 56 7 - boost::regex::icase | boost::regex::normal); - - boost::smatch result; - std::string::const_iterator it_current_bound = it_begin; - std::string::const_iterator it_end_bound = it_end; - - //lookup all fields and fill well-known fields - while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) - { - const size_t field_val = 6; - const size_t field_etc_name = 4; - - int i = 2; //start position = 2 - if(result[i++].matched)//"Content-Disposition" - entry.m_content_disposition = result[field_val]; - else if(result[i++].matched)//"Content-Type" - entry.m_content_type = result[field_val]; - else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) - entry.m_etc_header_fields.push_back(std::pair(result[field_etc_name], result[field_val])); - else - { - LOG_ERROR("simple_http_connection_handler::parse_header() not matched last entry in:"<& out_values) - { - //bool res = file_io_utils::load_file_to_string("C:\\public\\multupart_data", body); - - std::string boundary; - if(!match_boundary(content_type, boundary)) - { - MERROR("Failed to match boundary in content type: " << content_type); - return false; - } - - boundary+="\r\n"; - bool is_stop = false; - bool first_step = true; - - std::string::const_iterator it_begin = body.begin(); - std::string::const_iterator it_end; - while(!is_stop) - { - std::string::size_type pos = body.find(boundary, std::distance(body.begin(), it_begin)); - - if(std::string::npos == pos) - { - is_stop = true; - boundary.erase(boundary.size()-2, 2); - boundary+= "--"; - pos = body.find(boundary, std::distance(body.begin(), it_begin)); - if(std::string::npos == pos) - { - MERROR("Error: Filed to match closing multipart tag"); - it_end = body.end(); - }else - { - it_end = body.begin() + pos; - } - }else - it_end = body.begin() + pos; - - - if(first_step && !is_stop) - { - first_step = false; - it_begin = it_end + boundary.size(); - std::string temp = "\r\n--"; - boundary = temp + boundary; - continue; - } - - out_values.push_back(multipart_entry()); - if(!handle_part_of_multipart(it_begin, it_end, out_values.back())) - { - MERROR("Failed to handle_part_of_multipart"); - return false; - } - - it_begin = it_end + boundary.size(); - } - - return true; - } - - - - - //-------------------------------------------------------------------------------------------- - template - simple_http_connection_handler::simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config): - m_state(http_state_retriving_comand_line), - m_body_transfer_type(http_body_transfer_undefined), - m_is_stop_handling(false), - m_len_summary(0), - m_len_remain(0), - m_config(config), - m_want_close(false), - m_psnd_hndlr(psnd_hndlr) - { - - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::set_ready_state() - { - m_is_stop_handling = false; - m_state = http_state_retriving_comand_line; - m_body_transfer_type = http_body_transfer_undefined; - m_query_info.clear(); - m_len_summary = 0; - return true; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_recv(const void* ptr, size_t cb) - { - std::string buf((const char*)ptr, cb); - //LOG_PRINT_L0("HTTP_RECV: " << ptr << "\r\n" << buf); - //file_io_utils::save_string_to_file(string_tools::get_current_module_folder() + "/" + boost::lexical_cast(ptr), std::string((const char*)ptr, cb)); - - bool res = handle_buff_in(buf); - if(m_want_close/*m_state == http_state_connection_close || m_state == http_state_error*/) - return false; - return res; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_buff_in(std::string& buf) - { - - if(m_cache.size()) - m_cache += buf; - else - m_cache.swap(buf); - - m_is_stop_handling = false; - while(!m_is_stop_handling) - { - switch(m_state) - { - case http_state_retriving_comand_line: - //The HTTP protocol does not place any a priori limit on the length of a URI. (c)RFC2616 - //but we forebly restirct it len to HTTP_MAX_URI_LEN to make it more safely - if(!m_cache.size()) - break; - - //check_and_handle_fake_response(); - if((m_cache[0] == '\r' || m_cache[0] == '\n')) - { - //some times it could be that before query line cold be few line breaks - //so we have to be calm without panic with assers - m_cache.erase(0, 1); - break; - } - - if(std::string::npos != m_cache.find('\n', 0)) - handle_invoke_query_line(); - else - { - m_is_stop_handling = true; - if(m_cache.size() > HTTP_MAX_URI_LEN) - { - LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too long URI line"); - m_state = http_state_error; - return false; - } - } - break; - case http_state_retriving_header: - { - std::string::size_type pos = match_end_of_header(m_cache); - if(std::string::npos == pos) - { - m_is_stop_handling = true; - if(m_cache.size() > HTTP_MAX_HEADER_LEN) - { - LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long header area"); - m_state = http_state_error; - return false; - } - break; - } - if (!analize_cached_request_header_and_invoke_state(pos)) - return false; - break; - } - case http_state_retriving_body: - return handle_retriving_query_body(); - case http_state_connection_close: - return false; - default: - LOG_ERROR("simple_http_connection_handler::handle_char_out: Wrong state: " << m_state); - return false; - case http_state_error: - LOG_ERROR("simple_http_connection_handler::handle_char_out: Error state!!!"); - return false; - } - - if(!m_cache.size()) - m_is_stop_handling = true; - } - - return true; - } - //-------------------------------------------------------------------------------------------- - inline bool analize_http_method(const boost::smatch& result, http::http_method& method, int& http_ver_major, int& http_ver_minor) - { - CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed..."); - http_ver_major = boost::lexical_cast(result[11]); - http_ver_minor = boost::lexical_cast(result[12]); - - if(result[3].matched) - method = http::http_method_options; - else if(result[4].matched) - method = http::http_method_get; - else if(result[5].matched) - method = http::http_method_head; - else if(result[6].matched) - method = http::http_method_post; - else if(result[7].matched) - method = http::http_method_put; - else - method = http::http_method_etc; - - return true; - } - - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_invoke_query_line() - { - STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^(((OPTIONS)|(GET)|(HEAD)|(POST)|(PUT)|(DELETE)|(TRACE)) (\\S+) HTTP/(\\d+).(\\d+))\r?\n", boost::regex::icase | boost::regex::normal); - // 123 4 5 6 7 8 9 10 11 12 - //size_t match_len = 0; - boost::smatch result; - if(boost::regex_search(m_cache, result, rexp_match_command_line, boost::match_default) && result[0].matched) - { - analize_http_method(result, m_query_info.m_http_method, m_query_info.m_http_ver_hi, m_query_info.m_http_ver_hi); - m_query_info.m_URI = result[10]; - if (!parse_uri(m_query_info.m_URI, m_query_info.m_uri_content)) - { - m_state = http_state_error; - MERROR("Failed to parse URI: m_query_info.m_URI"); - return false; - } - m_query_info.m_http_method_str = result[2]; - m_query_info.m_full_request_str = result[0]; - - m_cache.erase(m_cache.begin(), to_nonsonst_iterator(m_cache, result[0].second)); - - m_state = http_state_retriving_header; - - return true; - }else - { - m_state = http_state_error; - LOG_ERROR("simple_http_connection_handler::handle_invoke_query_line(): Failed to match first line: " << m_cache); - return false; - } - - return false; - } - //-------------------------------------------------------------------------------------------- - template - std::string::size_type simple_http_connection_handler::match_end_of_header(const std::string& buf) - { - - //Here we returning head size, including terminating sequence (\r\n\r\n or \n\n) - std::string::size_type res = buf.find("\r\n\r\n"); - if(std::string::npos != res) - return res+4; - res = buf.find("\n\n"); - if(std::string::npos != res) - return res+2; - return res; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::analize_cached_request_header_and_invoke_state(size_t pos) - { - //LOG_PRINT_L4("HTTP HEAD:\r\n" << m_cache.substr(0, pos)); - - m_query_info.m_full_request_buf_size = pos; - m_query_info.m_request_head.assign(m_cache.begin(), m_cache.begin()+pos); - - if(!parse_cached_header(m_query_info.m_header_info, m_cache, pos)) - { - LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache); - m_state = http_state_error; - return false; - } - - m_cache.erase(0, pos); - - std::string req_command_str = m_query_info.m_full_request_str; - //if we have POST or PUT command, it is very possible tha we will get body - //but now, we suppose than we have body only in case of we have "ContentLength" - if(m_query_info.m_header_info.m_content_length.size()) - { - m_state = http_state_retriving_body; - m_body_transfer_type = http_body_transfer_measure; - if(!get_len_from_content_lenght(m_query_info.m_header_info.m_content_length, m_len_summary)) - { - LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="< - bool simple_http_connection_handler::handle_retriving_query_body() - { - switch(m_body_transfer_type) - { - case http_body_transfer_measure: - return handle_query_measure(); - case http_body_transfer_chunked: - case http_body_transfer_connection_close: - case http_body_transfer_multipart: - case http_body_transfer_undefined: - default: - LOG_ERROR("simple_http_connection_handler::handle_retriving_query_body(): Unexpected m_body_query_type state:" << m_body_transfer_type); - m_state = http_state_error; - return false; - } - - return true; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_query_measure() - { - - if(m_len_remain >= m_cache.size()) - { - m_len_remain -= m_cache.size(); - m_query_info.m_body += m_cache; - m_cache.clear(); - }else - { - m_query_info.m_body.append(m_cache.begin(), m_cache.begin() + m_len_remain); - m_cache.erase(0, m_len_remain); - m_len_remain = 0; - } - - if(!m_len_remain) - { - if(handle_request_and_send_response(m_query_info)) - set_ready_state(); - else - m_state = http_state_error; - } - return true; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos) - { - STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)|(Origin)" - // 12 3 4 5 6 7 8 9 10 11 - "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //11 1213 14 - boost::regex::icase | boost::regex::normal); - - boost::smatch result; - std::string::const_iterator it_current_bound = m_cache_to_process.begin(); - std::string::const_iterator it_end_bound = m_cache_to_process.begin()+pos; - - body_info.clear(); - - //lookup all fields and fill well-known fields - while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) - { - const size_t field_val = 14; - const size_t field_etc_name = 12; - - int i = 2; //start position = 2 - if(result[i++].matched)//"Connection" - body_info.m_connection = result[field_val]; - else if(result[i++].matched)//"Referer" - body_info.m_referer = result[field_val]; - else if(result[i++].matched)//"Content-Length" - body_info.m_content_length = result[field_val]; - else if(result[i++].matched)//"Content-Type" - body_info.m_content_type = result[field_val]; - else if(result[i++].matched)//"Transfer-Encoding" - body_info.m_transfer_encoding = result[field_val]; - else if(result[i++].matched)//"Content-Encoding" - body_info.m_content_encoding = result[field_val]; - else if(result[i++].matched)//"Host" - body_info.m_host = result[field_val]; - else if(result[i++].matched)//"Cookie" - body_info.m_cookie = result[field_val]; - else if(result[i++].matched)//"User-Agent" - body_info.m_user_agent = result[field_val]; - else if(result[i++].matched)//"Origin" - body_info.m_origin = result[field_val]; - else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) - body_info.m_etc_fields.push_back(std::pair(result[field_etc_name], result[field_val])); - else - { - LOG_ERROR("simple_http_connection_handler::parse_cached_header() not matched last entry in:"< - bool simple_http_connection_handler::get_len_from_content_lenght(const std::string& str, size_t& OUT len) - { - STATIC_REGEXP_EXPR_1(rexp_mach_field, "\\d+", boost::regex::normal); - std::string res; - boost::smatch result; - if(!(boost::regex_search( str, result, rexp_mach_field, boost::match_default) && result[0].matched)) - return false; - - len = boost::lexical_cast(result[0]); - return true; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_request_and_send_response(const http::http_request_info& query_info) - { - http_response_info response{}; - //CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" ); - bool res = true; - - if (query_info.m_http_method != http::http_method_options) - { - res = handle_request(query_info, response); - } - else - { - response.m_response_code = 200; - response.m_response_comment = "OK"; - } - - std::string response_data = get_response_header(response); - //LOG_PRINT_L0("HTTP_SEND: << \r\n" << response_data + response.m_body); - - LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" << response_data); - - m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size()); - if ((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options)) - m_psnd_hndlr->do_send((void*)response.m_body.data(), response.m_body.size()); - return res; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_request(const http::http_request_info& query_info, http_response_info& response) - { - - std::string uri_to_path = query_info.m_uri_content.m_path; - if("/" == uri_to_path) - uri_to_path = "/index.html"; - - //slash_to_back_slash(uri_to_path); - m_config.m_lock.lock(); - std::string destination_file_path = m_config.m_folder + uri_to_path; - m_config.m_lock.unlock(); - if(!file_io_utils::load_file_to_string(destination_file_path.c_str(), response.m_body)) - { - MWARNING("URI \""<< query_info.m_full_request_str.substr(0, query_info.m_full_request_str.size()-2) << "\" [" << destination_file_path << "] Not Found (404 )"); - response.m_body = get_not_found_response_body(query_info.m_URI); - response.m_response_code = 404; - response.m_response_comment = "Not found"; - response.m_mime_tipe = "text/html"; - return true; - } - - MDEBUG(" -->> " << query_info.m_full_request_str << "\r\n<<--OK"); - response.m_response_code = 200; - response.m_response_comment = "OK"; - response.m_mime_tipe = get_file_mime_tipe(uri_to_path); - - return true; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_response_header(const http_response_info& response) - { - std::string buf = "HTTP/1.1 "; - buf += boost::lexical_cast(response.m_response_code) + " " + response.m_response_comment + "\r\n" + - "Server: Epee-based\r\n" - "Content-Length: "; - buf += boost::lexical_cast(response.m_body.size()) + "\r\n"; - - if(!response.m_mime_tipe.empty()) - { - buf += "Content-Type: "; - buf += response.m_mime_tipe + "\r\n"; - } - - buf += "Last-Modified: "; - time_t tm; - time(&tm); - buf += misc_utils::get_internet_time_str(tm) + "\r\n"; - buf += "Accept-Ranges: bytes\r\n"; - //Wed, 01 Dec 2010 03:27:41 GMT" - - string_tools::trim(m_query_info.m_header_info.m_connection); - if(m_query_info.m_header_info.m_connection.size()) - { - if(!string_tools::compare_no_case("close", m_query_info.m_header_info.m_connection)) - { - //closing connection after sending - buf += "Connection: close\r\n"; - m_state = http_state_connection_close; - m_want_close = true; - } - } - - // Cross-origin resource sharing - if(m_query_info.m_header_info.m_origin.size()) - { - if (std::binary_search(m_config.m_access_control_origins.begin(), m_config.m_access_control_origins.end(), m_query_info.m_header_info.m_origin)) - { - buf += "Access-Control-Allow-Origin: "; - buf += m_query_info.m_header_info.m_origin; - buf += "\r\n"; - buf += "Access-Control-Expose-Headers: www-authenticate\r\n"; - if (m_query_info.m_http_method == http::http_method_options) - buf += "Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With\r\n"; - buf += "Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS\r\n"; - } - } - - //add additional fields, if it is - for(fields_list::const_iterator it = response.m_additional_fields.begin(); it!=response.m_additional_fields.end(); it++) - buf += it->first + ":" + it->second + "\r\n"; - - buf+="\r\n"; - - return buf; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_file_mime_tipe(const std::string& path) - { - std::string result; - std::string ext = string_tools::get_extension(path); - if(!string_tools::compare_no_case(ext, "gif")) - result = "image/gif"; - else if(!string_tools::compare_no_case(ext, "jpg")) - result = "image/jpeg"; - else if(!string_tools::compare_no_case(ext, "html")) - result = "text/html"; - else if(!string_tools::compare_no_case(ext, "htm")) - result = "text/html"; - else if(!string_tools::compare_no_case(ext, "js")) - result = "application/x-javascript"; - else if(!string_tools::compare_no_case(ext, "css")) - result = "text/css"; - else if(!string_tools::compare_no_case(ext, "xml")) - result = "application/xml"; - else if(!string_tools::compare_no_case(ext, "svg")) - result = "image/svg+xml"; - - - return result; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_not_found_response_body(const std::string& URI) - { - std::string body = - "\r\n" - "\r\n" - "404 Not Found\r\n" - "\r\n" - "

Not Found

\r\n" - "

The requested URL \r\n"; - body += URI; - body += "was not found on this server.

\r\n" - "\r\n"; - - return body; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::slash_to_back_slash(std::string& str) - { - for(std::string::iterator it = str.begin(); it!=str.end(); it++) - if('/' == *it) - *it = '\\'; - return true; - } - } -} -} - -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_server_cp.h b/src/Native/libcryptonote/contrib/epee/include/net/http_server_cp.h deleted file mode 100644 index 1ac2223c7..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_server_cp.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server_cp.h" -#include "http_server.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - typedef cp_server_impl cp_http_server_file_system; - typedef cp_server_impl cp_http_server_custum_handling; -} -} - - - -#endif - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_server_cp2.h b/src/Native/libcryptonote/contrib/epee/include/net/http_server_cp2.h deleted file mode 100644 index 8dfd43a16..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_server_cp2.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP2_H_ -#define _HTTP_SERVER_CP2_H_ - -#include "abstract_tcp_server2.h" -#include "http_protocol_handler.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ -namespace net_utils -{ - typedef boosted_tcp_server > boosted_http_server_file_system; - typedef boosted_tcp_server > boosted_http_server_custum_handling; -} -} - - -#endif - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_server_handlers_map2.h b/src/Native/libcryptonote/contrib/epee/include/net/http_server_handlers_map2.h deleted file mode 100644 index 429e3e1af..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_server_handlers_map2.h +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -#include "http_base.h" -#include "jsonrpc_structs.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - - -#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \ - epee::net_utils::http::http_response_info& response, \ - context_type& m_conn_context) \ -{\ - LOG_PRINT_L2("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ - response.m_response_code = 200; \ - response.m_response_comment = "Ok"; \ - if(!handle_http_request_map(query_info, response, m_conn_context)) \ - {response.m_response_code = 404;response.m_response_comment = "Not found";} \ - return true; \ -} - - -#define BEGIN_URI_MAP2() template bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \ - epee::net_utils::http::http_response_info& response_info, \ - t_context& m_conn_context) { \ - bool handled = false; \ - if(false) return true; //just a stub to have "else if" - -#define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, m_conn_context); - -#define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type) //TODO: don't think i ever again will use xml - ambiguous and "overtagged" format - -#define MAP_URI_AUTO_JON2_IF(s_pattern, callback_f, command_type, cond) \ - else if((query_info.m_URI == s_pattern) && (cond)) \ - { \ - handled = true; \ - uint64_t ticks = misc_utils::get_tick_count(); \ - boost::value_initialized req; \ - bool parse_res = epee::serialization::load_t_from_json(static_cast(req), query_info.m_body); \ - CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" << query_info.m_body); \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized resp;\ - if(!callback_f(static_cast(req), static_cast(resp))) \ - { \ - LOG_ERROR("Failed to " << #callback_f << "()"); \ - response_info.m_response_code = 500; \ - response_info.m_response_comment = "Internal Server Error"; \ - return true; \ - } \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(static_cast(resp), response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = "application/json"; \ - response_info.m_header_info.m_content_type = " application/json"; \ - MDEBUG( s_pattern << " processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); \ - } - -#define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) MAP_URI_AUTO_JON2_IF(s_pattern, callback_f, command_type, true) - -#define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \ - else if(query_info.m_URI == s_pattern) \ - { \ - handled = true; \ - uint64_t ticks = misc_utils::get_tick_count(); \ - boost::value_initialized req; \ - bool parse_res = epee::serialization::load_t_from_binary(static_cast(req), query_info.m_body); \ - CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \ - uint64_t ticks1 = misc_utils::get_tick_count(); \ - boost::value_initialized resp;\ - if(!callback_f(static_cast(req), static_cast(resp))) \ - { \ - LOG_ERROR("Failed to " << #callback_f << "()"); \ - response_info.m_response_code = 500; \ - response_info.m_response_comment = "Internal Server Error"; \ - return true; \ - } \ - uint64_t ticks2 = misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_binary(static_cast(resp), response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = " application/octet-stream"; \ - response_info.m_header_info.m_content_type = " application/octet-stream"; \ - MDEBUG( s_pattern << "() processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); \ - } - -#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);handled = true;} - -#define END_URI_MAP2() return handled;} - - -#define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == uri) \ - { \ - uint64_t ticks = epee::misc_utils::get_tick_count(); \ - epee::serialization::portable_storage ps; \ - if(!ps.load_from_json(query_info.m_body)) \ - { \ - boost::value_initialized rsp; \ - static_cast(rsp).error.code = -32700; \ - static_cast(rsp).error.message = "Parse error"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - return true; \ - } \ - epee::serialization::storage_entry id_; \ - id_ = epee::serialization::storage_entry(std::string()); \ - ps.get_value("id", id_, nullptr); \ - std::string callback_name; \ - if(!ps.get_value("method", callback_name, nullptr)) \ - { \ - epee::json_rpc::error_response rsp; \ - rsp.jsonrpc = "2.0"; \ - rsp.error.code = -32600; \ - rsp.error.message = "Invalid Request"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - return true; \ - } \ - if(false) return true; //just a stub to have "else if" - - -#define PREPARE_OBJECTS_FROM_JSON(command_type) \ - handled = true; \ - boost::value_initialized > req_; \ - epee::json_rpc::request& req = static_cast&>(req_);\ - if(!req.load(ps)) \ - { \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - fail_resp.error.code = -32602; \ - fail_resp.error.message = "Invalid params"; \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized > resp_; \ - epee::json_rpc::response& resp = static_cast &>(resp_); \ - resp.jsonrpc = "2.0"; \ - resp.id = req.id; - -#define FINALIZE_OBJECTS_TO_JSON(method_name) \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(resp, response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = "application/json"; \ - response_info.m_header_info.m_content_type = " application/json"; \ - MDEBUG( query_info.m_URI << "[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); - -#define MAP_JON_RPC_WE_IF(method_name, callback_f, command_type, cond) \ - else if((callback_name == method_name) && (cond)) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error)) \ - { \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define MAP_JON_RPC_WE(method_name, callback_f, command_type) MAP_JON_RPC_WE_IF(method_name, callback_f, command_type, true) - -#define MAP_JON_RPC_WERI(method_name, callback_f, command_type) \ - else if(callback_name == method_name) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context, response_info)) \ - { \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define MAP_JON_RPC(method_name, callback_f, command_type) \ - else if(callback_name == method_name) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - if(!callback_f(req.params, resp.result)) \ - { \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - fail_resp.error.code = -32603; \ - fail_resp.error.message = "Internal error"; \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define END_JSON_RPC_MAP() \ - epee::json_rpc::error_response rsp; \ - rsp.id = id_; \ - rsp.jsonrpc = "2.0"; \ - rsp.error.code = -32601; \ - rsp.error.message = "Method not found"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - return true; \ -} - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_server_impl_base.h b/src/Native/libcryptonote/contrib/epee/include/net/http_server_impl_base.h deleted file mode 100644 index 1a97e610a..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_server_impl_base.h +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - - -#include -#include - -#include "net/http_server_cp2.h" -#include "net/http_server_handlers_map2.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.http" - -namespace epee -{ - - template - class http_server_impl_base: public net_utils::http::i_http_server_handler - { - - public: - http_server_impl_base() - : m_net_server(epee::net_utils::e_connection_type_RPC) - {} - - explicit http_server_impl_base(boost::asio::io_service& external_io_service) - : m_net_server(external_io_service) - {} - - bool init(std::function rng, const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0", - std::vector access_control_origins = std::vector(), - boost::optional user = boost::none) - { - - //set self as callback handler - m_net_server.get_config_object().m_phandler = static_cast(this); - m_net_server.get_config_object().rng = std::move(rng); - - //here set folder for hosting reqests - m_net_server.get_config_object().m_folder = ""; - - //set access control allow origins if configured - std::sort(access_control_origins.begin(), access_control_origins.end()); - m_net_server.get_config_object().m_access_control_origins = std::move(access_control_origins); - - m_net_server.get_config_object().m_user = std::move(user); - - MGINFO("Binding on " << bind_ip << ":" << bind_port); - bool res = m_net_server.init_server(bind_port, bind_ip); - if(!res) - { - LOG_ERROR("Failed to bind server"); - return false; - } - return true; - } - - bool run(size_t threads_count, bool wait = true) - { - //go to loop - MINFO("Run net_service loop( " << threads_count << " threads)..."); - if(!m_net_server.run_server(threads_count, wait)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - if(wait) - MINFO("net_service loop stopped."); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool timed_wait_server_stop(uint64_t ms) - { - return m_net_server.timed_wait_server_stop(ms); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - int get_binded_port() - { - return m_net_server.get_binded_port(); - } - - long get_connections_count() const - { - return m_net_server.get_connections_count(); - } - - protected: - net_utils::boosted_tcp_server > m_net_server; - }; -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/http_server_thread_per_connect.h b/src/Native/libcryptonote/contrib/epee/include/net/http_server_thread_per_connect.h deleted file mode 100644 index bec43b726..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/http_server_thread_per_connect.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server.h" -#include "http_server.h" - -namespace epee -{ -namespace net_utils -{ - typedef abstract_tcp_server mt_http_server_file_system; - typedef abstract_tcp_server mt_http_server_custum_handling; - -} -} - - -#endif - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_protocol_handler.h b/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_protocol_handler.h deleted file mode 100644 index b224c3429..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_protocol_handler.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef JSONRPC_PROTOCOL_HANDLER_H -#define JSONRPC_PROTOCOL_HANDLER_H - -#include -#include - -#include "net/net_utils_base.h" -#include "jsonrpc_structs.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" - -namespace epee -{ -namespace net_utils -{ - namespace jsonrpc2 - { - inline - std::string& make_error_resp_json(int64_t code, const std::string& message, - std::string& response_data, - const epee::serialization::storage_entry& id = nullptr) - { - epee::json_rpc::error_response rsp; - rsp.id = id; - rsp.jsonrpc = "2.0"; - rsp.error.code = code; - rsp.error.message = message; - epee::serialization::store_t_to_json(static_cast(rsp), response_data, 0, false); - response_data += "\n"; - return response_data; - } - - template - struct i_jsonrpc2_server_handler - { - virtual ~i_jsonrpc2_server_handler() - {} - virtual bool handle_rpc_request(const std::string& req_data, - std::string& resp_data, - t_connection_context& conn_context) = 0; - virtual bool init_server_thread() - { return true; } - virtual bool deinit_server_thread() - { return true; } - }; - - template - struct jsonrpc2_server_config - { - i_jsonrpc2_server_handler* m_phandler; - critical_section m_lock; - }; - - template - class jsonrpc2_connection_handler - { - public: - typedef t_connection_context connection_context; - typedef jsonrpc2_server_config config_type; - - jsonrpc2_connection_handler(i_service_endpoint* psnd_hndlr, - config_type& config, - t_connection_context& conn_context) - : m_psnd_hndlr(psnd_hndlr), - m_config(config), - m_conn_context(conn_context), - m_is_stop_handling(false) - {} - virtual ~jsonrpc2_connection_handler() - {} - - bool release_protocol() - { - return true; - } - virtual bool thread_init() - { - return true; - } - virtual bool thread_deinit() - { - return true; - } - void handle_qued_callback() - {} - bool after_init_connection() - { - return true; - } - virtual bool handle_recv(const void* ptr, size_t cb) - { - std::string buf((const char*)ptr, cb); - LOG_PRINT_L0("JSONRPC2_RECV: " << ptr << "\r\n" << buf); - - bool res = handle_buff_in(buf); - return res; - } - private: - bool handle_buff_in(std::string& buf) - { - if(m_cache.size()) - m_cache += buf; - else - m_cache.swap(buf); - - m_is_stop_handling = false; - while (!m_is_stop_handling) { - std::string::size_type pos = match_end_of_request(m_cache); - if (std::string::npos == pos) { - m_is_stop_handling = true; - if (m_cache.size() > 4096) { - LOG_ERROR("jsonrpc2_connection_handler::handle_buff_in: Too long request"); - return false; - } - break; - } else { - extract_cached_request_and_handle(pos); - } - - if (!m_cache.size()) { - m_is_stop_handling = true; - } - } - - return true; - } - bool extract_cached_request_and_handle(std::string::size_type pos) - { - std::string request_data(m_cache.begin(), m_cache.begin() + pos); - m_cache.erase(0, pos); - return handle_request_and_send_response(request_data); - } - bool handle_request_and_send_response(const std::string& request_data) - { - CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!"); - std::string response_data; - - LOG_PRINT_L3("JSONRPC2_REQUEST: >> \r\n" << request_data); - bool rpc_result = m_config.m_phandler->handle_rpc_request(request_data, response_data, m_conn_context); - LOG_PRINT_L3("JSONRPC2_RESPONSE: << \r\n" << response_data); - - m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size()); - return rpc_result; - } - std::string::size_type match_end_of_request(const std::string& buf) - { - std::string::size_type res = buf.find("\n"); - if(std::string::npos != res) { - return res + 2; - } - return res; - } - - protected: - i_service_endpoint* m_psnd_hndlr; - - private: - config_type& m_config; - t_connection_context& m_conn_context; - std::string m_cache; - bool m_is_stop_handling; - }; - } -} -} - -#endif /* JSONRPC_PROTOCOL_HANDLER_H */ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_server_handlers_map.h b/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_server_handlers_map.h deleted file mode 100644 index 8c747d1af..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_server_handlers_map.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef JSONRPC_SERVER_HANDLERS_MAP_H -#define JSONRPC_SERVER_HANDLERS_MAP_H - -#include -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_template_helper.h" -#include "storages/portable_storage_base.h" -#include "jsonrpc_structs.h" -#include "jsonrpc_protocol_handler.h" - -#define BEGIN_JSONRPC2_MAP(t_connection_context) \ -bool handle_rpc_request(const std::string& req_data, \ - std::string& resp_data, \ - t_connection_context& m_conn_context) \ -{ \ - bool handled = false; \ - uint64_t ticks = epee::misc_utils::get_tick_count(); \ - epee::serialization::portable_storage ps; \ - if (!ps.load_from_json(req_data)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32700, "Parse error", resp_data); \ - return true; \ - } \ - epee::serialization::storage_entry id_; \ - id_ = epee::serialization::storage_entry(std::string()); \ - if (!ps.get_value("id", id_, nullptr)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data); \ - return true; \ - } \ - std::string callback_name; \ - if (!ps.get_value("method", callback_name, nullptr)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data, id_); \ - return true; \ - } \ - if (false) return true; //just a stub to have "else if" - - - -#define PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \ - handled = true; \ - boost::value_initialized > req_; \ - epee::json_rpc::request& req = static_cast&>(req_);\ - if(!req.load(ps)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32602, "Invalid params", resp_data, req.id); \ - return true; \ - } \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized > resp_; \ - epee::json_rpc::response& resp = static_cast &>(resp_); \ - resp.jsonrpc = "2.0"; \ - resp.id = req.id; - -#define FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(resp, resp_data, 0, false); \ - resp_data += "\n"; \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - LOG_PRINT("[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); - - -#define MAP_JSONRPC2_WE(method_name, callback_f, command_type) \ - else if (callback_name == method_name) \ - { \ - PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context)) \ - { \ - epee::serialization::store_t_to_json(static_cast(fail_resp), resp_data, 0, false); \ - resp_data += "\n"; \ - return true; \ - } \ - FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \ - return true; \ - } - -#define END_JSONRPC2_MAP() \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32601, "Method not found", resp_data, id_); \ - return true; \ -} - -#endif /* JSONRPC_SERVER_HANDLERS_MAP_H */ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_server_impl_base.h b/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_server_impl_base.h deleted file mode 100644 index 8a5a9a5b6..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_server_impl_base.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef JSONRPC_SERVER_IMPL_BASE_H -#define JSONRPC_SERVER_IMPL_BASE_H - -#include -#include - -#include "net/jsonrpc_protocol_handler.h" -#include "net/jsonrpc_server_handlers_map.h" -#include "net/abstract_tcp_server2.h" - -namespace epee -{ - -template - class jsonrpc_server_impl_base: public net_utils::jsonrpc2::i_jsonrpc2_server_handler - { - - public: - jsonrpc_server_impl_base() - : m_net_server() - {} - - explicit jsonrpc_server_impl_base(boost::asio::io_service& external_io_service) - : m_net_server(external_io_service) - {} - - bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0") - { - //set self as callback handler - m_net_server.get_config_object().m_phandler = static_cast(this); - - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - bool res = m_net_server.init_server(bind_port, bind_ip); - if (!res) - { - LOG_ERROR("Failed to bind server"); - return false; - } - return true; - } - - bool run(size_t threads_count, bool wait = true) - { - //go to loop - LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(threads_count, wait)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - if(wait) - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool timed_wait_server_stop(uint64_t ms) - { - return m_net_server.timed_wait_server_stop(ms); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - int get_binded_port() - { - return m_net_server.get_binded_port(); - } - - protected: - net_utils::boosted_tcp_server > m_net_server; - }; - -} - -#endif /* JSONRPC_SERVER_IMPL_BASE_H */ - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_structs.h b/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_structs.h deleted file mode 100644 index 9df9e2596..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/jsonrpc_structs.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef JSONRPC_STRUCTS_H -#define JSONRPC_STRUCTS_H - -#include -#include -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_base.h" - -namespace epee -{ - namespace json_rpc - { - template - struct request - { - std::string jsonrpc; - std::string method; - epee::serialization::storage_entry id; - t_param params; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(method) - KV_SERIALIZE(params) - END_KV_SERIALIZE_MAP() - }; - - struct error - { - int64_t code; - std::string message; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(code) - KV_SERIALIZE(message) - END_KV_SERIALIZE_MAP() - }; - - struct dummy_error - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct dummy_result - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_param result; - epee::serialization::storage_entry id; - t_error error; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(result) - KV_SERIALIZE(error) - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_param result; - epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(result) - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_error error; - epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(error) - END_KV_SERIALIZE_MAP() - }; - - typedef response error_response; - } -} - -#endif /* JSONRPC_STRUCTS_H */ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_base.h b/src/Native/libcryptonote/contrib/epee/include/net/levin_base.h deleted file mode 100644 index 7d060f5ef..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_base.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _LEVIN_BASE_H_ -#define _LEVIN_BASE_H_ - -#include "net_utils_base.h" - -#define LEVIN_SIGNATURE 0x0101010101012101LL //Bender's nightmare - -namespace epee -{ -namespace levin -{ -#pragma pack(push) -#pragma pack(1) - struct bucket_head - { - uint64_t m_signature; - uint64_t m_cb; - bool m_have_to_return_data; - uint32_t m_command; - int32_t m_return_code; - uint32_t m_reservedA; //probably some flags in future - uint32_t m_reservedB; //probably some check sum in future - }; -#pragma pack(pop) - - -#pragma pack(push) -#pragma pack(1) - struct bucket_head2 - { - uint64_t m_signature; - uint64_t m_cb; - bool m_have_to_return_data; - uint32_t m_command; - int32_t m_return_code; - uint32_t m_flags; - uint32_t m_protocol_version; - }; -#pragma pack(pop) - - -#define LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED 0 -#define LEVIN_DEFAULT_MAX_PACKET_SIZE 100000000 //100MB by default - -#define LEVIN_PACKET_REQUEST 0x00000001 -#define LEVIN_PACKET_RESPONSE 0x00000002 - - -#define LEVIN_PROTOCOL_VER_0 0 -#define LEVIN_PROTOCOL_VER_1 1 - - template - struct levin_commands_handler - { - virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, t_connection_context& context)=0; - virtual int notify(int command, const std::string& in_buff, t_connection_context& context)=0; - virtual void callback(t_connection_context& context){}; - - virtual void on_connection_new(t_connection_context& context){}; - virtual void on_connection_close(t_connection_context& context){}; - - virtual ~levin_commands_handler(){} - }; - -#define LEVIN_OK 0 -#define LEVIN_ERROR_CONNECTION -1 -#define LEVIN_ERROR_CONNECTION_NOT_FOUND -2 -#define LEVIN_ERROR_CONNECTION_DESTROYED -3 -#define LEVIN_ERROR_CONNECTION_TIMEDOUT -4 -#define LEVIN_ERROR_CONNECTION_NO_DUPLEX_PROTOCOL -5 -#define LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED -6 -#define LEVIN_ERROR_FORMAT -7 - -#define DESCRIBE_RET_CODE(code) case code: return #code; - inline - const char* get_err_descr(int err) - { - switch(err) - { - DESCRIBE_RET_CODE(LEVIN_OK); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_NOT_FOUND); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_DESTROYED); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_TIMEDOUT); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_NO_DUPLEX_PROTOCOL); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED); - DESCRIBE_RET_CODE(LEVIN_ERROR_FORMAT); - default: - return "unknown code"; - } - } - - -} -} - - -#endif //_LEVIN_BASE_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_client.h b/src/Native/libcryptonote/contrib/epee/include/net/levin_client.h deleted file mode 100644 index 335f6ba02..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_client.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - - -#ifndef _LEVIN_CLIENT_H_ -#define _LEVIN_CLIENT_H_ - -#include "net_helper.h" -#include "levin_base.h" - - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - -namespace epee -{ -namespace levin -{ - /************************************************************************/ - /* */ - /************************************************************************/ - class levin_client_impl - { - public: - levin_client_impl(); - virtual ~levin_client_impl(); - - bool connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0"); - bool connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0"); - bool is_connected(); - bool disconnect(); - - virtual int invoke(int command, const std::string& in_buff, std::string& buff_out); - virtual int notify(int command, const std::string& in_buff); - - protected: - net_utils::blocked_mode_client m_transport; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class levin_client_impl2: public levin_client_impl - { - public: - - int invoke(int command, const std::string& in_buff, std::string& buff_out); - int notify(int command, const std::string& in_buff); - }; - -} -namespace net_utils -{ - typedef levin::levin_client_impl levin_client; - typedef levin::levin_client_impl2 levin_client2; -} -} - -#include "levin_client.inl" - -#endif //_LEVIN_CLIENT_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_client.inl b/src/Native/libcryptonote/contrib/epee/include/net/levin_client.inl deleted file mode 100644 index ab7c32c32..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_client.inl +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -#include "string_tools.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace levin -{ -inline -bool levin_client_impl::connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip) -{ - return m_transport.connect(string_tools::get_ip_string_from_int32(ip), port, timeout, timeout, bind_ip); -} -//------------------------------------------------------------------------------ -inline - bool levin_client_impl::connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip) -{ - return m_transport.connect(addr, port, timeout, timeout, bind_ip); -} -//------------------------------------------------------------------------------ -inline -bool levin_client_impl::is_connected() -{ - return m_transport.is_connected(); -} -//------------------------------------------------------------------------------ -inline -bool levin_client_impl::disconnect() -{ - return m_transport.disconnect(); -} -//------------------------------------------------------------------------------ -inline -levin_client_impl::levin_client_impl() -{ -} -//------------------------------------------------------------------------------ -inline -levin_client_impl::~levin_client_impl() -{ - disconnect(); -} -//------------------------------------------------------------------------------ -inline -int levin_client_impl::invoke(int command, const std::string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_command = command; - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - std::string local_buff; - if(!m_transport.recv_n(local_buff, sizeof(bucket_head))) - return -1; - - head = *(bucket_head*)local_buff.data(); - - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_PRINT_L1("Signature mismatch in response"); - return -1; - } - - if(!m_transport.recv_n(buff_out, head.m_cb)) - return -1; - - return head.m_return_code; -} -//------------------------------------------------------------------------------ -inline -int levin_client_impl::notify(int command, const std::string& in_buff) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_command = command; - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -inline - int levin_client_impl2::invoke(int command, const std::string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - std::string local_buff; - if(!m_transport.recv_n(local_buff, sizeof(bucket_head2))) - return -1; - - head = *(bucket_head2*)local_buff.data(); - - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_PRINT_L1("Signature mismatch in response"); - return -1; - } - - if(!m_transport.recv_n(buff_out, head.m_cb)) - return -1; - - return head.m_return_code; -} -//------------------------------------------------------------------------------ -inline - int levin_client_impl2::notify(int command, const std::string& in_buff) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -} -} -//------------------------------------------------------------------------------ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_client_async.h b/src/Native/libcryptonote/contrib/epee/include/net/levin_client_async.h deleted file mode 100644 index 6c8f9bcb3..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_client_async.h +++ /dev/null @@ -1,585 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "" -#include "net_helper.h" -#include "levin_base.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - - -namespace epee -{ -namespace levin -{ - - /************************************************************************ - * levin_client_async - probably it is not really fast implementation, - * each handler thread could make up to 30 ms latency. - * But, handling events in reader thread will cause dead locks in - * case of recursive call (call invoke() to the same connection - * on reader thread on remote invoke() handler) - ***********************************************************************/ - - - class levin_client_async - { - levin_commands_handler* m_pcommands_handler; - void (*commands_handler_destroy)(levin_commands_handler*); - volatile uint32_t m_is_stop; - volatile uint32_t m_threads_count; - ::critical_section m_send_lock; - - std::string m_local_invoke_buff; - ::critical_section m_local_invoke_buff_lock; - volatile int m_invoke_res; - - volatile uint32_t m_invoke_data_ready; - volatile uint32_t m_invoke_is_active; - - boost::mutex m_invoke_event; - boost::condition_variable m_invoke_cond; - size_t m_timeout; - - ::critical_section m_recieved_packets_lock; - struct packet_entry - { - bucket_head m_hd; - std::string m_body; - uint32_t m_connection_index; - }; - std::list m_recieved_packets; - /* - m_current_connection_index needed when some connection was broken and reconnected - in this - case we could have some received packets in que, which shoud not be handled - */ - volatile uint32_t m_current_connection_index; - ::critical_section m_invoke_lock; - ::critical_section m_reciev_packet_lock; - ::critical_section m_connection_lock; - net_utils::blocked_mode_client m_transport; - public: - levin_client_async():m_pcommands_handler(NULL), commands_handler_destroy(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0) - {} - levin_client_async(const levin_client_async& /*v*/):m_pcommands_handler(NULL), commands_handler_destroy(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0) - {} - ~levin_client_async() - { - boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1); - disconnect(); - - - while(boost::interprocess::ipcdetail::atomic_read32(&m_threads_count)) - ::Sleep(100); - - set_handler(NULL); - } - - void set_handler(levin_commands_handler* phandler, void (*destroy)(levin_commands_handler*) = NULL) - { - if (commands_handler_destroy && m_pcommands_handler) - (*commands_handler_destroy)(m_pcommands_handler); - m_pcommands_handler = phandler; - m_pcommands_handler_destroy = destroy; - } - - bool connect(uint32_t ip, uint32_t port, uint32_t timeout) - { - loop_call_guard(); - critical_region cr(m_connection_lock); - - m_timeout = timeout; - bool res = false; - CRITICAL_REGION_BEGIN(m_reciev_packet_lock); - CRITICAL_REGION_BEGIN(m_send_lock); - res = levin_client_impl::connect(ip, port, timeout); - boost::interprocess::ipcdetail::atomic_inc32(&m_current_connection_index); - CRITICAL_REGION_END(); - CRITICAL_REGION_END(); - if(res && !boost::interprocess::ipcdetail::atomic_read32(&m_threads_count) ) - { - //boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 0);//m_is_stop = false; - boost::thread( boost::bind(&levin_duplex_client::reciever_thread, this) ); - boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) ); - boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) ); - } - - return res; - } - bool is_connected() - { - loop_call_guard(); - critical_region cr(m_cs); - return levin_client_impl::is_connected(); - } - - inline - bool check_connection() - { - loop_call_guard(); - critical_region cr(m_cs); - - if(!is_connected()) - { - if( !reconnect() ) - { - LOG_ERROR("Reconnect Failed. Failed to invoke() becouse not connected!"); - return false; - } - } - return true; - } - - //------------------------------------------------------------------------------ - inline - bool recv_n(SOCKET s, char* pbuff, size_t cb) - { - while(cb) - { - int res = ::recv(m_socket, pbuff, (int)cb, 0); - - if(SOCKET_ERROR == res) - { - if(!m_connected) - return false; - - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to recv(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - //reconnect(); - return false; - }else if(res == 0) - { - disconnect(); - //reconnect(); - return false; - } - LOG_PRINT_L4("[" << m_socket <<"] RECV " << res); - cb -= res; - pbuff += res; - } - - return true; - } - - //------------------------------------------------------------------------------ - inline - bool recv_n(SOCKET s, std::string& buff) - { - size_t cb_remain = buff.size(); - char* m_current_ptr = (char*)buff.data(); - return recv_n(s, m_current_ptr, cb_remain); - } - - bool disconnect() - { - //boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1);//m_is_stop = true; - loop_call_guard(); - critical_region cr(m_cs); - levin_client_impl::disconnect(); - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - m_local_invoke_buff.clear(); - m_invoke_res = LEVIN_ERROR_CONNECTION_DESTROYED; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true; - m_invoke_cond.notify_all(); - return true; - } - - void loop_call_guard() - { - - } - - void on_leave_invoke() - { - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 0); - } - - int invoke(const GUID& target, int command, const std::string& in_buff, std::string& buff_out) - { - - critical_region cr_invoke(m_invoke_lock); - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 1); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 0); - misc_utils::destr_ptr hdlr = misc_utils::add_exit_scope_handler(boost::bind(&levin_duplex_client::on_leave_invoke, this)); - - loop_call_guard(); - - if(!check_connection()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_id = target; -#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS - ::UuidCreate(&head.m_id); -#endif - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - LOG_PRINT("[" << m_socket <<"] Sending invoke data", LOG_LEVEL_4); - - CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head)); - int res = ::send(m_socket, (const char*)&head, sizeof(head), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size()); - res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - //hard coded timeout in 10 minutes for maximum invoke period. if it happens, it could mean only some real troubles. - boost::system_time timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100); - size_t timeout_count = 0; - boost::unique_lock lock(m_invoke_event); - - while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_data_ready)) - { - if(!m_invoke_cond.timed_wait(lock, timeout)) - { - if(timeout_count < 10) - { - //workaround to avoid freezing at timed_wait called after notify_all. - timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100); - ++timeout_count; - continue; - }else if(timeout_count == 10) - { - //workaround to avoid freezing at timed_wait called after notify_all. - timeout = boost::get_system_time()+ boost::posix_time::minutes(10); - ++timeout_count; - continue; - }else - { - LOG_PRINT("[" << m_socket <<"] Timeout on waiting invoke result. ", LOG_LEVEL_0); - //disconnect(); - return LEVIN_ERROR_CONNECTION_TIMEDOUT; - } - } - } - - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - buff_out.swap(m_local_invoke_buff); - m_local_invoke_buff.clear(); - CRITICAL_REGION_END(); - return m_invoke_res; - } - - int notify(const GUID& target, int command, const std::string& in_buff) - { - if(!check_connection()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_id = target; -#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS - ::UuidCreate(&head.m_id); -#endif - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head)); - int res = ::send(m_socket, (const char*)&head, sizeof(head), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size()); - res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - return 1; - } - - - private: - bool have_some_data(SOCKET sock, int interval = 1) - { - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - fd_set fdse; - FD_ZERO(&fdse); - FD_SET(sock, &fdse); - - - timeval tv; - tv.tv_sec = interval; - tv.tv_usec = 0; - - int sel_res = select(0, &fds, 0, &fdse, &tv); - if(0 == sel_res) - return false; - else if(sel_res == SOCKET_ERROR) - { - if(m_is_stop) - return false; - int err_code = ::WSAGetLastError(); - LOG_ERROR("Filed to call select, err code = " << err_code); - disconnect(); - }else - { - if(fds.fd_array[0]) - {//some read operations was performed - return true; - }else if(fdse.fd_array[0]) - {//some error was at the socket - return true; - } - } - return false; - } - - - bool reciev_and_process_incoming_data() - { - bucket_head head = {0}; - uint32_t conn_index = 0; - bool is_request = false; - std::string local_buff; - CRITICAL_REGION_BEGIN(m_reciev_packet_lock);//to protect from socket reconnect between head and body - - if(!recv_n(m_socket, (char*)&head, sizeof(head))) - { - if(m_is_stop) - return false; - LOG_ERROR("Failed to recv_n"); - return false; - } - - conn_index = boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index); - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_ERROR("Signature mismatch in response"); - return false; - } - - is_request = (head.m_protocol_version == LEVIN_PROTOCOL_VER_1 && head.m_flags&LEVIN_PACKET_REQUEST); - - - local_buff.resize((size_t)head.m_cb); - if(!recv_n(m_socket, local_buff)) - { - if(m_is_stop) - return false; - LOG_ERROR("Filed to reciev"); - return false; - } - CRITICAL_REGION_END(); - - LOG_PRINT_L4("LEVIN_PACKET_RECIEVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - if(is_request) - { - CRITICAL_REGION_BEGIN(m_recieved_packets_lock); - m_recieved_packets.resize(m_recieved_packets.size() + 1); - m_recieved_packets.back().m_hd = head; - m_recieved_packets.back().m_body.swap(local_buff); - m_recieved_packets.back().m_connection_index = conn_index; - CRITICAL_REGION_END(); - /* - - */ - }else - {//this is some response - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - m_local_invoke_buff.swap(local_buff); - m_invoke_res = head.m_return_code; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true; - m_invoke_cond.notify_all(); - - } - return true; - } - - bool reciever_thread() - { - LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread started.[m_threads_count=" << m_threads_count << "]"); - log_space::log_singletone::set_thread_log_prefix("RECIEVER_WORKER"); - boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); - - while(!m_is_stop) - { - if(!m_connected) - { - Sleep(100); - continue; - } - - if(have_some_data(m_socket, 1)) - { - if(!reciev_and_process_incoming_data()) - { - if(m_is_stop) - { - break;//boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - //return true; - } - LOG_ERROR("Failed to reciev_and_process_incoming_data. shutting down"); - //boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - //disconnect_no_wait(); - //break; - } - } - } - - boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread stopped.[m_threads_count=" << m_threads_count << "]"); - return true; - } - - bool process_recieved_packet(bucket_head& head, const std::string& local_buff, uint32_t conn_index) - { - - net_utils::connection_context_base conn_context; - conn_context.m_remote_address = m_address; - if(head.m_have_to_return_data) - { - std::string return_buff; - if(m_pcommands_handler) - head.m_return_code = m_pcommands_handler->invoke(head.m_id, head.m_command, local_buff, return_buff, conn_context); - else - head.m_return_code = LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; - - - - head.m_cb = return_buff.size(); - head.m_have_to_return_data = false; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_RESPONSE; - - std::string send_buff((const char*)&head, sizeof(head)); - send_buff += return_buff; - CRITICAL_REGION_BEGIN(m_send_lock); - if(conn_index != boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index)) - {//there was reconnect, send response back is not allowed - return true; - } - int res = ::send(m_socket, (const char*)send_buff.data(), send_buff.size(), 0); - if(res == SOCKET_ERROR) - { - int err_code = ::WSAGetLastError(); - LOG_ERROR("Failed to send, err = " << err_code); - return false; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - } - else - { - if(m_pcommands_handler) - m_pcommands_handler->notify(head.m_id, head.m_command, local_buff, conn_context); - } - - return true; - } - - bool handler_thread() - { - LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread started.[m_threads_count=" << m_threads_count << "]"); - log_space::log_singletone::set_thread_log_prefix("HANDLER_WORKER"); - boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); - - while(!m_is_stop) - { - bool have_some_work = false; - std::string local_buff; - bucket_head bh = {0}; - uint32_t conn_index = 0; - - CRITICAL_REGION_BEGIN(m_recieved_packets_lock); - if(m_recieved_packets.size()) - { - bh = m_recieved_packets.begin()->m_hd; - conn_index = m_recieved_packets.begin()->m_connection_index; - local_buff.swap(m_recieved_packets.begin()->m_body); - have_some_work = true; - m_recieved_packets.pop_front(); - } - CRITICAL_REGION_END(); - - if(have_some_work) - { - process_recieved_packet(bh, local_buff, conn_index); - }else - { - //Idle when no work - Sleep(30); - } - } - - boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread stopped.[m_threads_count=" << m_threads_count << "]"); - return true; - } - }; - -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_client_async.inl b/src/Native/libcryptonote/contrib/epee/include/net/levin_client_async.inl deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_helper.h b/src/Native/libcryptonote/contrib/epee/include/net/levin_helper.h deleted file mode 100644 index 05560dd90..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_helper.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "levin_base.h" -#include "serializeble_struct_helper.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace levin -{ - template - bool pack_struct_to_levin_message(const t_struct& t, std::string& buff, int command_id) - { - buff.resize(sizeof(levin::bucket_head)); - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = 0; - head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; - head.m_reservedA = rand(); //probably some flags in future - head.m_reservedB = rand(); //probably some check summ in future - - std::string buff_strg; - if(!StorageNamed::save_struct_as_storage_to_buff_t(t, buff_strg)) - return false; - - head.m_cb = buff_strg.size(); - buff.append(buff_strg); - return true; - } - - - bool pack_data_to_levin_message(const std::string& data, std::string& buff, int command_id) - { - buff.resize(sizeof(levin::bucket_head)); - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = 0; - head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; - head.m_reservedA = rand(); //probably some flags in future - head.m_reservedB = rand(); //probably some check summ in future - - head.m_cb = data.size(); - buff.append(data); - return true; - } - - bool load_levin_data_from_levin_message(std::string& levin_data, const std::string& buff, int& command) - { - if(buff.size() < sizeof(levin::bucket_head) ) - { - LOG_PRINT_L3("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); - return false; - } - - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - if(head.m_signature != LEVIN_SIGNATURE) - { - LOG_PRINT_L3("Failed to read signature in levin message, at load_struct_from_levin_message"); - return false; - } - if(head.m_cb != buff.size()-sizeof(levin::bucket_head)) - { - LOG_PRINT_L3("sizes mismatch, at load_struct_from_levin_message"); - return false; - } - - //std::string buff_strg; - levin_data.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head)); - command = head.m_command; - return true; - } - - template - bool load_struct_from_levin_message(t_struct& t, const std::string& buff, int& command) - { - if(buff.size() < sizeof(levin::bucket_head) ) - { - LOG_ERROR("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); - return false; - } - - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - if(head.m_signature != LEVIN_SIGNATURE) - { - LOG_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message"); - return false; - } - if(head.m_cb != buff.size()-sizeof(levin::bucket_head)) - { - LOG_ERROR("sizes mismatch, at load_struct_from_levin_message"); - return false; - } - - std::string buff_strg; - buff_strg.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head)); - - if(!StorageNamed::load_struct_from_storage_buff_t(t, buff_strg)) - { - LOG_ERROR("Failed to read storage, at load_struct_from_levin_message"); - return false; - } - command = head.m_command; - return true; - } -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_protocol_handler.h b/src/Native/libcryptonote/contrib/epee/include/net/levin_protocol_handler.h deleted file mode 100644 index b3a75bedc..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_protocol_handler.h +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _LEVIN_PROTOCOL_HANDLER_H_ -#define _LEVIN_PROTOCOL_HANDLER_H_ - -#include -#include "levin_base.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace levin -{ - template - struct protocl_handler_config - { - levin_commands_handler* m_pcommands_handler; - void (*m_pcommands_handler_destroy)(levin_commands_handler*); - ~protocl_handler_config() { if (m_pcommands_handler && m_pcommands_handler_destroy) (*m_pcommands_handler_destroy)(m_pcommands_handler); } - }; - - template - class protocol_handler - { - public: - typedef t_connection_context connection_context; - typedef protocl_handler_config config_type; - - protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context); - virtual ~protocol_handler(){} - - virtual bool handle_recv(const void* ptr, size_t cb); - - bool after_init_connection(){return true;} - private: - enum connection_data_state - { - conn_state_reading_head, - conn_state_reading_body - }; - - - config_type& m_config; - t_connection_context& m_conn_context; - net_utils::i_service_endpoint* m_psnd_hndlr; - std::string m_cach_in_buffer; - connection_data_state m_state; - bucket_head m_current_head; - }; - - template - protocol_handler::protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context): - m_config(config), - m_conn_context(conn_context), - m_psnd_hndlr(psnd_hndlr), - m_state(conn_state_reading_head), - m_current_head(bucket_head()) - {} - - template - bool protocol_handler::handle_recv(const void* ptr, size_t cb) - { - if(!m_config.m_pcommands_handler) - { - LOG_ERROR_CC(m_conn_context, "Command handler not set!"); - return false; - } - m_cach_in_buffer.append((const char*)ptr, cb); - - bool is_continue = true; - while(is_continue) - { - switch(m_state) - { - case conn_state_reading_head: - if(m_cach_in_buffer.size() < sizeof(bucket_head)) - { - if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cach_in_buffer.data()) != LEVIN_SIGNATURE) - { - LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection"); - return false; - } - is_continue = false; - break; - } - { - bucket_head* phead = (bucket_head*)m_cach_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) - { - LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection"); - return false; - } - m_current_head = *phead; - } - m_cach_in_buffer.erase(0, sizeof(bucket_head)); - m_state = conn_state_reading_body; - break; - case conn_state_reading_body: - if(m_cach_in_buffer.size() < m_current_head.m_cb) - { - is_continue = false; - break; - } - { - std::string buff_to_invoke; - if(m_cach_in_buffer.size() == m_current_head.m_cb) - buff_to_invoke.swap(m_cach_in_buffer); - else - { - buff_to_invoke.assign(m_cach_in_buffer, 0, (std::string::size_type)m_current_head.m_cb); - m_cach_in_buffer.erase(0, (std::string::size_type)m_current_head.m_cb); - } - - - if(m_current_head.m_have_to_return_data) - { - std::string return_buff; - m_current_head.m_return_code = m_config.m_pcommands_handler->invoke(m_current_head.m_command, buff_to_invoke, return_buff, m_conn_context); - m_current_head.m_cb = return_buff.size(); - m_current_head.m_have_to_return_data = false; - std::string send_buff((const char*)&m_current_head, sizeof(m_current_head)); - send_buff += return_buff; - - if(!m_psnd_hndlr->do_send(send_buff.data(), send_buff.size())) - return false; - - } - else - m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_conn_context); - } - m_state = conn_state_reading_head; - break; - default: - LOG_ERROR_CC(m_conn_context, "Undefined state in levin_server_impl::connection_handler, m_state=" << m_state); - return false; - } - } - - return true; - } - - - - - - - -} -} - - - - -#endif //_LEVIN_PROTOCOL_HANDLER_H_ - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_protocol_handler_async.h b/src/Native/libcryptonote/contrib/epee/include/net/levin_protocol_handler_async.h deleted file mode 100644 index 0b1fe05fa..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_protocol_handler_async.h +++ /dev/null @@ -1,911 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include -#include -#include -#include -#include - -#include - -#include "levin_base.h" -#include "misc_language.h" -#include "syncobj.h" -#include "misc_os_dependent.h" - -#include -#include - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -#ifndef MIN_BYTES_WANTED -#define MIN_BYTES_WANTED 512 -#endif - -namespace epee -{ -namespace levin -{ - -/************************************************************************/ -/* */ -/************************************************************************/ -template -class async_protocol_handler; - -template -class async_protocol_handler_config -{ - typedef boost::unordered_map* > connections_map; - critical_section m_connects_lock; - connections_map m_connects; - - void add_connection(async_protocol_handler* pc); - void del_connection(async_protocol_handler* pc); - - async_protocol_handler* find_connection(boost::uuids::uuid connection_id) const; - int find_and_lock_connection(boost::uuids::uuid connection_id, async_protocol_handler*& aph); - - friend class async_protocol_handler; - - levin_commands_handler* m_pcommands_handler; - void (*m_pcommands_handler_destroy)(levin_commands_handler*); - - void delete_connections (size_t count, bool incoming); - -public: - typedef t_connection_context connection_context; - uint64_t m_max_packet_size; - uint64_t m_invoke_timeout; - - int invoke(int command, const std::string& in_buff, std::string& buff_out, boost::uuids::uuid connection_id); - template - int invoke_async(int command, const std::string& in_buff, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED); - - int notify(int command, const std::string& in_buff, boost::uuids::uuid connection_id); - bool close(boost::uuids::uuid connection_id); - bool update_connection_context(const t_connection_context& contxt); - bool request_callback(boost::uuids::uuid connection_id); - template - bool foreach_connection(const callback_t &cb); - template - bool for_connection(const boost::uuids::uuid &connection_id, const callback_t &cb); - size_t get_connections_count(); - void set_handler(levin_commands_handler* handler, void (*destroy)(levin_commands_handler*) = NULL); - - async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE) - {} - ~async_protocol_handler_config() { set_handler(NULL, NULL); } - void del_out_connections(size_t count); - void del_in_connections(size_t count); -}; - - -/************************************************************************/ -/* */ -/************************************************************************/ -template -class async_protocol_handler -{ -public: - typedef t_connection_context connection_context; - typedef async_protocol_handler_config config_type; - - enum stream_state - { - stream_state_head, - stream_state_body - }; - - std::atomic m_deletion_initiated; - std::atomic m_protocol_released; - volatile uint32_t m_invoke_buf_ready; - - volatile int m_invoke_result_code; - - critical_section m_local_inv_buff_lock; - std::string m_local_inv_buff; - - critical_section m_send_lock; - critical_section m_call_lock; - - volatile uint32_t m_wait_count; - volatile uint32_t m_close_called; - bucket_head2 m_current_head; - net_utils::i_service_endpoint* m_pservice_endpoint; - config_type& m_config; - t_connection_context& m_connection_context; - - std::string m_cache_in_buffer; - stream_state m_state; - - int32_t m_oponent_protocol_ver; - bool m_connection_initialized; - - struct invoke_response_handler_base - { - virtual bool handle(int res, const std::string& buff, connection_context& context)=0; - virtual bool is_timer_started() const=0; - virtual void cancel()=0; - virtual bool cancel_timer()=0; - virtual void reset_timer()=0; - }; - template - struct anvoke_handler: invoke_response_handler_base - { - anvoke_handler(const callback_t& cb, uint64_t timeout, async_protocol_handler& con, int command) - :m_cb(cb), m_timeout(timeout), m_con(con), m_timer(con.m_pservice_endpoint->get_io_service()), m_timer_started(false), - m_cancel_timer_called(false), m_timer_cancelled(false), m_command(command) - { - if(m_con.start_outer_call()) - { - MDEBUG(con.get_context_ref() << "anvoke_handler, timeout: " << timeout); - m_timer.expires_from_now(boost::posix_time::milliseconds(timeout)); - m_timer.async_wait([&con, command, cb, timeout](const boost::system::error_code& ec) - { - if(ec == boost::asio::error::operation_aborted) - return; - MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout); - std::string fake; - cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref()); - con.close(); - con.finish_outer_call(); - }); - m_timer_started = true; - } - } - virtual ~anvoke_handler() - {} - callback_t m_cb; - async_protocol_handler& m_con; - boost::asio::deadline_timer m_timer; - bool m_timer_started; - bool m_cancel_timer_called; - bool m_timer_cancelled; - uint64_t m_timeout; - int m_command; - virtual bool handle(int res, const std::string& buff, typename async_protocol_handler::connection_context& context) - { - if(!cancel_timer()) - return false; - m_cb(res, buff, context); - m_con.finish_outer_call(); - return true; - } - virtual bool is_timer_started() const - { - return m_timer_started; - } - virtual void cancel() - { - if(cancel_timer()) - { - std::string fake; - m_cb(LEVIN_ERROR_CONNECTION_DESTROYED, fake, m_con.get_context_ref()); - m_con.finish_outer_call(); - } - } - virtual bool cancel_timer() - { - if(!m_cancel_timer_called) - { - m_cancel_timer_called = true; - boost::system::error_code ignored_ec; - m_timer_cancelled = 1 == m_timer.cancel(ignored_ec); - } - return m_timer_cancelled; - } - virtual void reset_timer() - { - boost::system::error_code ignored_ec; - if (!m_cancel_timer_called && m_timer.cancel(ignored_ec) > 0) - { - callback_t& cb = m_cb; - uint64_t timeout = m_timeout; - async_protocol_handler& con = m_con; - int command = m_command; - m_timer.expires_from_now(boost::posix_time::milliseconds(m_timeout)); - m_timer.async_wait([&con, cb, command, timeout](const boost::system::error_code& ec) - { - if(ec == boost::asio::error::operation_aborted) - return; - MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout); - std::string fake; - cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref()); - con.close(); - con.finish_outer_call(); - }); - } - } - }; - critical_section m_invoke_response_handlers_lock; - std::list > m_invoke_response_handlers; - - template - bool add_invoke_response_handler(const callback_t &cb, uint64_t timeout, async_protocol_handler& con, int command) - { - CRITICAL_REGION_LOCAL(m_invoke_response_handlers_lock); - boost::shared_ptr handler(boost::make_shared>(cb, timeout, con, command)); - m_invoke_response_handlers.push_back(handler); - return handler->is_timer_started(); - } - template friend struct anvoke_handler; -public: - async_protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, - config_type& config, - t_connection_context& conn_context): - m_current_head(bucket_head2()), - m_pservice_endpoint(psnd_hndlr), - m_config(config), - m_connection_context(conn_context), - m_state(stream_state_head) - { - m_close_called = 0; - m_deletion_initiated = false; - m_protocol_released = false; - m_wait_count = 0; - m_oponent_protocol_ver = 0; - m_connection_initialized = false; - } - virtual ~async_protocol_handler() - { - m_deletion_initiated = true; - if(m_connection_initialized) - { - m_config.del_connection(this); - } - - for (size_t i = 0; i < 60 * 1000 / 100 && 0 != boost::interprocess::ipcdetail::atomic_read32(&m_wait_count); ++i) - { - misc_utils::sleep_no_w(100); - } - CHECK_AND_ASSERT_MES_NO_RET(0 == boost::interprocess::ipcdetail::atomic_read32(&m_wait_count), "Failed to wait for operation completion. m_wait_count = " << m_wait_count); - - MTRACE(m_connection_context << "~async_protocol_handler()"); - } - - bool start_outer_call() - { - MTRACE(m_connection_context << "[levin_protocol] -->> start_outer_call"); - if(!m_pservice_endpoint->add_ref()) - { - MERROR(m_connection_context << "[levin_protocol] -->> start_outer_call failed"); - return false; - } - boost::interprocess::ipcdetail::atomic_inc32(&m_wait_count); - return true; - } - bool finish_outer_call() - { - MTRACE(m_connection_context << "[levin_protocol] <<-- finish_outer_call"); - boost::interprocess::ipcdetail::atomic_dec32(&m_wait_count); - m_pservice_endpoint->release(); - return true; - } - - bool release_protocol() - { - decltype(m_invoke_response_handlers) local_invoke_response_handlers; - CRITICAL_REGION_BEGIN(m_invoke_response_handlers_lock); - local_invoke_response_handlers.swap(m_invoke_response_handlers); - m_protocol_released = true; - CRITICAL_REGION_END(); - - // Never call callback inside critical section, that can cause deadlock. Callback can be called when - // invoke_response_handler_base is cancelled - std::for_each(local_invoke_response_handlers.begin(), local_invoke_response_handlers.end(), [](const boost::shared_ptr& pinv_resp_hndlr) { - pinv_resp_hndlr->cancel(); - }); - - return true; - } - - bool close() - { - boost::interprocess::ipcdetail::atomic_inc32(&m_close_called); - - m_pservice_endpoint->close(); - return true; - } - - void update_connection_context(const connection_context& contxt) - { - m_connection_context = contxt; - } - - void request_callback() - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - m_pservice_endpoint->request_callback(); - } - - void handle_qued_callback() - { - m_config.m_pcommands_handler->callback(m_connection_context); - } - - virtual bool handle_recv(const void* ptr, size_t cb) - { - if(boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) - return false; //closing connections - - if(!m_config.m_pcommands_handler) - { - MERROR(m_connection_context << "Commands handler not set!"); - return false; - } - - if(m_cache_in_buffer.size() + cb > m_config.m_max_packet_size) - { - MWARNING(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet received " << m_cache_in_buffer.size() + cb - << ", connection will be closed."); - return false; - } - - m_cache_in_buffer.append((const char*)ptr, cb); - - bool is_continue = true; - while(is_continue) - { - switch(m_state) - { - case stream_state_body: - if(m_cache_in_buffer.size() < m_current_head.m_cb) - { - is_continue = false; - if(cb >= MIN_BYTES_WANTED) - { - CRITICAL_REGION_LOCAL(m_invoke_response_handlers_lock); - if (!m_invoke_response_handlers.empty()) - { - //async call scenario - boost::shared_ptr response_handler = m_invoke_response_handlers.front(); - response_handler->reset_timer(); - MDEBUG(m_connection_context << "LEVIN_PACKET partial msg received. len=" << cb); - } - } - break; - } - { - std::string buff_to_invoke; - if(m_cache_in_buffer.size() == m_current_head.m_cb) - buff_to_invoke.swap(m_cache_in_buffer); - else - { - buff_to_invoke.assign(m_cache_in_buffer, 0, (std::string::size_type)m_current_head.m_cb); - m_cache_in_buffer.erase(0, (std::string::size_type)m_current_head.m_cb); - } - - bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE); - - MDEBUG(m_connection_context << "LEVIN_PACKET_RECIEVED. [len=" << m_current_head.m_cb - << ", flags" << m_current_head.m_flags - << ", r?=" << m_current_head.m_have_to_return_data - <<", cmd = " << m_current_head.m_command - << ", v=" << m_current_head.m_protocol_version); - - if(is_response) - {//response to some invoke - - epee::critical_region_t invoke_response_handlers_guard(m_invoke_response_handlers_lock); - if(!m_invoke_response_handlers.empty()) - {//async call scenario - boost::shared_ptr response_handler = m_invoke_response_handlers.front(); - bool timer_cancelled = response_handler->cancel_timer(); - // Don't pop handler, to avoid destroying it - if(timer_cancelled) - m_invoke_response_handlers.pop_front(); - invoke_response_handlers_guard.unlock(); - - if(timer_cancelled) - response_handler->handle(m_current_head.m_return_code, buff_to_invoke, m_connection_context); - } - else - { - invoke_response_handlers_guard.unlock(); - //use sync call scenario - if(!boost::interprocess::ipcdetail::atomic_read32(&m_wait_count) && !boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) - { - MERROR(m_connection_context << "no active invoke when response came, wtf?"); - return false; - }else - { - CRITICAL_REGION_BEGIN(m_local_inv_buff_lock); - buff_to_invoke.swap(m_local_inv_buff); - buff_to_invoke.clear(); - m_invoke_result_code = m_current_head.m_return_code; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 1); - } - } - }else - { - if(m_current_head.m_have_to_return_data) - { - std::string return_buff; - m_current_head.m_return_code = m_config.m_pcommands_handler->invoke( - m_current_head.m_command, - buff_to_invoke, - return_buff, - m_connection_context); - m_current_head.m_cb = return_buff.size(); - m_current_head.m_have_to_return_data = false; - m_current_head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - m_current_head.m_flags = LEVIN_PACKET_RESPONSE; - std::string send_buff((const char*)&m_current_head, sizeof(m_current_head)); - send_buff += return_buff; - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(send_buff.data(), send_buff.size())) - return false; - CRITICAL_REGION_END(); - MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << m_current_head.m_cb - << ", flags" << m_current_head.m_flags - << ", r?=" << m_current_head.m_have_to_return_data - <<", cmd = " << m_current_head.m_command - << ", ver=" << m_current_head.m_protocol_version); - } - else - m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_connection_context); - } - } - m_state = stream_state_head; - break; - case stream_state_head: - { - if(m_cache_in_buffer.size() < sizeof(bucket_head2)) - { - if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cache_in_buffer.data()) != LEVIN_SIGNATURE) - { - MWARNING(m_connection_context << "Signature mismatch, connection will be closed"); - return false; - } - is_continue = false; - break; - } - - bucket_head2* phead = (bucket_head2*)m_cache_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) - { - LOG_ERROR_CC(m_connection_context, "Signature mismatch, connection will be closed"); - return false; - } - m_current_head = *phead; - - m_cache_in_buffer.erase(0, sizeof(bucket_head2)); - m_state = stream_state_body; - m_oponent_protocol_ver = m_current_head.m_protocol_version; - if(m_current_head.m_cb > m_config.m_max_packet_size) - { - LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet header received " << m_current_head.m_cb - << ", connection will be closed."); - return false; - } - } - break; - default: - LOG_ERROR_CC(m_connection_context, "Undefined state in levin_server_impl::connection_handler, m_state=" << m_state); - return false; - } - } - - return true; - } - - bool after_init_connection() - { - if (!m_connection_initialized) - { - m_connection_initialized = true; - m_config.add_connection(this); - } - return true; - } - - template - bool async_invoke(int command, const std::string& in_buff, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(timeout == LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) - timeout = m_config.m_invoke_timeout; - - int err_code = LEVIN_OK; - do - { - if(m_deletion_initiated) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); - CRITICAL_REGION_BEGIN(m_send_lock); - CRITICAL_REGION_LOCAL1(m_invoke_response_handlers_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); - err_code = LEVIN_ERROR_CONNECTION; - break; - } - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); - err_code = LEVIN_ERROR_CONNECTION; - break; - } - - if(!add_invoke_response_handler(cb, timeout, *this, command)) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - CRITICAL_REGION_END(); - } while (false); - - if (LEVIN_OK != err_code) - { - std::string stub_buff; - // Never call callback inside critical section, that can cause deadlock - cb(err_code, stub_buff, m_connection_context); - return false; - } - - return true; - } - - int invoke(int command, const std::string& in_buff, std::string& buff_out) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); - return LEVIN_ERROR_CONNECTION; - } - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); - return LEVIN_ERROR_CONNECTION; - } - CRITICAL_REGION_END(); - - MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << head.m_cb - << ", f=" << head.m_flags - << ", r?=" << head.m_have_to_return_data - << ", cmd = " << head.m_command - << ", ver=" << head.m_protocol_version); - - uint64_t ticks_start = misc_utils::get_tick_count(); - size_t prev_size = 0; - - while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_buf_ready) && !m_deletion_initiated && !m_protocol_released) - { - if(m_cache_in_buffer.size() - prev_size >= MIN_BYTES_WANTED) - { - prev_size = m_cache_in_buffer.size(); - ticks_start = misc_utils::get_tick_count(); - } - if(misc_utils::get_tick_count() - ticks_start > m_config.m_invoke_timeout) - { - MWARNING(m_connection_context << "invoke timeout (" << m_config.m_invoke_timeout << "), closing connection "); - close(); - return LEVIN_ERROR_CONNECTION_TIMEDOUT; - } - if(!m_pservice_endpoint->call_run_once_service_io()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - - if(m_deletion_initiated || m_protocol_released) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_BEGIN(m_local_inv_buff_lock); - buff_out.swap(m_local_inv_buff); - m_local_inv_buff.clear(); - CRITICAL_REGION_END(); - - return m_invoke_result_code; - } - - int notify(int command, const std::string& in_buff) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_have_to_return_data = false; - head.m_cb = in_buff.size(); - - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send()"); - return -1; - } - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send()"); - return -1; - } - CRITICAL_REGION_END(); - LOG_DEBUG_CC(m_connection_context, "LEVIN_PACKET_SENT. [len=" << head.m_cb << - ", f=" << head.m_flags << - ", r?=" << head.m_have_to_return_data << - ", cmd = " << head.m_command << - ", ver=" << head.m_protocol_version); - - return 1; - } - //------------------------------------------------------------------------------------------ - boost::uuids::uuid get_connection_id() {return m_connection_context.m_connection_id;} - //------------------------------------------------------------------------------------------ - t_connection_context& get_context_ref() {return m_connection_context;} -}; -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::del_connection(async_protocol_handler* pconn) -{ - CRITICAL_REGION_BEGIN(m_connects_lock); - m_connects.erase(pconn->get_connection_id()); - CRITICAL_REGION_END(); - m_pcommands_handler->on_connection_close(pconn->m_connection_context); -} -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::delete_connections(size_t count, bool incoming) -{ - std::vector connections; - CRITICAL_REGION_BEGIN(m_connects_lock); - for (auto& c: m_connects) - { - if (c.second->m_connection_context.m_is_income == incoming) - connections.push_back(c.first); - } - - // close random connections from the provided set - // TODO or better just keep removing random elements (performance) - unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); - shuffle(connections.begin(), connections.end(), std::default_random_engine(seed)); - while (count > 0 && connections.size() > 0) - { - try - { - auto i = connections.end() - 1; - async_protocol_handler *conn = m_connects.at(*i); - del_connection(conn); - close(*i); - connections.erase(i); - } - catch (const std::out_of_range &e) - { - MWARNING("Connection not found in m_connects, continuing"); - } - --count; - } - - CRITICAL_REGION_END(); -} -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::del_out_connections(size_t count) -{ - delete_connections(count, false); -} -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::del_in_connections(size_t count) -{ - delete_connections(count, true); -} -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::add_connection(async_protocol_handler* pconn) -{ - CRITICAL_REGION_BEGIN(m_connects_lock); - m_connects[pconn->get_connection_id()] = pconn; - CRITICAL_REGION_END(); - m_pcommands_handler->on_connection_new(pconn->m_connection_context); -} -//------------------------------------------------------------------------------------------ -template -async_protocol_handler* async_protocol_handler_config::find_connection(boost::uuids::uuid connection_id) const -{ - auto it = m_connects.find(connection_id); - return it == m_connects.end() ? 0 : it->second; -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::find_and_lock_connection(boost::uuids::uuid connection_id, async_protocol_handler*& aph) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - aph = find_connection(connection_id); - if(0 == aph) - return LEVIN_ERROR_CONNECTION_NOT_FOUND; - if(!aph->start_outer_call()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - return LEVIN_OK; -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::invoke(int command, const std::string& in_buff, std::string& buff_out, boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->invoke(command, in_buff, buff_out) : r; -} -//------------------------------------------------------------------------------------------ -template template -int async_protocol_handler_config::invoke_async(int command, const std::string& in_buff, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->async_invoke(command, in_buff, cb, timeout) : r; -} -//------------------------------------------------------------------------------------------ -template template -bool async_protocol_handler_config::foreach_connection(const callback_t &cb) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - for(auto& c: m_connects) - { - async_protocol_handler* aph = c.second; - if(!cb(aph->get_context_ref())) - return false; - } - return true; -} -//------------------------------------------------------------------------------------------ -template template -bool async_protocol_handler_config::for_connection(const boost::uuids::uuid &connection_id, const callback_t &cb) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - async_protocol_handler* aph = find_connection(connection_id); - if (!aph) - return false; - if(!cb(aph->get_context_ref())) - return false; - return true; -} -//------------------------------------------------------------------------------------------ -template -size_t async_protocol_handler_config::get_connections_count() -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - return m_connects.size(); -} -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::set_handler(levin_commands_handler* handler, void (*destroy)(levin_commands_handler*)) -{ - if (m_pcommands_handler && m_pcommands_handler_destroy) - (*m_pcommands_handler_destroy)(m_pcommands_handler); - m_pcommands_handler = handler; - m_pcommands_handler_destroy = destroy; -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::notify(int command, const std::string& in_buff, boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->notify(command, in_buff) : r; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::close(boost::uuids::uuid connection_id) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - async_protocol_handler* aph = find_connection(connection_id); - return 0 != aph ? aph->close() : false; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::update_connection_context(const t_connection_context& contxt) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - async_protocol_handler* aph = find_connection(contxt.m_connection_id); - if(0 == aph) - return false; - aph->update_connection_context(contxt); - return true; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::request_callback(boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - if(LEVIN_OK == r) - { - aph->request_callback(); - return true; - } - else - { - return false; - } -} -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_server_cp.h b/src/Native/libcryptonote/contrib/epee/include/net/levin_server_cp.h deleted file mode 100644 index 8ece35059..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_server_cp.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server_cp.h" -#include "levin_protocol_handler.h" -namespace epee -{ -namespace net_utils -{ - typedef cp_server_impl cp_levin_server; -} -} - - - -#endif - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/levin_server_cp2.h b/src/Native/libcryptonote/contrib/epee/include/net/levin_server_cp2.h deleted file mode 100644 index b29d49bf8..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/levin_server_cp2.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server2.h" -#include "levin_protocol_handler.h" -#include "levin_protocol_handler_async.h" - -namespace epee -{ -namespace net_utils -{ - typedef boosted_tcp_server > boosted_levin_server; - typedef boosted_tcp_server > boosted_levin_async_server; -} -} - - - -#endif - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/local_ip.h b/src/Native/libcryptonote/contrib/epee/include/net/local_ip.h deleted file mode 100644 index 0d458963c..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/local_ip.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -namespace epee -{ - namespace net_utils - { - inline - bool is_ip_local(uint32_t ip) - { - /* - local ip area - 10.0.0.0 — 10.255.255.255 - 172.16.0.0 — 172.31.255.255 - 192.168.0.0 — 192.168.255.255 - */ - if( (ip | 0xffffff00) == 0xffffff0a) - return true; - - if( (ip | 0xffff0000) == 0xffffa8c0) - return true; - - if( (ip | 0xffffff00) == 0xffffffac) - { - uint32_t second_num = (ip << 8) & 0xff000000; - if(second_num >= 16 && second_num <= 31 ) - return true; - } - return false; - } - inline - bool is_ip_loopback(uint32_t ip) - { - if( (ip | 0xffffff00) == 0xffffff7f) - return true; - //MAKE_IP - /* - loopback ip - 127.0.0.0 — 127.255.255.255 - */ - return false; - } - - } -} - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/multiprotocols_server.h b/src/Native/libcryptonote/contrib/epee/include/net/multiprotocols_server.h deleted file mode 100644 index 4807a4421..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/multiprotocols_server.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MULTIPROTOCOLS_SERVER_H_ -#define _MULTIPROTOCOLS_SERVER_H_ - -//#include "abstract_tcp_server_cp.h" -#include "protocol_switcher.h" -#include "abstract_tcp_server2.h" - -namespace epee -{ -namespace net_utils -{ - //typedef cp_server_impl multiprotocol_server; - typedef boosted_tcp_server boosted_multiprotocol_server; -} -} - - -#endif //_MULTIPROTOCOLS_SERVER_H_ - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/munin_connection_handler.h b/src/Native/libcryptonote/contrib/epee/include/net/munin_connection_handler.h deleted file mode 100644 index 62856bec5..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/munin_connection_handler.h +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MUNIN_CONNECTION_HANDLER_H_ -#define _MUNIN_CONNECTION_HANDLER_H_ - -#include -#include "net_utils_base.h" -#include "to_nonconst_iterator.h" -#include "http_base.h" -#include "reg_exp_definer.h" - -#define MUNIN_ARGS_DEFAULT(vertial_lable_str) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " \n" -#define MUNIN_ARGS_FORCE_AUPPER_LIMIT(vertial_lable_str, limit) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " --rigid --upper-limit " limit " \n" -#define MUNIN_TITLE(title_str) "graph_title " title_str "\n" -#define MUNIN_CATEGORY(category_str) "graph_category " category_str "\n" -#define MUNIN_INFO(info_str) "graph_info " info_str "\n" -#define MUNIN_ENTRY(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" -#define MUNIN_ENTRY_AREA(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" #var_name".draw AREASTACK\n" -#define MUNIN_ENTRY_ALIAS(var_name, alias) #var_name".label " #alias"\n" #var_name".info "#alias".\n" -#define BEGIN_MUNIN_SERVICE(servivece_name_str) if(servivece_name_str == pservice->m_service_name) { -#define END_MUNIN_SERVICE() } -#define MUNIN_SERVICE_PARAM(munin_var_name_str, variable) paramters_text += std::string() + munin_var_name_str ".value " + boost::lexical_cast(variable) + "\n" - - - - -namespace epee -{ -namespace net_utils -{ - namespace munin - { - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct munin_service; - - struct munin_service_data_provider - { - virtual bool update_service_data(munin_service* pservice, std::string& paramters_text)=0; - }; - - struct munin_service - { - std::string m_service_name; - std::string m_service_config_string; - munin_service_data_provider* m_pdata_provider; - }; - - struct node_server_config - { - std::list m_services; - //TODO: - }; - - struct fake_send_handler: public i_service_endpoint - { - virtual bool do_send(const void* ptr, size_t cb) - { - m_cache += std::string((const char*)ptr, cb); - return true; - } - public: - - std::string m_cache; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class munin_node_server_connection_handler - { - public: - typedef node_server_config config_type; - typedef connection_context_base connection_context; - - munin_node_server_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, const connection_context_base& context):m_psnd_hndlr(psnd_hndlr), - m_machine_state(http_state_retriving_comand_line), - m_config(config) - { - init(); - } - virtual ~munin_node_server_connection_handler() - { - - } - - bool release_protocol() - { - return true; - } - bool after_init_connection() - { - std::string hello_str = "# munin node at "; - hello_str += m_host_name + "\n"; - send_hook(hello_str); - return true; - } - - virtual bool thread_init() - { - return true; - } - - virtual bool thread_deinit() - { - return true; - } - - void handle_qued_callback() - { - - } - - virtual bool handle_recv(const void* ptr, size_t cb) - { - - const char* pbuff = (const char*)ptr; - std::string recvd_buff(pbuff, cb); - LOG_PRINT("munin_recv: \n" << recvd_buff, LOG_LEVEL_3); - - m_cache += recvd_buff; - - bool stop_handling = false; - while(!stop_handling) - { - switch(m_machine_state) - { - case http_state_retriving_comand_line: - { - - std::string::size_type fpos = m_cache.find('\n'); - if(std::string::npos != fpos ) - { - bool res = handle_command(m_cache); - if(!res) - return false; - m_cache.erase(0, fpos+1); - continue; - } - stop_handling = true; - } - break; - case http_state_error: - stop_handling = true; - return false; - default: - LOG_ERROR("Error in munin state machine! Unknown state=" << m_machine_state); - stop_handling = true; - m_machine_state = http_state_error; - return false; - } - - } - - return true; - } - - private: - - - bool init() - { - char hostname[64] = {0}; - int res = gethostname(hostname, 64); - hostname[63] = 0;//be happy - m_host_name = hostname; - return true; - } - bool handle_command(const std::string& command) - { - // list, nodes, config, fetch, version or quit - STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^((list)|(nodes)|(config)|(fetch)|(version)|(quit))(\\s+(\\S+))?", boost::regex::icase | boost::regex::normal); - // 12 3 4 5 6 7 8 9 - size_t match_len = 0; - boost::smatch result; - if(boost::regex_search(command, result, rexp_match_command_line, boost::match_default) && result[0].matched) - { - if(result[2].matched) - {//list command - return handle_list_command(); - }else if(result[3].matched) - {//nodes command - return handle_nodes_command(); - }else if(result[4].matched) - {//config command - if(result[9].matched) - return handle_config_command(result[9]); - else - { - send_hook("Unknown service\n"); - } - }else if(result[5].matched) - {//fetch command - if(result[9].matched) - return handle_fetch_command(result[9]); - else - { - send_hook("Unknown service\n"); - } - }else if(result[6].matched) - {//version command - return handle_version_command(); - }else if(result[7].matched) - {//quit command - return handle_quit_command(); - } - else - return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n"); - } - - return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n");; - } - - bool handle_list_command() - { - std::string buff_to_send; - for(std::list::const_iterator it = m_config.m_services.begin(); it!=m_config.m_services.end();it++) - { - buff_to_send += it->m_service_name + " "; - } - buff_to_send+='\n'; - return send_hook(buff_to_send); - } - bool handle_nodes_command() - { - //supports only one node - host name - send_hook(m_host_name + "\n.\n"); - return true; - } - bool handle_config_command(const std::string& service_name) - { - munin_service* psrv = get_service_by_name(service_name); - if(!psrv) - return send_hook(std::string() + "Unknown service\n"); - - - return send_hook(psrv->m_service_config_string + ".\n"); - } - - bool handle_fetch_command(const std::string& service_name) - { - munin_service* psrv = get_service_by_name(service_name); - if(!psrv) - return send_hook(std::string() + "Unknown service\n"); - - std::string buff; - psrv->m_pdata_provider->update_service_data(psrv, buff); - - buff += ".\n"; - return send_hook(buff); - } - bool handle_version_command() - { - return send_hook("Munin node component by Andrey Sabelnikov\n"); - } - bool handle_quit_command() - { - return false; - } - - bool send_hook(const std::string& buff) - { - LOG_PRINT("munin_send: \n" << buff, LOG_LEVEL_3); - - if(m_psnd_hndlr) - return m_psnd_hndlr->do_send(buff.data(), buff.size()); - else - return false; - } - - - munin_service* get_service_by_name(const std::string& srv_name) - { - std::list::iterator it = m_config.m_services.begin(); - for(; it!=m_config.m_services.end(); it++) - if(it->m_service_name == srv_name) - break; - - if(it==m_config.m_services.end()) - return NULL; - - return &(*it); - } - - enum machine_state{ - http_state_retriving_comand_line, - http_state_error - }; - - - config_type& m_config; - machine_state m_machine_state; - std::string m_cache; - std::string m_host_name; - protected: - i_service_endpoint* m_psnd_hndlr; - }; - - - inline bool test_self() - { - /*WSADATA w; - ::WSAStartup(MAKEWORD(1, 1), &w); - node_server_config sc; - sc.m_services.push_back(munin_service()); - sc.m_services.back().m_service_name = "test_service"; - - sc.m_services.back().m_service_config_string = - "graph_args --base 1000 -l 0 --vertical-label N --upper-limit 329342976\n" - "graph_title REPORTS STATICTICS\n" - "graph_category bind\n" - "graph_info This graph shows how many reports came in fixed time period.\n" - "graph_order apps free swap\n" - "apps.label apps\n" - "apps.draw AREA\n" - "apps.info Memory used by user-space applications.\n" - "swap.label swap\n" - "swap.draw STACK\n" - "swap.info Swap space used.\n" - "free.label unused\n" - "free.draw STACK\n" - "free.info Wasted memory. Memory that is not used for anything at all.\n" - "committed.label committed\n" - "committed.draw LINE2\n" - "committed.warn 625410048\n" - "committed.info The amount of memory that would be used if all the memory that's been allocated were to be used.\n"; - - - sc.m_services.push_back(munin_service()); - sc.m_services.back().m_service_name = "test_service1"; - fake_send_handler fh; - munin_node_server_connection_handler mh(&fh, sc); - - std::string buff = "list\n"; - mh.handle_recv(buff.data(), buff.size()); - - - buff = "nodes\n"; - mh.handle_recv(buff.data(), buff.size()); -*/ - return true; - } - - } -} -} -#endif//!_MUNIN_CONNECTION_HANDLER_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/munin_node_server.h b/src/Native/libcryptonote/contrib/epee/include/net/munin_node_server.h deleted file mode 100644 index e6df390cb..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/munin_node_server.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MUNIN_NODE_SERVER_H_ -#define _MUNIN_NODE_SERVER_H_ - -#include -//#include "net_utils_base.h" -#include "munin_connection_handler.h" -//#include "abstract_tcp_server.h" -//#include "abstract_tcp_server_cp.h" -#include "abstract_tcp_server2.h" -namespace epee -{ -namespace net_utils -{ - namespace munin - { - typedef boosted_tcp_server munin_node_server; - //typedef cp_server_impl munin_node_cp_server; - } -} -} -#endif//!_MUNIN_NODE_SERVER_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/net_helper.h b/src/Native/libcryptonote/contrib/epee/include/net/net_helper.h deleted file mode 100644 index 2c2efcd82..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/net_helper.h +++ /dev/null @@ -1,736 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - -//#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "net/net_utils_base.h" -#include "misc_language.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - - -namespace epee -{ -namespace net_utils -{ - - class blocked_mode_client - { - - - struct handler_obj - { - handler_obj(boost::system::error_code& error, size_t& bytes_transferred):ref_error(error), ref_bytes_transferred(bytes_transferred) - {} - handler_obj(const handler_obj& other_obj):ref_error(other_obj.ref_error), ref_bytes_transferred(other_obj.ref_bytes_transferred) - {} - - boost::system::error_code& ref_error; - size_t& ref_bytes_transferred; - - void operator()(const boost::system::error_code& error, // Result of operation. - std::size_t bytes_transferred // Number of bytes read. - ) - { - ref_error = error; - ref_bytes_transferred = bytes_transferred; - } - }; - - public: - inline - blocked_mode_client():m_initialized(false), - m_connected(false), - m_deadline(m_io_service), - m_shutdowned(0), - m_ssl(false), - m_ctx(boost::asio::ssl::context::sslv23), - m_ssl_socket(m_io_service,m_ctx) - { - - - m_initialized = true; - - - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); - - // Start the persistent actor that checks for deadline expiry. - check_deadline(); - - } - inline - ~blocked_mode_client() - { - //profile_tools::local_coast lc("~blocked_mode_client()", 3); - shutdown(); - } - - inline - bool connect(const std::string& addr, int port, std::chrono::milliseconds timeout, bool ssl = false, const std::string& bind_ip = "0.0.0.0") - { - return connect(addr, std::to_string(port), timeout, ssl, bind_ip); - } - - inline - bool connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout, bool ssl = false, const std::string& bind_ip = "0.0.0.0") - { - m_connected = false; - m_ssl = ssl; - try - { - m_ssl_socket.next_layer().close(); - - // Set SSL options - // disable sslv2 - m_ctx.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2); - m_ctx.set_default_verify_paths(); - - // Get a list of endpoints corresponding to the server name. - - - ////////////////////////////////////////////////////////////////////////// - - boost::asio::ip::tcp::resolver resolver(m_io_service); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port, boost::asio::ip::tcp::resolver::query::canonical_name); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - LOG_ERROR("Failed to resolve " << addr); - return false; - } - - ////////////////////////////////////////////////////////////////////////// - - - //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - - m_ssl_socket.next_layer().open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(addr.c_str()), 0); - m_ssl_socket.next_layer().bind(local_endpoint); - } - - - m_deadline.expires_from_now(timeout); - - - boost::system::error_code ec = boost::asio::error::would_block; - - m_ssl_socket.next_layer().async_connect(remote_endpoint, boost::lambda::var(ec) = boost::lambda::_1); - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - - if (!ec && m_ssl_socket.next_layer().is_open()) - { - m_connected = true; - m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); - // SSL Options - if(m_ssl) { - // Disable verification of host certificate - m_ssl_socket.set_verify_mode(boost::asio::ssl::verify_peer); - // Handshake - m_ssl_socket.next_layer().set_option(boost::asio::ip::tcp::no_delay(true)); - m_ssl_socket.handshake(boost::asio::ssl::stream_base::client); - } - return true; - }else - { - MWARNING("Some problems at connect, message: " << ec.message()); - return false; - } - - } - catch(const boost::system::system_error& er) - { - MDEBUG("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - MDEBUG("Some fatal problems."); - return false; - } - - return true; - } - - inline - bool disconnect() - { - try - { - if(m_connected) - { - m_connected = false; - if(m_ssl) - shutdown_ssl(); - m_ssl_socket.next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both); - } - } - - catch(const boost::system::system_error& /*er*/) - { - //LOG_ERROR("Some problems at disconnect, message: " << er.what()); - return false; - } - catch(...) - { - //LOG_ERROR("Some fatal problems."); - return false; - } - return true; - } - - - inline - bool send(const std::string& buff, std::chrono::milliseconds timeout) - { - - try - { - m_deadline.expires_from_now(timeout); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - async_write(buff.c_str(), buff.size(), ec); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - - if (ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - inline - bool send(const void* data, size_t sz) - { - try - { - /* - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - */ - boost::system::error_code ec; - - size_t writen = write(data, sz, ec); - - if (!writen || ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at send, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - bool is_connected() - { - return m_connected && m_ssl_socket.next_layer().is_open(); - } - - inline - bool recv(std::string& buff, std::chrono::milliseconds timeout) - { - - try - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(timeout); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - //boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - - boost::system::error_code ec = boost::asio::error::would_block; - size_t bytes_transfered = 0; - - handler_obj hndlr(ec, bytes_transfered); - - char local_buff[10000] = {0}; - - async_read(local_buff, sizeof(local_buff), boost::asio::transfer_at_least(1), hndlr); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) - { - m_io_service.run_one(); - } - - - if (ec) - { - MTRACE("READ ENDS: Connection err_code " << ec.value()); - if(ec == boost::asio::error::eof) - { - MTRACE("Connection err_code eof."); - //connection closed there, empty - return true; - } - - MDEBUG("Problems at read: " << ec.message()); - m_connected = false; - return false; - }else - { - MTRACE("READ ENDS: Success. bytes_tr: " << bytes_transfered); - m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); - } - - /*if(!bytes_transfered) - return false;*/ - - buff.assign(local_buff, bytes_transfered); - return true; - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at read, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems at read."); - return false; - } - - - - return false; - - } - - inline bool recv_n(std::string& buff, int64_t sz, std::chrono::milliseconds timeout) - { - - try - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(timeout); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - //boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - - buff.resize(static_cast(sz)); - boost::system::error_code ec = boost::asio::error::would_block; - size_t bytes_transfered = 0; - - - handler_obj hndlr(ec, bytes_transfered); - async_read((char*)buff.data(), buff.size(), boost::asio::transfer_at_least(buff.size()), hndlr); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) - { - m_io_service.run_one(); - } - - if (ec) - { - LOG_PRINT_L3("Problems at read: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); - } - - if(bytes_transfered != buff.size()) - { - LOG_ERROR("Transferred mismatch with transfer_at_least value: m_bytes_transferred=" << bytes_transfered << " at_least value=" << buff.size()); - return false; - } - - return true; - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at read, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems at read."); - return false; - } - - - - return false; - } - - bool shutdown() - { - m_deadline.cancel(); - boost::system::error_code ec; - if(m_ssl) - shutdown_ssl(); - m_ssl_socket.next_layer().cancel(ec); - if(ec) - MDEBUG("Problems at cancel: " << ec.message()); - m_ssl_socket.next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); - if(ec) - MDEBUG("Problems at shutdown: " << ec.message()); - m_ssl_socket.next_layer().close(ec); - if(ec) - MDEBUG("Problems at close: " << ec.message()); - boost::interprocess::ipcdetail::atomic_write32(&m_shutdowned, 1); - m_connected = false; - return true; - } - - void set_connected(bool connected) - { - m_connected = connected; - } - boost::asio::io_service& get_io_service() - { - return m_io_service; - } - - boost::asio::ip::tcp::socket& get_socket() - { - return m_ssl_socket.next_layer(); - } - - private: - - void check_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (m_deadline.expires_at() <= std::chrono::steady_clock::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); - m_connected = false; - m_ssl_socket.next_layer().close(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); - } - - // Put the actor back to sleep. - m_deadline.async_wait(boost::bind(&blocked_mode_client::check_deadline, this)); - } - - void shutdown_ssl() { - // ssl socket shutdown blocks if server doesn't respond. We close after 2 secs - boost::system::error_code ec = boost::asio::error::would_block; - m_deadline.expires_from_now(std::chrono::milliseconds(2000)); - m_ssl_socket.async_shutdown(boost::lambda::var(ec) = boost::lambda::_1); - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - // Ignore "short read" error - if (ec.category() == boost::asio::error::get_ssl_category() && - ec.value() != -#if BOOST_VERSION >= 106200 - boost::asio::ssl::error::stream_truncated -#else // older Boost supports only OpenSSL 1.0, so 1.0-only macros are appropriate - ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ) -#endif - ) - MDEBUG("Problems at ssl shutdown: " << ec.message()); - } - - protected: - bool write(const void* data, size_t sz, boost::system::error_code& ec) - { - bool success; - if(m_ssl) - success = boost::asio::write(m_ssl_socket, boost::asio::buffer(data, sz), ec); - else - success = boost::asio::write(m_ssl_socket.next_layer(), boost::asio::buffer(data, sz), ec); - return success; - } - - void async_write(const void* data, size_t sz, boost::system::error_code& ec) - { - if(m_ssl) - boost::asio::async_write(m_ssl_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - else - boost::asio::async_write(m_ssl_socket.next_layer(), boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - } - - void async_read(char* buff, size_t sz, boost::asio::detail::transfer_at_least_t transfer_at_least, handler_obj& hndlr) - { - if(!m_ssl) - boost::asio::async_read(m_ssl_socket.next_layer(), boost::asio::buffer(buff, sz), transfer_at_least, hndlr); - else - boost::asio::async_read(m_ssl_socket, boost::asio::buffer(buff, sz), transfer_at_least, hndlr); - - } - - protected: - boost::asio::io_service m_io_service; - boost::asio::ssl::context m_ctx; - boost::asio::ssl::stream m_ssl_socket; - bool m_ssl; - bool m_initialized; - bool m_connected; - boost::asio::steady_timer m_deadline; - volatile uint32_t m_shutdowned; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class async_blocked_mode_client: public blocked_mode_client - { - public: - async_blocked_mode_client():m_send_deadline(blocked_mode_client::m_io_service) - { - - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - m_send_deadline.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_send_deadline(); - } - ~async_blocked_mode_client() - { - m_send_deadline.cancel(); - } - - bool shutdown() - { - blocked_mode_client::shutdown(); - m_send_deadline.cancel(); - return true; - } - - inline - bool send(const void* data, size_t sz) - { - try - { - /* - m_send_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - - // Block until the asynchronous operation has completed. - while(ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - }*/ - - boost::system::error_code ec; - - size_t writen = write(data, sz, ec); - - if (!writen || ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - return false; - }else - { - m_send_deadline.expires_at(boost::posix_time::pos_infin); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - - private: - - boost::asio::deadline_timer m_send_deadline; - - void check_send_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (m_send_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); - m_ssl_socket.next_layer().close(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - m_send_deadline.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - m_send_deadline.async_wait(boost::bind(&async_blocked_mode_client::check_send_deadline, this)); - } - }; -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/net_parse_helpers.h b/src/Native/libcryptonote/contrib/epee/include/net/net_parse_helpers.h deleted file mode 100644 index 708cce0ff..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/net_parse_helpers.h +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include "http_base.h" -#include "reg_exp_definer.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -namespace epee -{ -namespace net_utils -{ - - inline bool parse_uri_query(const std::string& query, std::list >& params) - { - enum state - { - st_param_name, - st_param_val - }; - state st = st_param_name; - std::string::const_iterator start_it = query.begin(); - std::pair e; - for(std::string::const_iterator it = query.begin(); it != query.end(); it++) - { - switch(st) - { - case st_param_name: - if(*it == '=') - { - e.first.assign(start_it, it); - start_it = it;++start_it; - st = st_param_val; - } - break; - case st_param_val: - if(*it == '&') - { - e.second.assign(start_it, it); - start_it = it;++start_it; - params.push_back(e); - e.first.clear();e.second.clear(); - st = st_param_name; - } - break; - default: - LOG_ERROR("Unknown state " << (int)st); - return false; - } - } - if(st == st_param_name) - { - if(start_it != query.end()) - { - e.first.assign(start_it, query.end()); - params.push_back(e); - } - }else - { - if(start_it != query.end()) - e.second.assign(start_it, query.end()); - - if(e.first.size()) - params.push_back(e); - } - return true; - } - - inline - bool parse_uri(const std::string uri, http::uri_content& content) - { - - ///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash= - content.m_query_params.clear(); - STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal); - - boost::smatch result; - if(!(boost::regex_search(uri, result, rexp_match_uri, boost::match_default) && result[0].matched)) - { - LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << uri); - content.m_path = uri; - return true; - } - if(result[1].matched) - { - content.m_path = result[1]; - } - if(result[3].matched) - { - content.m_query = result[3]; - } - if(result[5].matched) - { - content.m_fragment = result[5]; - } - if(content.m_query.size()) - { - parse_uri_query(content.m_query, content.m_query_params); - } - return true; - } - - - inline - bool parse_url(const std::string url_str, http::url_content& content) - { - - ///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash= - //STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal); - STATIC_REGEXP_EXPR_1(rexp_match_uri, "^((.*?)://)?(([^/:]*)(:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal); - // 12 34 5 6 7 - content.port = 0; - boost::smatch result; - if(!(boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched)) - { - LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << rexp_match_uri); - //content.m_path = uri; - return true; - } - if(result[2].matched) - { - content.schema = result[2]; - } - if(result[4].matched) - { - content.host = result[4]; - } - if(result[6].matched) - { - content.port = boost::lexical_cast(result[6]); - } - if(result[7].matched) - { - content.uri = result[7]; - return parse_uri(result[7], content.m_uri_content); - } - - return true; - } - -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/net_utils_base.h b/src/Native/libcryptonote/contrib/epee/include/net/net_utils_base.h deleted file mode 100644 index 7615786be..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/net_utils_base.h +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _NET_UTILS_BASE_H_ -#define _NET_UTILS_BASE_H_ - -#include -#include -#include -#include -#include "serialization/keyvalue_serialization.h" -#include "misc_log_ex.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net" - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - -namespace epee -{ -namespace net_utils -{ - class ipv4_network_address - { - uint32_t m_ip; - uint16_t m_port; - - public: - constexpr ipv4_network_address(uint32_t ip, uint16_t port) noexcept - : m_ip(ip), m_port(port) {} - - bool equal(const ipv4_network_address& other) const noexcept; - bool less(const ipv4_network_address& other) const noexcept; - constexpr bool is_same_host(const ipv4_network_address& other) const noexcept - { return ip() == other.ip(); } - - constexpr uint32_t ip() const noexcept { return m_ip; } - constexpr uint16_t port() const noexcept { return m_port; } - std::string str() const; - std::string host_str() const; - bool is_loopback() const; - bool is_local() const; - static constexpr uint8_t get_type_id() noexcept { return ID; } - - static const uint8_t ID = 1; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_ip) - KV_SERIALIZE(m_port) - END_KV_SERIALIZE_MAP() - }; - - inline bool operator==(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept - { return lhs.equal(rhs); } - inline bool operator!=(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept - { return !lhs.equal(rhs); } - inline bool operator<(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept - { return lhs.less(rhs); } - inline bool operator<=(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept - { return !rhs.less(lhs); } - inline bool operator>(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept - { return rhs.less(lhs); } - inline bool operator>=(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept - { return !lhs.less(rhs); } - - class network_address - { - struct interface - { - virtual ~interface() {}; - - virtual bool equal(const interface&) const = 0; - virtual bool less(const interface&) const = 0; - virtual bool is_same_host(const interface&) const = 0; - - virtual std::string str() const = 0; - virtual std::string host_str() const = 0; - virtual bool is_loopback() const = 0; - virtual bool is_local() const = 0; - virtual uint8_t get_type_id() const = 0; - }; - - template - struct implementation final : interface - { - T value; - - implementation(const T& src) : value(src) {} - ~implementation() = default; - - // Type-checks for cast are done in cpp - static const T& cast(const interface& src) noexcept - { return static_cast&>(src).value; } - - virtual bool equal(const interface& other) const override - { return value.equal(cast(other)); } - - virtual bool less(const interface& other) const override - { return value.less(cast(other)); } - - virtual bool is_same_host(const interface& other) const override - { return value.is_same_host(cast(other)); } - - virtual std::string str() const override { return value.str(); } - virtual std::string host_str() const override { return value.host_str(); } - virtual bool is_loopback() const override { return value.is_loopback(); } - virtual bool is_local() const override { return value.is_local(); } - virtual uint8_t get_type_id() const override { return value.get_type_id(); } - }; - - std::shared_ptr self; - - template - Type& as_mutable() const - { - // types `implmentation` and `implementation` are unique - using Type_ = typename std::remove_const::type; - network_address::interface* const self_ = self.get(); // avoid clang warning in typeid - if (!self_ || typeid(implementation) != typeid(*self_)) - throw std::bad_cast{}; - return static_cast*>(self_)->value; - } - public: - network_address() : self(nullptr) {} - template - network_address(const T& src) - : self(std::make_shared>(src)) {} - bool equal(const network_address &other) const; - bool less(const network_address &other) const; - bool is_same_host(const network_address &other) const; - std::string str() const { return self ? self->str() : ""; } - std::string host_str() const { return self ? self->host_str() : ""; } - bool is_loopback() const { return self ? self->is_loopback() : false; } - bool is_local() const { return self ? self->is_local() : false; } - uint8_t get_type_id() const { return self ? self->get_type_id() : 0; } - template const Type &as() const { return as_mutable(); } - - BEGIN_KV_SERIALIZE_MAP() - uint8_t type = is_store ? this_ref.get_type_id() : 0; - if (!epee::serialization::selector::serialize(type, stg, hparent_section, "type")) - return false; - switch (type) - { - case ipv4_network_address::ID: - { - if (!is_store) - { - const_cast(this_ref) = ipv4_network_address{0, 0}; - auto &addr = this_ref.template as_mutable(); - if (epee::serialization::selector::serialize(addr, stg, hparent_section, "addr")) - MDEBUG("Found as addr: " << this_ref.str()); - else if (epee::serialization::selector::serialize(addr, stg, hparent_section, "template as()")) - MDEBUG("Found as template as(): " << this_ref.str()); - else if (epee::serialization::selector::serialize(addr, stg, hparent_section, "template as_mutable()")) - MDEBUG("Found as template as_mutable(): " << this_ref.str()); - else - { - MWARNING("Address not found"); - return false; - } - } - else - { - auto &addr = this_ref.template as_mutable(); - if (!epee::serialization::selector::serialize(addr, stg, hparent_section, "addr")) - return false; - } - break; - } - default: MERROR("Unsupported network address type: " << (unsigned)type); return false; - } - END_KV_SERIALIZE_MAP() - }; - - inline bool operator==(const network_address& lhs, const network_address& rhs) - { return lhs.equal(rhs); } - inline bool operator!=(const network_address& lhs, const network_address& rhs) - { return !lhs.equal(rhs); } - inline bool operator<(const network_address& lhs, const network_address& rhs) - { return lhs.less(rhs); } - inline bool operator<=(const network_address& lhs, const network_address& rhs) - { return !rhs.less(lhs); } - inline bool operator>(const network_address& lhs, const network_address& rhs) - { return rhs.less(lhs); } - inline bool operator>=(const network_address& lhs, const network_address& rhs) - { return !lhs.less(rhs); } - - bool create_network_address(network_address &address, const std::string &string, uint16_t default_port = 0); - - /************************************************************************/ - /* */ - /************************************************************************/ - struct connection_context_base - { - const boost::uuids::uuid m_connection_id; - const network_address m_remote_address; - const bool m_is_income; - const time_t m_started; - time_t m_last_recv; - time_t m_last_send; - uint64_t m_recv_cnt; - uint64_t m_send_cnt; - double m_current_speed_down; - double m_current_speed_up; - - connection_context_base(boost::uuids::uuid connection_id, - const network_address &remote_address, bool is_income, - time_t last_recv = 0, time_t last_send = 0, - uint64_t recv_cnt = 0, uint64_t send_cnt = 0): - m_connection_id(connection_id), - m_remote_address(remote_address), - m_is_income(is_income), - m_started(time(NULL)), - m_last_recv(last_recv), - m_last_send(last_send), - m_recv_cnt(recv_cnt), - m_send_cnt(send_cnt), - m_current_speed_down(0), - m_current_speed_up(0) - {} - - connection_context_base(): m_connection_id(), - m_remote_address(ipv4_network_address{0,0}), - m_is_income(false), - m_started(time(NULL)), - m_last_recv(0), - m_last_send(0), - m_recv_cnt(0), - m_send_cnt(0), - m_current_speed_down(0), - m_current_speed_up(0) - {} - - connection_context_base& operator=(const connection_context_base& a) - { - set_details(a.m_connection_id, a.m_remote_address, a.m_is_income); - return *this; - } - - private: - template - friend class connection; - void set_details(boost::uuids::uuid connection_id, const network_address &remote_address, bool is_income) - { - this->~connection_context_base(); - new(this) connection_context_base(connection_id, remote_address, is_income); - } - - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct i_service_endpoint - { - virtual bool do_send(const void* ptr, size_t cb)=0; - virtual bool close()=0; - virtual bool call_run_once_service_io()=0; - virtual bool request_callback()=0; - virtual boost::asio::io_service& get_io_service()=0; - //protect from deletion connection object(with protocol instance) during external call "invoke" - virtual bool add_ref()=0; - virtual bool release()=0; - protected: - virtual ~i_service_endpoint() noexcept(false) {} - }; - - - //some helpers - - - std::string print_connection_context(const connection_context_base& ctx); - std::string print_connection_context_short(const connection_context_base& ctx); - -inline MAKE_LOGGABLE(connection_context_base, ct, os) -{ - os << "[" << epee::net_utils::print_connection_context_short(ct) << "] "; - return os; -} - -#define LOG_ERROR_CC(ct, message) MERROR(ct << message) -#define LOG_WARNING_CC(ct, message) MWARNING(ct << message) -#define LOG_INFO_CC(ct, message) MINFO(ct << message) -#define LOG_DEBUG_CC(ct, message) MDEBUG(ct << message) -#define LOG_TRACE_CC(ct, message) MTRACE(ct << message) -#define LOG_CC(level, ct, message) MLOG(level, ct << message) - -#define LOG_PRINT_CC_L0(ct, message) LOG_PRINT_L0(ct << message) -#define LOG_PRINT_CC_L1(ct, message) LOG_PRINT_L1(ct << message) -#define LOG_PRINT_CC_L2(ct, message) LOG_PRINT_L2(ct << message) -#define LOG_PRINT_CC_L3(ct, message) LOG_PRINT_L3(ct << message) -#define LOG_PRINT_CC_L4(ct, message) LOG_PRINT_L4(ct << message) - -#define LOG_PRINT_CCONTEXT_L0(message) LOG_PRINT_CC_L0(context, message) -#define LOG_PRINT_CCONTEXT_L1(message) LOG_PRINT_CC_L1(context, message) -#define LOG_PRINT_CCONTEXT_L2(message) LOG_PRINT_CC_L2(context, message) -#define LOG_PRINT_CCONTEXT_L3(message) LOG_PRINT_CC_L3(context, message) -#define LOG_ERROR_CCONTEXT(message) LOG_ERROR_CC(context, message) - -#define CHECK_AND_ASSERT_MES_CC(condition, return_val, err_message) CHECK_AND_ASSERT_MES(condition, return_val, "[" << epee::net_utils::print_connection_context_short(context) << "]" << err_message) - -} -} - -#endif //_NET_UTILS_BASE_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/network_throttle-detail.hpp b/src/Native/libcryptonote/contrib/epee/include/net/network_throttle-detail.hpp deleted file mode 100644 index 955668d62..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/network_throttle-detail.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/// @file -/// @author rfree (current maintainer in monero.cc project) -/// @brief implementaion for throttling of connection (count and rate-limit speed etc) - -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* rfree: throttle details, implementing rate limiting */ - - -#ifndef INCLUDED_throttle_detail_hpp -#define INCLUDED_throttle_detail_hpp - -#include "network_throttle.hpp" - -namespace epee -{ -namespace net_utils -{ - - -class network_throttle : public i_network_throttle { - private: - struct packet_info { - size_t m_size; // octets sent. Summary for given small-window (e.g. for all packaged in 1 second) - packet_info(); - }; - - - network_speed_bps m_target_speed; - size_t m_network_add_cost; // estimated add cost of headers - size_t m_network_minimal_segment; // estimated minimal cost of sending 1 byte to round up to - size_t m_network_max_segment; // recommended max size of 1 TCP transmission - - const size_t m_window_size; // the number of samples to average over - network_time_seconds m_slot_size; // the size of one slot. TODO: now hardcoded for 1 second e.g. in time_to_slot() - // TODO for big window size, for performance better the substract on change of m_last_sample_time instead of recalculating average of eg >100 elements - - std::vector< packet_info > m_history; // the history of bw usage - network_time_seconds m_last_sample_time; // time of last history[0] - so we know when to rotate the buffer - network_time_seconds m_start_time; // when we were created - bool m_any_packet_yet; // did we yet got any packet to count - - std::string m_name; // my name for debug and logs - std::string m_nameshort; // my name for debug and logs (used in log file name) - - // each sample is now 1 second - public: - network_throttle(const std::string &nameshort, const std::string &name, int window_size=-1); - virtual ~network_throttle(); - virtual void set_name(const std::string &name); - virtual void set_target_speed( network_speed_kbps target ); - virtual network_speed_kbps get_target_speed(); - - // add information about events: - virtual void handle_trafic_exact(size_t packet_size); ///< count the new traffic/packet; the size is exact considering all network costs - virtual void handle_trafic_tcp(size_t packet_size); ///< count the new traffic/packet; the size is as TCP, we will consider MTU etc - - virtual void tick(); ///< poke and update timers/history (recalculates, moves the history if needed, checks the real clock etc) - - virtual double get_time_seconds() const ; ///< timer that we use, time in seconds, monotionic - - // time calculations: - virtual void calculate_times(size_t packet_size, calculate_times_struct &cts, bool dbg, double force_window) const; ///< MAIN LOGIC (see base class for info) - - virtual network_time_seconds get_sleep_time_after_tick(size_t packet_size); ///< increase the timer if needed, and get the package size - virtual network_time_seconds get_sleep_time(size_t packet_size) const; ///< gets the Delay (recommended Delay time) from calc. (not safe: only if time didnt change?) TODO - - virtual size_t get_recommended_size_of_planned_transport() const; ///< what should be the size (bytes) of next data block to be transported - virtual size_t get_recommended_size_of_planned_transport_window(double force_window) const; ///< ditto, but for given windows time frame - virtual double get_current_speed() const; - - private: - virtual network_time_seconds time_to_slot(network_time_seconds t) const { return std::floor( t ); } // convert exact time eg 13.7 to rounded time for slot number in history 13 - virtual void _handle_trafic_exact(size_t packet_size, size_t orginal_size); - virtual void logger_handle_net(const std::string &filename, double time, size_t size); -}; - -/*** - * The complete set of traffic throttle for one typical connection -*/ -struct network_throttle_bw { - public: - network_throttle m_in; ///< for incomming traffic (this we can not controll directly as it depends of what others send to us - usually) - network_throttle m_inreq; ///< for requesting incomming traffic (this is exact usually) - network_throttle m_out; ///< for outgoing traffic that we just sent (this is exact usually) - - public: - network_throttle_bw(const std::string &name1); -}; - - - -} // namespace net_utils -} // namespace epee - - -#endif - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/network_throttle.hpp b/src/Native/libcryptonote/contrib/epee/include/net/network_throttle.hpp deleted file mode 100644 index 7df79a908..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/network_throttle.hpp +++ /dev/null @@ -1,171 +0,0 @@ -/// @file -/// @author rfree (current maintainer in monero.cc project) -/// @brief interface for throttling of connection (count and rate-limit speed etc) - -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* rfree: throttle basic interface */ -/* rfree: also includes the manager for singeton/global such objects */ - - -#ifndef INCLUDED_network_throttle_hpp -#define INCLUDED_network_throttle_hpp - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "syncobj.h" - -#include "net/net_utils_base.h" -#include "misc_log_ex.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "misc_language.h" -#include "pragma_comp_defs.h" -#include -#include -#include - -#include -#include -#include - -namespace epee -{ -namespace net_utils -{ - -// just typedefs to in code define the units used. TODO later it will be enforced that casts to other numericals are only explicit to avoid mistakes? use boost::chrono? -typedef double network_speed_kbps; // externally, for parameters and return values, all defined in kilobytes per second -typedef double network_speed_bps; // throttle-internally, bytes per second -typedef double network_time_seconds; -typedef double network_MB; - -class i_network_throttle; - -/*** -@brief All information about given throttle - speed calculations -*/ -struct calculate_times_struct { - double average; - double window; - double delay; - double recomendetDataSize; -}; -typedef calculate_times_struct calculate_times_struct; - - -/*** -@brief Access to simple throttles, with singlton to access global network limits -*/ -class network_throttle_manager { - // provides global (singleton) in/inreq/out throttle access - - // [[note1]] see also http://www.nuonsoft.com/blog/2012/10/21/implementing-a-thread-safe-singleton-with-c11/ - // [[note2]] _inreq is the requested in traffic - we anticipate we will get in-bound traffic soon as result of what we do (e.g. that we sent network downloads requests) - - //protected: - public: // XXX - - static boost::mutex m_lock_get_global_throttle_in; - static boost::mutex m_lock_get_global_throttle_inreq; - static boost::mutex m_lock_get_global_throttle_out; - - friend class connection_basic; // FRIEND - to directly access global throttle-s. !! REMEMBER TO USE LOCKS! - friend class connection_basic_pimpl; // ditto - - public: - static i_network_throttle & get_global_throttle_in(); ///< singleton ; for friend class ; caller MUST use proper locks! like m_lock_get_global_throttle_in - static i_network_throttle & get_global_throttle_inreq(); ///< ditto ; use lock ... use m_lock_get_global_throttle_inreq obviously - static i_network_throttle & get_global_throttle_out(); ///< ditto ; use lock ... use m_lock_get_global_throttle_out obviously -}; - - - -/*** -@brief interface for the throttle, see the derivated class -*/ -class i_network_throttle { - public: - virtual void set_name(const std::string &name)=0; - virtual void set_target_speed( network_speed_kbps target )=0; - virtual network_speed_kbps get_target_speed()=0; - - virtual void handle_trafic_exact(size_t packet_size) =0; // count the new traffic/packet; the size is exact considering all network costs - virtual void handle_trafic_tcp(size_t packet_size) =0; // count the new traffic/packet; the size is as TCP, we will consider MTU etc - virtual void tick() =0; // poke and update timers/history - - // time calculations: - - virtual void calculate_times(size_t packet_size, calculate_times_struct &cts, bool dbg, double force_window) const =0; // assuming sending new package (or 0), calculate: - // Average, Window, Delay, Recommended data size ; also gets dbg=debug flag, and forced widnow size if >0 or -1 for not forcing window size - - // Average speed, Window size, recommended Delay to sleep now, Recommended size of data to send now - - virtual network_time_seconds get_sleep_time(size_t packet_size) const =0; // gets the D (recommended Delay time) from calc - virtual network_time_seconds get_sleep_time_after_tick(size_t packet_size) =0; // ditto, but first tick the timer - - virtual size_t get_recommended_size_of_planned_transport() const =0; // what should be the recommended limit of data size that we can transport over current network_throttle in near future - - virtual double get_time_seconds() const =0; // a timer - virtual void logger_handle_net(const std::string &filename, double time, size_t size)=0; - - -}; - - -// ... more in the -advanced.h file - - -} // namespace net_utils -} // namespace epee - - -#endif - - - diff --git a/src/Native/libcryptonote/contrib/epee/include/net/protocol_switcher.h b/src/Native/libcryptonote/contrib/epee/include/net/protocol_switcher.h deleted file mode 100644 index 3b153d19c..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/protocol_switcher.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _PROTOCOL_SWITCHER_H_ -#define _PROTOCOL_SWITCHER_H_ - -#include "levin_base.h" -#include "http_server.h" -#include "levin_protocol_handler.h" -//#include "abstract_tcp_server.h" - -namespace epee -{ -namespace net_utils -{ - struct protocl_switcher_config - { - http::http_custom_handler::config_type m_http_config; - levin::protocol_handler::config_type m_levin_config; - }; - - - struct i_protocol_handler - { - virtual bool handle_recv(const void* ptr, size_t cb)=0; - }; - - template - class t_protocol_handler: public i_protocol_handler - { - public: - typedef t t_type; - t_protocol_handler(i_service_endpoint* psnd_hndlr, typename t_type::config_type& config, const connection_context& conn_context):m_hadler(psnd_hndlr, config, conn_context) - {} - private: - bool handle_recv(const void* ptr, size_t cb) - { - return m_hadler.handle_recv(ptr, cb); - } - t_type m_hadler; - }; - - - class protocol_switcher - { - public: - typedef protocl_switcher_config config_type; - - protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context); - virtual ~protocol_switcher(){} - - virtual bool handle_recv(const void* ptr, size_t cb); - - bool after_init_connection(){return true;} - private: - t_protocol_handler m_http_handler; - t_protocol_handler m_levin_handler; - i_protocol_handler* pcurrent_handler; - - std::string m_cached_buff; - }; - - protocol_switcher::protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context):m_http_handler(psnd_hndlr, config.m_http_config, conn_context), m_levin_handler(psnd_hndlr, config.m_levin_config, conn_context), pcurrent_handler(NULL) - {} - - bool protocol_switcher::handle_recv(const void* ptr, size_t cb) - { - if(pcurrent_handler) - return pcurrent_handler->handle_recv(ptr, cb); - else - { - m_cached_buff.append((const char*)ptr, cb); - if(m_cached_buff.size() < sizeof(uint64_t)) - return true; - - if(*((uint64_t*)&m_cached_buff[0]) == LEVIN_SIGNATURE) - { - pcurrent_handler = &m_levin_handler; - return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size()); - } - if(m_cached_buff.substr(0, 4) == "GET " || m_cached_buff.substr(0, 4) == "POST") - { - pcurrent_handler = &m_http_handler; - return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size()); - }else - { - LOG_ERROR("Wrong protocol accepted on port..."); - return false; - } - } - - return true; - } -} -} -#endif //_PROTOCOL_SWITCHER_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/net/rpc_method_name.h b/src/Native/libcryptonote/contrib/epee/include/net/rpc_method_name.h deleted file mode 100644 index 1c327bc31..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/rpc_method_name.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - - -#define RPC_METHOD_NAME(name) static inline const char* methodname(){return name;} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/smtp.h b/src/Native/libcryptonote/contrib/epee/include/net/smtp.h deleted file mode 100644 index 5f2b842d5..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/smtp.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - using boost::asio::ip::tcp; - using namespace boost::archive::iterators; - typedef base64_from_binary > base64_text; - - /************************************************************************/ - /* */ - /************************************************************************/ - class smtp_client - { - public: - smtp_client(std::string pServer,unsigned int pPort,std::string pUser,std::string pPassword): - mServer(pServer),mPort(pPort),mUserName(pUser),mPassword(pPassword),mSocket(mIOService),mResolver(mIOService) - { - tcp::resolver::query qry(mServer,boost::lexical_cast( mPort )); - mResolver.async_resolve(qry,boost::bind(&smtp_client::handleResolve,this,boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); - } - bool Send(std::string pFrom,std::string pTo,std::string pSubject,std::string pMessage) - { - mHasError = true; - mFrom=pFrom; - mTo=pTo; - mSubject=pSubject; - mMessage=pMessage; - mIOService.run(); - return !mHasError; - } - private: - std::string encodeBase64(std::string pData) - { - std::stringstream os; - size_t sz=pData.size(); - std::copy(base64_text(pData.c_str()),base64_text(pData.c_str()+sz),std::ostream_iterator(os)); - return os.str(); - } - void handleResolve(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) - { - if(!err) - { - tcp::endpoint endpoint=*endpoint_iterator; - mSocket.async_connect(endpoint, - boost::bind(&smtp_client::handleConnect,this,boost::asio::placeholders::error,++endpoint_iterator)); - } - else - { - mHasError=true; - mErrorMsg= err.message(); - } - } - void writeLine(std::string pData) - { - std::ostream req_strm(&mRequest); - req_strm << pData << "\r\n"; - boost::asio::write(mSocket,mRequest); - req_strm.clear(); - } - void readLine(std::string& pData) - { - boost::asio::streambuf response; - boost::asio::read_until(mSocket, response, "\r\n"); - std::istream response_stream(&response); - response_stream >> pData; - } - void handleConnect(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) - { - if (!err) - { - std::string read_buff; - // The connection was successful. Send the request. - std::ostream req_strm(&mRequest); - writeLine("EHLO "+mServer); - readLine(read_buff);//220 - writeLine("AUTH LOGIN"); - readLine(read_buff);// - writeLine(encodeBase64(mUserName)); - readLine(read_buff); - writeLine(encodeBase64(mPassword)); - readLine(read_buff); - writeLine( "MAIL FROM:<"+mFrom+">"); - writeLine( "RCPT TO:<"+mTo+">"); - writeLine( "DATA"); - writeLine( "SUBJECT:"+mSubject); - writeLine( "From:"+mFrom); - writeLine( "To:"+mTo); - writeLine( ""); - writeLine( mMessage ); - writeLine( "\r\n.\r\n"); - readLine(read_buff); - if(read_buff == "250") - mHasError = false; - writeLine( "QUIT"); - } - else - { - mHasError=true; - mErrorMsg= err.message(); - } - } - std::string mServer; - std::string mUserName; - std::string mPassword; - std::string mFrom; - std::string mTo; - std::string mSubject; - std::string mMessage; - unsigned int mPort; - boost::asio::io_service mIOService; - tcp::resolver mResolver; - tcp::socket mSocket; - boost::asio::streambuf mRequest; - boost::asio::streambuf mResponse; - bool mHasError; - std::string mErrorMsg; - }; - - - bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_email, /*"STIL CRAWLER",*/ - const std::string& maillist, const std::string& subject, const std::string& body) - { - STD_TRY_BEGIN(); - //smtp_client mailc("yoursmtpserver.com",25,"user@yourdomain.com","password"); - //mailc.Send("from@yourdomain.com","to@somewhere.com","subject","Hello from C++ SMTP Client!"); - smtp_client mailc(server,port,login,pass); - return mailc.Send(from_email,maillist,subject,body); - STD_TRY_CATCH("at send_mail", false); - } - - } -} -} - -//#include "smtp.inl" diff --git a/src/Native/libcryptonote/contrib/epee/include/net/smtp.inl b/src/Native/libcryptonote/contrib/epee/include/net/smtp.inl deleted file mode 100644 index c16372c88..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/smtp.inl +++ /dev/null @@ -1,1569 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "md5.h" - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - - ////////////////////////////////////////////////////////////////////////// - inline char * convert_hex( unsigned char *in, int len ) - { - static char hex[] = "0123456789abcdef"; - char * out; - int i; - - out = (char *) malloc(len * 2 + 1); - if (out == NULL) - return NULL; - - for (i = 0; i < len; i++) { - out[i * 2] = hex[in[i] >> 4]; - out[i * 2 + 1] = hex[in[i] & 15]; - } - - out[i*2] = 0; - - return out; - } - - ////////////////////////////////////////////////////////////////////////// - inline char * hash_md5(const char * sec_key, const char * data, int len) - { - char key[65], digest[24]; - char * hash_hex; - - int sec_len, i; - - sec_len = strlen(sec_key); - - if (sec_len < 64) { - memcpy(key, sec_key, sec_len); - for (i = sec_len; i < 64; i++) { - key[i] = 0; - } - } else { - memcpy(key, sec_key, 64); - } - - md5::hmac_md5( (const unsigned char*)data, len, (const unsigned char*)key, 64, (unsigned char*)digest ); - hash_hex = convert_hex( (unsigned char*)digest, 16 ); - - return hash_hex; - } - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - inline CSMTPClient::CSMTPClient(void) - { - m_dwSupportedAuthModesCount = 0; - m_bConnected = FALSE; - m_hSocket = INVALID_SOCKET; - m_pErrorText = NULL; - - // Initialize WinSock - WORD wVer = MAKEWORD( 2, 2 ); - if ( WSAStartup( wVer, &m_wsaData ) != NO_ERROR ) - { - SetErrorText( "WSAStartup.", WSAGetLastError() ); - throw; - } - if ( LOBYTE( m_wsaData.wVersion ) != 2 || HIBYTE( m_wsaData.wVersion ) != 2 ) - { - SetErrorText( "Can't find a useable WinSock DLL." ); - WSACleanup(); - throw; - } - } - - ////////////////////////////////////////////////////////////////////////// - inline CSMTPClient::~CSMTPClient(void) - { - if ( m_pErrorText ) - { - free( m_pErrorText ); - m_pErrorText = NULL; - } - - if ( m_bConnected ) - ServerDisconnect(); - - // Cleanup - WSACleanup(); - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::SetErrorText( LPCSTR szErrorText, DWORD dwErrorCode ) - { - if ( m_pErrorText ) - { - free( m_pErrorText ); - m_pErrorText = NULL; - } - - LPVOID lpMsgBuf = NULL; - if ( dwErrorCode ) - { - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dwErrorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR) &lpMsgBuf, - 0, NULL ); - } - - if ( szErrorText && strlen( szErrorText ) ) - { - m_pErrorText = (LPBYTE)malloc( strlen( szErrorText ) + 1 ); - strcpy( (char*)m_pErrorText, szErrorText ); - - if ( lpMsgBuf ) - { - strcat( (char*)m_pErrorText, " " ); - strcpy( (char*)m_pErrorText, (char*)lpMsgBuf ); - - LocalFree( lpMsgBuf ); - } - } - } - - inline void CSMTPClient::SetErrorText( PBYTE szErrorText, DWORD dwErrorCode ) - { - SetErrorText( (LPCSTR)szErrorText, dwErrorCode ); - } - - ////////////////////////////////////////////////////////////////////////// - inline char* CSMTPClient::GetLastErrorText() - { - return (char*)m_pErrorText; - } - - ////////////////////////////////////////////////////////////////////////// - inline DWORD CSMTPClient::ReceiveData( SOCKET hSocket, PBYTE pReceiveBuffer, DWORD dwReceiveBufferSize ) - { - DWORD dwReceivedDataSize = 0; - - if ( hSocket != INVALID_SOCKET && pReceiveBuffer && dwReceiveBufferSize ) - { - int iReceived = 0; - int iLength = 0; - - iLength = recv( hSocket, (LPSTR)pReceiveBuffer + iReceived, dwReceiveBufferSize - iReceived, - NO_FLAGS ); - - if ( iLength != 0 && iLength != SOCKET_ERROR ) - iReceived += iLength; - - dwReceivedDataSize = iReceived; - - pReceiveBuffer[ iReceived ] = 0; - } - - return dwReceivedDataSize; - } - - inline ////////////////////////////////////////////////////////////////////////// - DWORD CSMTPClient::SendData( SOCKET hSocket, PBYTE pSendBuffer, DWORD dwSendBufferSize ) - { - DWORD dwSended = 0; - - if ( hSocket != INVALID_SOCKET && pSendBuffer && dwSendBufferSize ) - { - int iSended = 0; - int iLength = 0; - - while ( iLength != SOCKET_ERROR && dwSendBufferSize - iSended > 0 ) - { - iLength = send( hSocket, (LPSTR)pSendBuffer + iSended, dwSendBufferSize - iSended, - NO_FLAGS ); - - if ( iLength != 0 && iLength != SOCKET_ERROR ) - iSended += iLength; - } - - dwSended = iSended; - } - - //if ( dwSended ) - // printf( "C: %s", pSendBuffer ); - - return dwSended; - } - - ////////////////////////////////////////////////////////////////////////// - inline unsigned short CSMTPClient::GetResponseCode( LPBYTE pBuffer, DWORD dwBufferSize ) - { - unsigned short iCode = 0; - - if ( dwBufferSize >= 3 ) - { - CHAR szResponseCode[ 4 ] = { 0 }; - memcpy( szResponseCode, pBuffer, 3 ); - szResponseCode[ 3 ] = 0; - iCode = atoi( szResponseCode ); - } - - return iCode; - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::ParseESMTPExtensions( LPBYTE pBuffer, DWORD dwBufferSize ) - { - const char *szSubstring = strstr( (const char*)pBuffer, "250-AUTH " ); - if ( !szSubstring ) - { - szSubstring = strstr( (const char*)pBuffer, "250 AUTH " ); - } - - if ( szSubstring ) - { - const char *szSubstringEnd = strstr( (const char*)szSubstring, "\r\n" ); - if ( szSubstringEnd ) - { - szSubstring += 9; - char szAuthMode[ 256 ] = { 0 }; - for ( ; szSubstring < szSubstringEnd + 1 ; szSubstring++ ) - { - if ( *szSubstring == ' ' || *szSubstring == '\r' ) - { - if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_PLAIN ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_PLAIN; - m_dwSupportedAuthModesCount++; - } - else if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_LOGIN ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_LOGIN; - m_dwSupportedAuthModesCount++; - } - else if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_CRAM_MD5 ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_CRAM_MD5; - m_dwSupportedAuthModesCount++; - } - - szAuthMode[ 0 ] = 0; - - if ( m_dwSupportedAuthModesCount == MAX_AUTH_MODES_COUND ) - break; - } - else - { - szAuthMode[ strlen( szAuthMode ) + 1 ] = 0; - szAuthMode[ strlen( szAuthMode ) ] = *szSubstring; - } - } - } - } - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerConnect( LPCSTR szServerAddress, const unsigned short iPortNumber ) - { - if ( m_bConnected ) - ServerDisconnect(); - - m_bConnected = FALSE; - m_hSocket = INVALID_SOCKET; - - m_hSocket = _connectServerSocket( szServerAddress, iPortNumber ); - - if ( m_hSocket != INVALID_SOCKET ) - { - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - // Check 220 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 220 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error. ", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - // EHLO / HELO - BYTE szHelloBuffer[ 256 ]; - sprintf( (char*)szHelloBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_EHLO, (char*)szServerAddress ); - if ( SendData( m_hSocket, (PBYTE)szHelloBuffer, strlen( (const char*)szHelloBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 500 ) - { - SetErrorText( pReceiveBuffer ); - - sprintf( (char*)szHelloBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_HELO, (char*)szServerAddress ); - if ( SendData( m_hSocket, (PBYTE)szHelloBuffer, strlen( (const char*)szHelloBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 250 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - } - else if ( iResponseCode != 250 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - // Parse AUTH supported modes - ParseESMTPExtensions( pReceiveBuffer, iReceived ); - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - free( pReceiveBuffer ); - } - } - else - { - return FALSE; - } - - m_bConnected = TRUE; - - return TRUE; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerConnect( LPCSTR szServerAddress, const unsigned short iPortNumber, LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - bSuccess = ServerConnect( szServerAddress, iPortNumber ); - if ( bSuccess ) - { - if ( GetAuthModeIsSupported( AUTH_MODE_CRAM_MD5 ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_CRAM_MD5 ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_PLAIN ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_PLAIN ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_LOGIN ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_LOGIN ); - } - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline SOCKET CSMTPClient::_connectServerSocket( LPCSTR szServerAddress, const unsigned short iPortNumber ) - { - int nConnect; - short nProtocolPort = iPortNumber; - LPHOSTENT lpHostEnt; - SOCKADDR_IN sockAddr; - - SOCKET hServerSocket = INVALID_SOCKET; - - lpHostEnt = gethostbyname( szServerAddress ); - if (lpHostEnt) - { - hServerSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if (hServerSocket != INVALID_SOCKET) - { - sockAddr.sin_family = AF_INET; - sockAddr.sin_port = htons( nProtocolPort ); - sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list); - - nConnect = connect( hServerSocket, (PSOCKADDR)&sockAddr, - sizeof(sockAddr) ); - - if ( nConnect != 0 ) - { - SetErrorText( "connect error.", WSAGetLastError() ); - hServerSocket = INVALID_SOCKET; - } - } - else - { - SetErrorText( "Invalid socket." ); - throw; - } - } - else - { - SetErrorText( "Error retrieving host by name.", WSAGetLastError() ); - } - - return hServerSocket ; - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::ServerDisconnect() - { - if ( m_hSocket != INVALID_SOCKET ) - { - if ( SendData( m_hSocket, (PBYTE)SMTP_COMMAND_QUIT, strlen( SMTP_COMMAND_QUIT ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - - if ( iReceived ) - SetErrorText( pReceiveBuffer ); - - free( pReceiveBuffer ); - } - - m_hSocket = INVALID_SOCKET; - } - - m_bConnected = FALSE; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::GetAuthModeIsSupported( int iMode ) - { - BOOL bSupported = FALSE; - - for ( int i = 0 ; i < m_dwSupportedAuthModesCount ; i++ ) - { - if ( m_aSupportedAuthModes[ i ] == iMode ) - { - bSupported = TRUE; - break; - } - } - - return bSupported; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLogin( LPCSTR szUsername, LPCSTR szPassword, int iAuthMode ) - { - BOOL bSuccess = FALSE; - - if ( iAuthMode == AUTH_MODE_PLAIN ) - { - bSuccess = ServerLoginMethodPlain( szUsername, szPassword ); - } - else if ( iAuthMode == AUTH_MODE_LOGIN ) - { - bSuccess = ServerLoginMethodLogin( szUsername, szPassword ); - } - else if ( iAuthMode == AUTH_MODE_CRAM_MD5 ) - { - bSuccess = ServerLoginMethodCramMD5( szUsername, szPassword ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLogin( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - if ( GetAuthModeIsSupported( AUTH_MODE_CRAM_MD5 ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_CRAM_MD5 ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_PLAIN ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_PLAIN ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_LOGIN ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_LOGIN ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodPlain( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_PLAIN ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - // Encode. - DWORD dwLoginBuffer = strlen( szUsername ) + strlen( szPassword ) + 3; - char *pLoginBuffer = (char*)malloc( dwLoginBuffer ); - if ( pLoginBuffer ) - { - ZeroMemory( pLoginBuffer, dwLoginBuffer ); - strcpy( pLoginBuffer + 1, szUsername ); - strcpy( pLoginBuffer + 1 + strlen( szUsername ) + 1, szPassword ); - - Base64Coder coder; - coder.Encode( (const PBYTE)pLoginBuffer, dwLoginBuffer - 1 ); - LPCSTR szLoginBufferEncoded = coder.EncodedMessage(); - - if ( szLoginBufferEncoded && strlen( szLoginBufferEncoded ) > 0 ) - { - DWORD dwSendBufferSize = strlen( szLoginBufferEncoded ) + 4; - char* pSendBuffer = (char*)malloc( dwSendBufferSize ); - if ( pSendBuffer ) - { - strcpy( pSendBuffer, szLoginBufferEncoded ); - strcat( pSendBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)pSendBuffer, strlen( (const char*)pSendBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pSendBuffer ); - free( pLoginBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pSendBuffer ); - } - } - - free( pLoginBuffer ); - - // check result - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - } - - free( pReceiveBuffer ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodLogin( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_LOGIN ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - Base64Coder coder; - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szRequest = coder.DecodedMessage(); - if ( szRequest && strlen( szRequest ) > 0 ) - { - if ( strcmpi( szRequest, "Username:" ) == 0 ) - { - coder.Encode( (const PBYTE)szUsername, strlen( szUsername ) ); - LPCSTR szUsernameEncoded = coder.EncodedMessage(); - - char* szLoginUsernameBuffer = (char*)malloc( strlen( szUsernameEncoded ) + 4 ); - if ( szLoginUsernameBuffer ) - { - strcpy( szLoginUsernameBuffer, szUsernameEncoded ); - strcat( szLoginUsernameBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)szLoginUsernameBuffer, strlen( (const char*)szLoginUsernameBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szLoginUsernameBuffer ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szRequest2 = coder.DecodedMessage(); - if ( szRequest2 && strlen( szRequest2 ) > 0 ) - { - if ( strcmpi( szRequest2, "Password:" ) == 0 ) - { - coder.Encode( (const PBYTE)szPassword, strlen( szPassword ) ); - LPCSTR szPasswordEncoded = coder.EncodedMessage(); - - char* szLoginPasswordBuffer = (char*)malloc( strlen( szPasswordEncoded ) + 4 ); - if ( szLoginPasswordBuffer ) - { - strcpy( szLoginPasswordBuffer, szPasswordEncoded ); - strcat( szLoginPasswordBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)szLoginPasswordBuffer, strlen( (const char*)szLoginPasswordBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szLoginPasswordBuffer ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - } - } - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pReceiveBuffer ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodCramMD5( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_CRAM_MD5 ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - Base64Coder coder; - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szResponse = coder.DecodedMessage(); - if ( szResponse && strlen( szResponse ) > 0 ) - { - char *auth_hex = hash_md5( szPassword, szResponse, strlen(szResponse) ); - if ( !auth_hex ) - { - free( pReceiveBuffer ); - return FALSE; - } - - char *szCommand = (char*)malloc( strlen( szUsername ) + strlen( auth_hex ) + 5 ); - if ( szCommand ) - { - sprintf( szCommand, "%s %s", szUsername, auth_hex ); - - free( auth_hex ); - - coder.Encode( (const PBYTE)szCommand, strlen( szCommand ) ); - - free( szCommand ); - - LPCSTR szAuthEncoded = coder.EncodedMessage(); - if ( szAuthEncoded == NULL ) - { - free( pReceiveBuffer ); - return FALSE; - } - - char *szAuthCommand = (char*)malloc( strlen( szAuthEncoded ) + 4 ); - if ( szAuthCommand ) - { - strcpy( szAuthCommand, szAuthEncoded ); - strcat( szAuthCommand, "\r\n" ); - - // Send auth data - if ( SendData( m_hSocket, (PBYTE)szAuthCommand, strlen( (const char*)szAuthCommand ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szAuthCommand ); - free( pReceiveBuffer ); - return FALSE; - } - - // Check response - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szAuthCommand ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( auth_hex ); - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pReceiveBuffer ); - } - else - { - SetErrorText( "malloc() failed.", GetLastError() ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::SendMessage( LPCSTR szFromAddress, LPCSTR szFromName, LPCSTR szToAddresses, LPCSTR szSubject, LPCSTR szXMailer, LPBYTE pBodyBuffer, DWORD dwBodySize ) - { - BOOL bSuccess = FALSE; - - // Format Header - if ( !szFromAddress ) - { - SetErrorText( "SendMessage. Invalid Parameters!" ); - return NULL; - } - - char *szHeaderBuffer = (char*)malloc( 1024 * 16 ); - if ( szHeaderBuffer ) - { - // get the current date and time - char szDate[ 500 ]; - char sztTime[ 500 ]; - - SYSTEMTIME st = { 0 }; - ::GetSystemTime(&st); - - ::GetDateFormatA( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), 0, &st, "ddd',' dd MMM yyyy", szDate , sizeof( szDate ) ); - ::GetTimeFormatA( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), TIME_FORCE24HOURFORMAT, &st, "HH':'mm':'ss", sztTime, sizeof( sztTime ) ); - - sprintf( szHeaderBuffer, "DATE: %s %s\r\n", szDate, sztTime ); - - // X-Mailer Field - if ( szXMailer && strlen( szXMailer ) ) - { - strcat( szHeaderBuffer, "X-Mailer: " ); - strcat( szHeaderBuffer, szXMailer ); - strcat( szHeaderBuffer, "\r\n" ); - } - - // From: - strcat( szHeaderBuffer, "From: " ); - if ( szFromName ) - { - strcat( szHeaderBuffer, "\"" ); - strcat( szHeaderBuffer, szFromName ); - strcat( szHeaderBuffer, "\" <" ); - strcat( szHeaderBuffer, szFromAddress ); - strcat( szHeaderBuffer, ">\r\n" ); - } - else - { - strcat( szHeaderBuffer, "<" ); - strcat( szHeaderBuffer, szFromAddress ); - strcat( szHeaderBuffer, ">\r\n" ); - } - - // Subject: - if ( szSubject && strlen( szSubject ) ) - { - strcat( szHeaderBuffer, "Subject: " ); - strcat( szHeaderBuffer, szSubject ); - strcat( szHeaderBuffer, "\r\n" ); - } - - // To Fields - strcat( szHeaderBuffer, "To: " ); - strcat( szHeaderBuffer, szToAddresses ); - strcat( szHeaderBuffer, "\r\n" ); - - // MIME - strcat( szHeaderBuffer, "MIME-Version: 1.0\r\nContent-type: text/plain; charset=US-ASCII\r\n" ); - - // End Header - strcat( szHeaderBuffer, "\r\n" ); - } - else - { - SetErrorText( "malloc error.", GetLastError() ); - return FALSE; - } - - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "MAIL FROM:<%s> SIZE=%u\r\n", (char*)szFromAddress, strlen( szHeaderBuffer ) + dwBodySize + 2 ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szHeaderBuffer ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 250 ) - { - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - // Post "RCTP TO:" - char *szCurrentAddr = (char*)malloc( strlen( szToAddresses ) + 1 ); - if ( !szCurrentAddr ) - { - SetErrorText( "malloc error.", GetLastError() ); - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - const char* szToOffset = szToAddresses; - char* szZap = NULL; - - BOOL bRCPTAccepted = FALSE; - do - { - strcpy( szCurrentAddr, szToOffset ); - char *szExtractedAdress = szCurrentAddr; - szZap = strchr( szCurrentAddr, ',' ); - - if ( szZap ) - { - *szZap = 0; - szToOffset = szZap + 1; - } - - char *pSkobka1 = strchr( szCurrentAddr, '<' ); - char *pSkobka2 = strchr( szCurrentAddr, '>' ); - - if ( pSkobka1 && pSkobka2 && pSkobka2 > pSkobka1 ) - { - szExtractedAdress = pSkobka1 + 1; - *pSkobka2 = NULL; - } - - if ( szExtractedAdress && strlen( szExtractedAdress ) > 0 ) - { - sprintf( (char*)szCommandBuffer, "RCPT TO:<%s>\r\n", (char*)szExtractedAdress ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szCurrentAddr ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 250 ) - { - bRCPTAccepted = TRUE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( szCurrentAddr ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - } - - } while( szZap ); - - free( szCurrentAddr ); - - if ( bRCPTAccepted ) - { - sprintf( (char*)szCommandBuffer, "DATA\r\n" ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 354 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 354 ) - { - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - // Send message data (header + body + .) - if ( SendData( m_hSocket, (PBYTE)szHeaderBuffer, strlen( (const char*)szHeaderBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - if ( SendData( m_hSocket, (PBYTE)pBodyBuffer, dwBodySize ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - if ( SendData( m_hSocket, (PBYTE)"\r\n.\r\n", 5 ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 250 ) - { - bSuccess = TRUE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - } - } - - free( pReceiveBuffer ); - } - else - { - SetErrorText( "malloc error.", GetLastError() ); - } - - if ( szHeaderBuffer ) - free( szHeaderBuffer ); - - return bSuccess; - } - - - - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - - -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif - -#ifndef ROUNDTOPAGE -#define ROUNDTOPAGE(a) (((a/4096)+1)*4096) -#endif - - ////////////////////////////////////////////////////////////////////// - // Construction/Destruction - ////////////////////////////////////////////////////////////////////// - - inline Base64Coder::Base64Coder() - : m_pDBuffer(NULL), - m_pEBuffer(NULL), - m_nDBufLen(0), - m_nEBufLen(0) - { - - } - - inline Base64Coder::~Base64Coder() - { - if(m_pDBuffer != NULL) - delete [] m_pDBuffer; - - if(m_pEBuffer != NULL) - delete [] m_pEBuffer; - } - - inline LPCSTR Base64Coder::DecodedMessage() const - { - return (LPCSTR) m_pDBuffer; - } - - inline LPCSTR Base64Coder::EncodedMessage() const - { - return (LPCSTR) m_pEBuffer; - } - - inline void Base64Coder::AllocEncode(DWORD nSize) - { - if(m_nEBufLen < nSize) - { - if(m_pEBuffer != NULL) - delete [] m_pEBuffer; - - m_nEBufLen = ROUNDTOPAGE(nSize); - m_pEBuffer = new BYTE[m_nEBufLen]; - } - - ::ZeroMemory(m_pEBuffer, m_nEBufLen); - m_nEDataLen = 0; - } - - inline void Base64Coder::AllocDecode(DWORD nSize) - { - if(m_nDBufLen < nSize) - { - if(m_pDBuffer != NULL) - delete [] m_pDBuffer; - - m_nDBufLen = ROUNDTOPAGE(nSize); - m_pDBuffer = new BYTE[m_nDBufLen]; - } - - ::ZeroMemory(m_pDBuffer, m_nDBufLen); - m_nDDataLen = 0; - } - - inline void Base64Coder::SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen) - { - DWORD i = 0; - - AllocEncode(nBufLen); - while(i < nBufLen) - { - if(!_IsBadMimeChar(pBuffer[i])) - { - m_pEBuffer[m_nEDataLen] = pBuffer[i]; - m_nEDataLen++; - } - - i++; - } - } - - inline void Base64Coder::SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen) - { - AllocDecode(nBufLen); - ::CopyMemory(m_pDBuffer, pBuffer, nBufLen); - m_nDDataLen = nBufLen; - } - - inline void Base64Coder::Encode(const PBYTE pBuffer, DWORD nBufLen) - { - SetDecodeBuffer(pBuffer, nBufLen); - AllocEncode(nBufLen * 2); - - TempBucket Raw; - DWORD nIndex = 0; - - while((nIndex + 3) <= nBufLen) - { - Raw.Clear(); - ::CopyMemory(&Raw, m_pDBuffer + nIndex, 3); - Raw.nSize = 3; - _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen); - nIndex += 3; - m_nEDataLen += 4; - } - - if(nBufLen > nIndex) - { - Raw.Clear(); - Raw.nSize = (BYTE) (nBufLen - nIndex); - ::CopyMemory(&Raw, m_pDBuffer + nIndex, nBufLen - nIndex); - _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen); - m_nEDataLen += 4; - } - } - - inline void Base64Coder::Encode(LPCSTR szMessage) - { - if(szMessage != NULL) - Base64Coder::Encode((const PBYTE)szMessage, strlen( (const char*)szMessage)); - } - - inline void Base64Coder::Decode(const PBYTE pBuffer, DWORD dwBufLen) - { - if(is_init()) - _Init(); - - SetEncodeBuffer(pBuffer, dwBufLen); - - AllocDecode(dwBufLen); - - TempBucket Raw; - - DWORD nIndex = 0; - - while((nIndex + 4) <= m_nEDataLen) - { - Raw.Clear(); - Raw.nData[0] = DecodeTable()[m_pEBuffer[nIndex]]; - Raw.nData[1] = DecodeTable()[m_pEBuffer[nIndex + 1]]; - Raw.nData[2] = DecodeTable()[m_pEBuffer[nIndex + 2]]; - Raw.nData[3] = DecodeTable()[m_pEBuffer[nIndex + 3]]; - - if(Raw.nData[2] == 255) - Raw.nData[2] = 0; - if(Raw.nData[3] == 255) - Raw.nData[3] = 0; - - Raw.nSize = 4; - _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen); - nIndex += 4; - m_nDDataLen += 3; - } - - // If nIndex < m_nEDataLen, then we got a decode message without padding. - // We may want to throw some kind of warning here, but we are still required - // to handle the decoding as if it was properly padded. - if(nIndex < m_nEDataLen) - { - Raw.Clear(); - for(DWORD i = nIndex; i < m_nEDataLen; i++) - { - Raw.nData[i - nIndex] = DecodeTable()[m_pEBuffer[i]]; - Raw.nSize++; - if(Raw.nData[i - nIndex] == 255) - Raw.nData[i - nIndex] = 0; - } - - _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen); - m_nDDataLen += (m_nEDataLen - nIndex); - } - } - - inline void Base64Coder::Decode(LPCSTR szMessage) - { - if(szMessage != NULL) - Base64Coder::Decode((const PBYTE)szMessage, strlen((const char*)szMessage)); - } - - inline DWORD Base64Coder::_DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) - { - TempBucket Data; - DWORD nCount = 0; - - _DecodeRaw(Data, Decode); - - for(int i = 0; i < 3; i++) - { - pBuffer[i] = Data.nData[i]; - if(pBuffer[i] != 255) - nCount++; - } - - return nCount; - } - - - inline void Base64Coder::_EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) - { - TempBucket Data; - - _EncodeRaw(Data, Decode); - - for(int i = 0; i < 4; i++) - pBuffer[i] = Base64Digits()[Data.nData[i]]; - - switch(Decode.nSize) - { - case 1: - pBuffer[2] = '='; - case 2: - pBuffer[3] = '='; - } - } - - inline void Base64Coder::_DecodeRaw(TempBucket &Data, const TempBucket &Decode) - { - BYTE nTemp; - - Data.nData[0] = Decode.nData[0]; - Data.nData[0] <<= 2; - - nTemp = Decode.nData[1]; - nTemp >>= 4; - nTemp &= 0x03; - Data.nData[0] |= nTemp; - - Data.nData[1] = Decode.nData[1]; - Data.nData[1] <<= 4; - - nTemp = Decode.nData[2]; - nTemp >>= 2; - nTemp &= 0x0F; - Data.nData[1] |= nTemp; - - Data.nData[2] = Decode.nData[2]; - Data.nData[2] <<= 6; - nTemp = Decode.nData[3]; - nTemp &= 0x3F; - Data.nData[2] |= nTemp; - } - - inline void Base64Coder::_EncodeRaw(TempBucket &Data, const TempBucket &Decode) - { - BYTE nTemp; - - Data.nData[0] = Decode.nData[0]; - Data.nData[0] >>= 2; - - Data.nData[1] = Decode.nData[0]; - Data.nData[1] <<= 4; - nTemp = Decode.nData[1]; - nTemp >>= 4; - Data.nData[1] |= nTemp; - Data.nData[1] &= 0x3F; - - Data.nData[2] = Decode.nData[1]; - Data.nData[2] <<= 2; - - nTemp = Decode.nData[2]; - nTemp >>= 6; - - Data.nData[2] |= nTemp; - Data.nData[2] &= 0x3F; - - Data.nData[3] = Decode.nData[2]; - Data.nData[3] &= 0x3F; - } - - inline BOOL Base64Coder::_IsBadMimeChar(BYTE nData) - { - switch(nData) - { - case '\r': case '\n': case '\t': case ' ' : - case '\b': case '\a': case '\f': case '\v': - return TRUE; - default: - return FALSE; - } - } - - inline void Base64Coder::_Init() - { // Initialize Decoding table. - - int i; - - for(i = 0; i < 256; i++) - DecodeTable()[i] = -2; - - for(i = 0; i < 64; i++) - { - DecodeTable()[Base64Digits()[i]] = i; - DecodeTable()[Base64Digits()[i]|0x80] = i; - } - - DecodeTable()['='] = -1; - DecodeTable()['='|0x80] = -1; - - is_init() = TRUE; - } - - - } -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/net/smtp_helper.h b/src/Native/libcryptonote/contrib/epee/include/net/smtp_helper.h deleted file mode 100644 index 7827315a2..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/net/smtp_helper.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include "smtp.h" - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - inline bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_addres, const std::string& from_name, const std::string& maillist, const std::string& subject, const std::string& mail_body) - { - net_utils::smtp::CSMTPClient smtp; - - if ( !smtp.ServerConnect( server.c_str(), port ) ) - { - LOG_PRINT("Reporting: Failed to connect to server " << server <<":"<< port, LOG_LEVEL_0); - return false; - } - - if(login.size() && pass.size()) - { - if ( !smtp.ServerLogin( login.c_str(), pass.c_str()) ) - { - LOG_PRINT("Reporting: Failed to auth on server " << server <<":"<< port, LOG_LEVEL_0); - return false; - - } - } - - if ( !smtp.SendMessage( from_addres.c_str(), - from_name.c_str(), - maillist.c_str(), - subject.c_str(), - "bicycle-client", - (LPBYTE)mail_body.data(), - mail_body.size())) - { - char *szErrorText = smtp.GetLastErrorText(); - if ( szErrorText ) - { - LOG_PRINT("Failed to send message, error text: " << szErrorText, LOG_LEVEL_0); - } - else - { - LOG_PRINT("Failed to send message, error text: null", LOG_LEVEL_0); - } - return false; - } - - smtp.ServerDisconnect(); - - return true; - - - } - } -} -} diff --git a/src/Native/libcryptonote/contrib/epee/include/profile_tools.h b/src/Native/libcryptonote/contrib/epee/include/profile_tools.h deleted file mode 100644 index a0b5f77f4..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/profile_tools.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _PROFILE_TOOLS_H_ -#define _PROFILE_TOOLS_H_ - -#include "misc_os_dependent.h" - -namespace epee -{ - -#ifdef ENABLE_PROFILING -#define PROFILE_FUNC(immortal_ptr_str) static profile_tools::local_call_account lcl_acc(immortal_ptr_str); \ - profile_tools::call_frame cf(lcl_acc); - -#define PROFILE_FUNC_SECOND(immortal_ptr_str) static profile_tools::local_call_account lcl_acc2(immortal_ptr_str); \ - profile_tools::call_frame cf2(lcl_acc2); - -#define PROFILE_FUNC_THIRD(immortal_ptr_str) static profile_tools::local_call_account lcl_acc3(immortal_ptr_str); \ - profile_tools::call_frame cf3(lcl_acc3); - -#define PROFILE_FUNC_ACC(acc) \ - profile_tools::call_frame cf(acc); - - -#else -#define PROFILE_FUNC(immortal_ptr_str) -#define PROFILE_FUNC_SECOND(immortal_ptr_str) -#define PROFILE_FUNC_THIRD(immortal_ptr_str) -#endif - -#define START_WAY_POINTS() uint64_t _____way_point_time = epee::misc_utils::get_tick_count(); -#define WAY_POINT(name) {uint64_t delta = epee::misc_utils::get_tick_count()-_____way_point_time; MDEBUG("Way point " << name << ": " << delta);_____way_point_time = misc_utils::get_tick_count();} -#define WAY_POINT2(name, avrg_obj) {uint64_t delta = epee::misc_utils::get_tick_count()-_____way_point_time; avrg_obj.push(delta); MDEBUG("Way point " << name << ": " << delta);_____way_point_time = misc_utils::get_tick_count();} - - -#define TIME_MEASURE_START(var_name) uint64_t var_name = epee::misc_utils::get_tick_count(); -#define TIME_MEASURE_PAUSE(var_name) var_name = epee::misc_utils::get_tick_count() - var_name; -#define TIME_MEASURE_RESTART(var_name) var_name = epee::misc_utils::get_tick_count() - var_name; -#define TIME_MEASURE_FINISH(var_name) var_name = epee::misc_utils::get_tick_count() - var_name; - -#define TIME_MEASURE_NS_START(var_name) uint64_t var_name = epee::misc_utils::get_ns_count(); -#define TIME_MEASURE_NS_PAUSE(var_name) var_name = epee::misc_utils::get_ns_count() - var_name; -#define TIME_MEASURE_NS_RESTART(var_name) var_name = epee::misc_utils::get_ns_count() - var_name; -#define TIME_MEASURE_NS_FINISH(var_name) var_name = epee::misc_utils::get_ns_count() - var_name; - -namespace profile_tools -{ - struct local_call_account - { - local_call_account(const char* pstr):m_count_of_call(0), m_summary_time_used(0),m_pname(pstr) - {} - ~local_call_account() - { - MINFO("PROFILE "< -#include -#include - -namespace rdln -{ - typedef enum { empty, partial, full } linestatus; - class readline_buffer : public std::stringbuf - { - public: - readline_buffer(); - void start(); - void stop(); - bool is_running() const - { - return m_cout_buf != NULL; - } - linestatus get_line(std::string& line) const; - void set_prompt(const std::string& prompt); - static void add_completion(const std::string& command); - static const std::vector& get_completions(); - - protected: - virtual int sync(); - - private: - std::streambuf* m_cout_buf; - static std::vector& completion_commands(); - }; - - class suspend_readline - { - public: - suspend_readline(); - ~suspend_readline(); - private: - readline_buffer* m_buffer; - bool m_restart; - }; -} - diff --git a/src/Native/libcryptonote/contrib/epee/include/reg_exp_definer.h b/src/Native/libcryptonote/contrib/epee/include/reg_exp_definer.h deleted file mode 100644 index eb11c9e10..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/reg_exp_definer.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _REG_EXP_DEFINER_H_ -#define _REG_EXP_DEFINER_H_ - -#include -#include "syncobj.h" - -namespace epee -{ - class global_regexp_critical_section - { - private: - mutable critical_section regexp_lock; - public: - global_regexp_critical_section(){} - critical_section& get_lock()const {return regexp_lock;} - }; - - const static global_regexp_critical_section gregexplock; - -#define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_1 = 0;\ - volatile uint32_t local_is_initialized_1 = regexp_initialized_1;\ - if(!local_is_initialized_1)\ - gregexplock.get_lock().lock();\ - static const boost::regex var_name(xpr_text , reg_exp_flags);\ - if(!local_is_initialized_1)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_1, 1);\ - gregexplock.get_lock().unlock();\ -} - -#define STATIC_REGEXP_EXPR_2(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_2 = 0;\ - volatile uint32_t local_is_initialized_2 = regexp_initialized_2;\ - if(!local_is_initialized_2)\ - gregexplock.get_lock().lock().lock();\ - static const boost::regex var_name(xpr_text , reg_exp_flags);\ - if(!local_is_initialized_2)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_2, 1);\ - gregexplock.get_lock().lock().unlock();\ -} - -#define STATIC_REGEXP_EXPR_3(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_3 = 0;\ - volatile uint32_t local_is_initialized_3 = regexp_initialized_3;\ - if(!local_is_initialized_3)\ - gregexplock.get_lock().lock().lock();\ - static const boost::regex var_name(xpr_text , reg_exp_flags);\ - if(!local_is_initialized_3)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_3, 1);\ - gregexplock.get_lock().lock().unlock();\ -} -} - -#endif //_REG_EXP_DEFINER_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/reg_utils.h b/src/Native/libcryptonote/contrib/epee/include/reg_utils.h deleted file mode 100644 index 22227a9b2..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/reg_utils.h +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _MUSC_UTILS_EX_H_ -#define _MUSC_UTILS_EX_H_ - -namespace epee -{ -namespace reg_utils -{ - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetPODValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const T& valToSave, bool force_create = true) - { - HKEY hRegKey = 0; - DWORD dw = 0; - - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - if(force_create && (::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS) ) - return false; - - - DWORD val_type = (sizeof(valToSave) == sizeof(DWORD)) ? REG_DWORD:REG_BINARY; - - BOOL res = ::RegSetValueExA( hRegKey, pValName, 0, val_type, (LPBYTE)&valToSave, sizeof(valToSave)) == ERROR_SUCCESS; - - ::RegCloseKey(hRegKey); - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetPODValue(HKEY hParentKey, const char* pSubKey, const char* pValName, T& valToSave) - { - HKEY hRegKey = 0; - LONG res = 0; - - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - DWORD dwType, lSize = 0; - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || (sizeof(valToSave) < lSize) ) - { - ::RegCloseKey(hRegKey); - return false; - } - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, (LPBYTE)&valToSave, &lSize); - } - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegSetANSIString(HKEY hParentKey, const char* pSubKey, const char* pValName, const std::string& strToSave) - { - HKEY hRegKey = 0; - DWORD dw = 0; - DWORD res_ = 0; - if( (res_ = ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw)) != ERROR_SUCCESS ) - if( (res_= ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey)) != ERROR_SUCCESS ) - return false; - - DWORD valType = REG_SZ; - const char* pStr = strToSave.c_str(); - DWORD sizeOfStr = (DWORD)strToSave.size()+1; - LSTATUS res = ::RegSetValueExA(hRegKey, pValName, 0, valType, (LPBYTE)pStr, sizeOfStr); - - ::RegCloseKey(hRegKey); - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegGetANSIString(HKEY hParentKey, const char* pSubKey, const char* pValName, std::string& strToSave) - { - HKEY hRegKey = 0; - LONG res = 0; - - - if((res = ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey)) == ERROR_SUCCESS ) - { - DWORD dwType, lSize = 0; - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res) - { - - ::RegCloseKey(hRegKey); - return false; - } - char* pTmpStr = new char[lSize+2]; - memset(pTmpStr, 0, lSize+2); - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, (LPBYTE)pTmpStr, &lSize); - pTmpStr[lSize+1] = 0; //be happy ;) - strToSave = pTmpStr; - delete [] pTmpStr; - ::RegCloseKey(hRegKey); - } - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetRAWValue(HKEY hKey, const char* pValName, const TMemoryObject& valToSave, DWORD valType = REG_BINARY) - { - LONG res = ::RegSetValueExA( hKey, pValName, 0, valType, (CONST BYTE*)valToSave.get(0), (DWORD)valToSave.get_size()); - - return ERROR_SUCCESS==res ? true:false; - } - //---------------------------------------------------------------------------------------------------------------------------------- - bool RegSetRAWValue(HKEY hKey, const char* pValName, const std::string & valToSave, DWORD valType = REG_BINARY) - { - LONG res = ::RegSetValueExA( hKey, pValName, 0, valType, (CONST BYTE*)valToSave.data(), (DWORD)valToSave.size()); - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetRAWValue(HKEY hKey, const char* pValName, TMemoryObject& valToSave, DWORD* pRegType) - { - DWORD dwType, lSize = 0; - LONG res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || 0 >= lSize) - { - valToSave.release(); - return false; - } - if(valToSave.get_size() < lSize) - valToSave.alloc_buff(lSize); - res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, (LPBYTE)valToSave.get(0), &lSize); - if(pRegType) *pRegType = dwType; - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - bool RegGetRAWValue(HKEY hKey, const char* pValName, std::string& valToSave, DWORD* pRegType) - { - DWORD dwType, lSize = 0; - LONG res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || 0 >= lSize) - { - return false; - } - - valToSave.resize(lSize); - res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, (LPBYTE)valToSave.data(), &lSize); - if(pRegType) *pRegType = dwType; - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const TMemoryObject& valToSave, DWORD valType = REG_BINARY) - { - HKEY hRegKey = 0; - DWORD dw = 0; - bool res = false; - - if( ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS ) - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - return false; - - res = RegSetRAWValue(hRegKey, pValName, valToSave, valType); - - ::RegCloseKey(hRegKey); - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - bool RegSetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const std::string& valToSave, DWORD valType = REG_BINARY) - { - HKEY hRegKey = 0; - DWORD dw = 0; - bool res = false; - - if( ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS ) - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - return false; - - res = RegSetRAWValue(hRegKey, pValName, valToSave, valType); - - ::RegCloseKey(hRegKey); - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, TMemoryObject& valToSave, DWORD* pRegType) - { - HKEY hRegKey = 0; - bool res = false; - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - res = RegGetRAWValue(hRegKey, pValName, valToSave, pRegType); - ::RegCloseKey(hRegKey); - } - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegGetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, std::string& valToSave, DWORD* pRegType) - { - HKEY hRegKey = 0; - bool res = false; - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - res = RegGetRAWValue(hRegKey, pValName, valToSave, pRegType); - ::RegCloseKey(hRegKey); - } - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegRemoveValue(HKEY hParentKey, const char* pValName) - { - //CHECK_AND_ASSERT(hParentKey&&pValName, false); - return ::RegDeleteValueA(hParentKey, pValName)==ERROR_SUCCESS ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegRemoveKey(HKEY hParentKey, const char* pKeyName) - { - //CHECK_AND_ASSERT(hParentKey&&pKeyName, false); - return ::RegDeleteKeyA(hParentKey, pKeyName)==ERROR_SUCCESS ? true:false; - } - -} -} -#endif //_MUSC_UTILS_EX_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/serialization/keyvalue_serialization.h b/src/Native/libcryptonote/contrib/epee/include/serialization/keyvalue_serialization.h index 5791e1998..5459c8409 100644 --- a/src/Native/libcryptonote/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/src/Native/libcryptonote/contrib/epee/include/serialization/keyvalue_serialization.h @@ -32,6 +32,9 @@ #include "enableable.h" #include "keyvalue_serialization_overloads.h" +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "serialization" + namespace epee { /************************************************************************/ @@ -85,6 +88,14 @@ public: \ static_assert(std::is_pod::value, "t_type must be a POD type."); \ KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) +#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(varialble, val_name, default_value) \ + do { \ + static_assert(std::is_pod::value, "t_type must be a POD type."); \ + bool ret = KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name); \ + if (!ret) \ + epee::serialize_default(this_ref.varialble, default_value); \ + } while(0); + #define KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, val_name) \ epee::serialization::selector::serialize_stl_container_pod_val_as_blob(this_ref.varialble, stg, hparent_section, val_name); @@ -92,6 +103,7 @@ public: \ #define KV_SERIALIZE(varialble) KV_SERIALIZE_N(varialble, #varialble) #define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, #varialble) +#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT(varialble, def) KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(varialble, #varialble, def) #define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_pod compile time check #define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble) #define KV_SERIALIZE_OPT(variable,default_value) KV_SERIALIZE_OPT_N(variable, #variable, default_value) diff --git a/src/Native/libcryptonote/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/src/Native/libcryptonote/contrib/epee/include/serialization/keyvalue_serialization_overloads.h index 7087136cc..fc8b90a2c 100644 --- a/src/Native/libcryptonote/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/src/Native/libcryptonote/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -33,8 +33,16 @@ #include #include +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "serialization" + namespace epee { + namespace + { + template void hint_resize(C &container, size_t size) {} + template void hint_resize(std::vector &container, size_t size) { container.reserve(size); } + } namespace serialization { @@ -156,8 +164,9 @@ namespace epee typename stl_container::value_type* pelem = (typename stl_container::value_type*)buff.data(); CHECK_AND_ASSERT_MES(!(loaded_size%sizeof(typename stl_container::value_type)), false, - "size in blob " << loaded_size << " not have not zero modulo for sizeof(value_type) = " << sizeof(typename stl_container::value_type)); + "size in blob " << loaded_size << " not have not zero modulo for sizeof(value_type) = " << sizeof(typename stl_container::value_type) << ", type " << typeid(typename stl_container::value_type).name()); size_t count = (loaded_size/sizeof(typename stl_container::value_type)); + hint_resize(container, count); for(size_t i = 0; i < count; i++) container.insert(container.end(), *(pelem++)); } diff --git a/src/Native/libcryptonote/contrib/epee/include/serialization/serialize_base.h b/src/Native/libcryptonote/contrib/epee/include/serialization/serialize_base.h deleted file mode 100644 index 84a1624cb..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/serialization/serialize_base.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once - diff --git a/src/Native/libcryptonote/contrib/epee/include/service_impl_base.h b/src/Native/libcryptonote/contrib/epee/include/service_impl_base.h deleted file mode 100644 index 6e9aefc46..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/service_impl_base.h +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _SERVICE_IMPL_BASE_H_ -#define _SERVICE_IMPL_BASE_H_ - -#pragma comment(lib, "advapi32.lib") - - -namespace epee -{ -class service_impl_base { - public: - service_impl_base(); - virtual ~service_impl_base(); - - virtual const char *get_name() = 0; - virtual const char *get_caption() = 0; - virtual const char *get_description() = 0; - - bool run_service(); - virtual bool install(); - virtual bool remove(); - virtual bool init(); - void set_control_accepted(unsigned controls); - void set_status(unsigned state, unsigned pending = 0); - unsigned get_control_accepted(); - - private: - virtual void service_main() = 0; - virtual unsigned service_handler(unsigned control, unsigned event_code, - void *pdata) = 0; - //------------------------------------------------------------------------- - static service_impl_base*& instance(); - //------------------------------------------------------------------------- - static DWORD __stdcall _service_handler(DWORD control, DWORD event, - void *pdata, void *pcontext); - static void __stdcall service_entry(DWORD argc, char **pargs); - virtual SERVICE_FAILURE_ACTIONSA* get_failure_actions(); - - private: - SC_HANDLE m_manager; - SC_HANDLE m_service; - SERVICE_STATUS_HANDLE m_status_handle; - DWORD m_accepted_control; -}; - -inline service_impl_base::service_impl_base() { - m_manager = 0; - m_service = 0; - m_status_handle = 0; - m_accepted_control = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN - | SERVICE_ACCEPT_PAUSE_CONTINUE; - - instance() = this; -} -//----------------------------------------------------------------------------- -inline service_impl_base::~service_impl_base() { - if (m_service) { - ::CloseServiceHandle(m_service); - } - m_service = 0; - if (m_manager) { - ::CloseServiceHandle(m_manager); - } - m_manager = 0; - instance() = 0; -} -//----------------------------------------------------------------------------- -inline service_impl_base*& service_impl_base::instance() { - static service_impl_base *pservice = NULL; - return pservice; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::install() { - CHECK_AND_ASSERT(!m_service, false); - const char *psz_descr = get_description(); - SERVICE_FAILURE_ACTIONSA* fail_acts = get_failure_actions(); - - char sz_path[MAX_PATH]; - ::GetModuleFileNameA(0, sz_path, sizeof(sz_path)); - ::GetShortPathNameA(sz_path, sz_path, sizeof(sz_path)); - - while (TRUE) { - if (!m_manager) { - m_manager = ::OpenSCManager(NULL, NULL, GENERIC_ALL); - if (!m_manager) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - m_service = ::CreateServiceA(m_manager, get_name(), get_caption(), - SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, - SERVICE_ERROR_IGNORE, sz_path, 0, 0, 0, 0, 0); - if (!m_service) { - int err = GetLastError(); - LOG_ERROR( - "Failed to CreateService(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - - if (psz_descr) { - SERVICE_DESCRIPTIONA sd = { (char*) psz_descr }; - if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_DESCRIPTION, - &sd)) { - int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_DESCRIPTION), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (fail_acts) { - if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_FAILURE_ACTIONS, - fail_acts)) { - int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_FAILURE_ACTIONS), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - LOG_PRINT("Installed succesfully.", LOG_LEVEL_0); - return true; - } - LOG_PRINT("Failed to install.", LOG_LEVEL_0); - return false; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::remove() { - CHECK_AND_ASSERT(!m_service, false); - - while (TRUE) { - if (!m_manager) { - m_manager = ::OpenSCManager(0, 0, GENERIC_ALL); - if (!m_manager) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (!m_service) { - m_service = ::OpenServiceA(m_manager, get_name(), SERVICE_STOP | DELETE); - if (!m_service) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenService(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - SERVICE_STATUS status = { }; - if (!::ControlService(m_service, SERVICE_CONTROL_STOP, &status)) { - int err = ::GetLastError(); - if (err == ERROR_SHUTDOWN_IN_PROGRESS) - continue; - else if (err != ERROR_SERVICE_NOT_ACTIVE) { - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (!::DeleteService(m_service)) { - int err = ::GetLastError(); - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - - LOG_PRINT("Removed successfully.", LOG_LEVEL_0); - break; - } - - return true; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::init() { - return true; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::run_service() { - CHECK_AND_ASSERT(!m_service, false); - - long error_code = 0; - - SERVICE_TABLE_ENTRYA service_table[2]; - ZeroMemory(&service_table, sizeof(service_table)); - - service_table->lpServiceName = (char*) get_name(); - service_table->lpServiceProc = service_entry; - - LOG_PRINT("[+] Start service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); - - error_code = 1; - BOOL res = ::StartServiceCtrlDispatcherA(service_table); - if (!res) { - int err = GetLastError(); - LOG_PRINT( - "[+] Error starting service control dispatcher, err=" - << log_space::get_win32_err_descr(err), LOG_LEVEL_1); - return false; - } else { - LOG_PRINT("[+] End service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); - } - return true; -} -//----------------------------------------------------------------------------- -inline DWORD __stdcall service_impl_base::_service_handler(DWORD control, - DWORD event, void *pdata, void *pcontext) { - CHECK_AND_ASSERT(pcontext, ERROR_CALL_NOT_IMPLEMENTED); - - service_impl_base *pservice = (service_impl_base*) pcontext; - return pservice->service_handler(control, event, pdata); -} -//----------------------------------------------------------------------------- -inline -void __stdcall service_impl_base::service_entry(DWORD argc, char **pargs) { - service_impl_base *pme = instance(); - LOG_PRINT("instance: " << pme, LOG_LEVEL_4); - if (!pme) { - LOG_ERROR("Error: at service_entry() pme = NULL"); - return; - } - pme->m_status_handle = ::RegisterServiceCtrlHandlerExA(pme->get_name(), - _service_handler, pme); - - pme->set_status(SERVICE_RUNNING); - pme->service_main(); - pme->set_status(SERVICE_STOPPED); -} -//----------------------------------------------------------------------------- -inline -void service_impl_base::set_status(unsigned state, unsigned pending) { - if (!m_status_handle) - return; - - SERVICE_STATUS status = { 0 }; - status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - status.dwCurrentState = state; - status.dwControlsAccepted = m_accepted_control; - /*status.dwWin32ExitCode = NO_ERROR; - status.dwServiceSpecificExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - status.dwCheckPoint = 0; - status.dwWaitHint = 0; - - status.dwCurrentState = state;*/ - - if (state == SERVICE_START_PENDING || state == SERVICE_STOP_PENDING - || state == SERVICE_CONTINUE_PENDING || state == SERVICE_PAUSE_PENDING) { - status.dwWaitHint = 2000; - status.dwCheckPoint = pending; - } - ::SetServiceStatus(m_status_handle, &status); -} -//----------------------------------------------------------------------------------------- -inline -void service_impl_base::set_control_accepted(unsigned controls) { - m_accepted_control = controls; -} -//----------------------------------------------------------------------------------------- -inline -unsigned service_impl_base::get_control_accepted() { - return m_accepted_control; -} -//----------------------------------------------------------------------------------------- -inline SERVICE_FAILURE_ACTIONSA* service_impl_base::get_failure_actions() { - // first 3 failures in 30 minutes. Service will be restarted. - // do nothing for next failures - static SC_ACTION sa[] = { { SC_ACTION_RESTART, 3 * 1000 }, { - SC_ACTION_RESTART, 3 * 1000 }, { SC_ACTION_RESTART, 3 * 1000 }, { - SC_ACTION_NONE, 0 } }; - - static SERVICE_FAILURE_ACTIONSA sfa = { 1800, // interval for failures counter - 30 min - "", NULL, 4, (SC_ACTION*) &sa }; - - // TODO: refactor this code, really unsafe! - return &sfa; -} -} - -#endif //_SERVICE_IMPL_BASE_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/sha1.h b/src/Native/libcryptonote/contrib/epee/include/sha1.h deleted file mode 100644 index ce42082f8..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/sha1.h +++ /dev/null @@ -1,51 +0,0 @@ - -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SHA1_DEFINED -#define SHA1_DEFINED - -namespace sha1 { - - /** - @param src points to any kind of data to be hashed. - @param bytelength the number of bytes to hash from the src pointer. - @param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in. - */ - void calc(const void* src, const int bytelength, unsigned char* hash); - - /** - @param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function. - @param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string. - */ - void toHexString(const unsigned char* hash, char* hexstring); - -} // namespace sha1 - -#include "sha1.inl" - -#endif // SHA1_DEFINED diff --git a/src/Native/libcryptonote/contrib/epee/include/sha1.inl b/src/Native/libcryptonote/contrib/epee/include/sha1.inl deleted file mode 100644 index d33202724..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/sha1.inl +++ /dev/null @@ -1,179 +0,0 @@ - -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - Contributors: - Gustav - Several members in the gamedev.se forum. - Gregory Petrosyan - */ - -#include "sha1.h" - -namespace sha1 { -namespace {// local -// Rotate an integer value to left. -inline const unsigned int rol(const unsigned int value, - const unsigned int steps) { - return ((value << steps) | (value >> (32 - steps))); -} - -// Sets the first 16 integers in the buffert to zero. -// Used for clearing the W buffert. -inline void clearWBuffert(unsigned int* buffert) { - for (int pos = 16; --pos >= 0;) - { - buffert[pos] = 0; - } -} - -inline -void innerHash(unsigned int* result, unsigned int* w) { - unsigned int a = result[0]; - unsigned int b = result[1]; - unsigned int c = result[2]; - unsigned int d = result[3]; - unsigned int e = result[4]; - - int round = 0; - -#define sha1macro(func,val) \ - { \ - const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \ - e = d; \ - d = c; \ - c = rol(b, 30); \ - b = a; \ - a = t; \ - } - - while (round < 16) { - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 20) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 40) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0x6ed9eba1) - ++round; - } - while (round < 60) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc) - ++round; - } - while (round < 80) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0xca62c1d6) - ++round; - } - -#undef sha1macro - - result[0] += a; - result[1] += b; - result[2] += c; - result[3] += d; - result[4] += e; -} -} // namespace - -inline -void calc(const void* src, const int bytelength, unsigned char* hash) { - // Init the result array. - unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, - 0xc3d2e1f0 }; - - // Cast the void src pointer to be the byte array we can work with. - const unsigned char* sarray = (const unsigned char*) src; - - // The reusable round buffer - unsigned int w[80]; - - // Loop through all complete 64byte blocks. - const int endOfFullBlocks = bytelength - 64; - int endCurrentBlock; - int currentBlock(0); - - while (currentBlock <= endOfFullBlocks) { - endCurrentBlock = currentBlock + 64; - - // Init the round buffer with the 64 byte block data. - for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4) - { - // This line will swap endian on big endian and keep endian on little endian. - w[roundPos++] = (unsigned int) sarray[currentBlock + 3] - | (((unsigned int) sarray[currentBlock + 2]) << 8) - | (((unsigned int) sarray[currentBlock + 1]) << 16) - | (((unsigned int) sarray[currentBlock]) << 24); - } - innerHash(result, w); - } - - // Handle the last and not full 64 byte block if existing. - endCurrentBlock = bytelength - currentBlock; - clearWBuffert(w); - int lastBlockBytes = 0; - for (; lastBlockBytes < endCurrentBlock; ++lastBlockBytes) { - w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes - + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3); - } - w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3); - if (endCurrentBlock >= 56) { - innerHash(result, w); - clearWBuffert(w); - } - w[15] = bytelength << 3; - innerHash(result, w); - - // Store hash in result pointer, and make sure we get in in the correct order on both endian models. - for (int hashByte = 20; --hashByte >= 0;) { - hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) - & 0xff; - } -} -inline -void toHexString(const unsigned char* hash, char* hexstring) { - const char hexDigits[] = { "0123456789abcdef" }; - - for (int hashByte = 20; --hashByte >= 0;) - { - hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf]; - hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf]; - } - hexstring[40] = 0; -} -} // namespace sha1 diff --git a/src/Native/libcryptonote/contrib/epee/include/soci_helper.h b/src/Native/libcryptonote/contrib/epee/include/soci_helper.h deleted file mode 100644 index 1da5aa7e2..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/soci_helper.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -#include "soci.h" -#include "soci-postgresql.h" - -using namespace epee; -namespace soci -{ - - template <> - struct type_conversion - { - typedef long long base_type; - - static void from_base(base_type a_, indicator ind, uint64_t & mi) - { - if (ind == i_null) - { - mi = 0; - //throw soci_error("Null value not allowed for this type"); - } - mi = (uint64_t)a_; - //mi.set(i); - } - - static void to_base(const uint64_t & mi, base_type & i, indicator & ind) - { - i = (base_type)mi; - ind = i_ok; - } - }; - - - - template <> - struct type_conversion - { - typedef int base_type; - - static void from_base(base_type a_, indicator ind, bool& mi) - { - if (ind == i_null) - { - mi = false; - //throw soci_error("Null value not allowed for this type"); - } - mi = a_? true:false; - //mi.set(i); - } - - static void to_base(const bool & mi, base_type & i, indicator & ind) - { - i = mi? 1:0; - ind = i_ok; - } - }; - - - - class per_thread_session - { - public: - bool init(const std::string& connection_string) - { - m_connection_string = connection_string; - - return true; - } - - soci::session& get() - { - - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr& conn_ptr = m_db_connections[epee::misc_utils::get_thread_string_id()]; - m_db_connections_lock.unlock(); - if(!conn_ptr.get()) - { - conn_ptr.reset(new soci::session(soci::postgresql, m_connection_string)); - } - //init new connection - return *conn_ptr.get(); - } - - bool reopen() - { - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr& conn_ptr = m_db_connections[misc_utils::get_thread_string_id()]; - m_db_connections_lock.unlock(); - if(conn_ptr.get()) - { - conn_ptr->close(); - conn_ptr.reset(new soci::session(soci::postgresql, m_connection_string)); - } - - //init new connection - return true; - } - - //---------------------------------------------------------------------------------------------- - bool check_status() - { - return true; - } - - protected: - private: - std::map > m_db_connections; - epee::critical_section m_db_connections_lock; - std::string m_connection_string; - }; -} -/*}*/ diff --git a/src/Native/libcryptonote/contrib/epee/include/span.h b/src/Native/libcryptonote/contrib/epee/include/span.h index 452cc088f..e100452ca 100644 --- a/src/Native/libcryptonote/contrib/epee/include/span.h +++ b/src/Native/libcryptonote/contrib/epee/include/span.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // @@ -28,8 +28,10 @@ #pragma once +#include #include #include +#include #include namespace epee @@ -52,11 +54,15 @@ namespace epee template class span { - /* Supporting class types is tricky - the {ptr,len} constructor will allow - derived-to-base conversions. This is NOT desireable because an array of - derived types is not an array of base types. It is possible to handle - this case, implement when/if needed. */ - static_assert(!std::is_class(), "no class types are currently allowed"); + template + static constexpr bool safe_conversion() noexcept + { + // Allow exact matches or `T*` -> `const T*`. + using with_const = typename std::add_const::type; + return std::is_same() || + (std::is_const() && std::is_same()); + } + public: using value_type = T; using size_type = std::size_t; @@ -71,7 +77,9 @@ namespace epee constexpr span() noexcept : ptr(nullptr), len(0) {} constexpr span(std::nullptr_t) noexcept : span() {} - constexpr span(T* const src_ptr, const std::size_t count) noexcept + //! Prevent derived-to-base conversions; invalid in this context. + template()>::type> + constexpr span(U* const src_ptr, const std::size_t count) noexcept : ptr(src_ptr), len(count) {} //! Conversion from C-array. Prevents common bugs with sizeof + arrays. @@ -81,6 +89,16 @@ namespace epee constexpr span(const span&) noexcept = default; span& operator=(const span&) noexcept = default; + /*! Try to remove `amount` elements from beginning of span. + \return Number of elements removed. */ + std::size_t remove_prefix(std::size_t amount) noexcept + { + amount = std::min(len, amount); + ptr += amount; + len -= amount; + return amount; + } + constexpr iterator begin() const noexcept { return ptr; } constexpr const_iterator cbegin() const noexcept { return ptr; } @@ -92,6 +110,8 @@ namespace epee constexpr std::size_t size() const noexcept { return len; } constexpr std::size_t size_bytes() const noexcept { return size() * sizeof(value_type); } + const T &operator[](size_t idx) const { return ptr[idx]; } + private: T* ptr; std::size_t len; @@ -105,6 +125,14 @@ namespace epee return {src.data(), src.size()}; } + //! \return `span` from a STL compatible `src`. + template + constexpr span to_mut_span(T& src) + { + // compiler provides diagnostic if size() is not size_t. + return {src.data(), src.size()}; + } + template constexpr bool has_padding() noexcept { @@ -127,4 +155,21 @@ namespace epee static_assert(!has_padding(), "source type may have padding"); return {reinterpret_cast(std::addressof(src)), sizeof(T)}; } + + //! \return `span` which represents the bytes at `&src`. + template + span as_mut_byte_span(T& src) noexcept + { + static_assert(!std::is_empty(), "empty types will not work -> sizeof == 1"); + static_assert(!has_padding(), "source type may have padding"); + return {reinterpret_cast(std::addressof(src)), sizeof(T)}; + } + + //! make a span from a std::string + template + span strspan(const std::string &s) noexcept + { + static_assert(std::is_same() || std::is_same() || std::is_same() || std::is_same(), "Unexpected type"); + return {reinterpret_cast(s.data()), s.size()}; + } } diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/http_abstract_invoke.h b/src/Native/libcryptonote/contrib/epee/include/storages/http_abstract_invoke.h index d93084ab0..18b7f10c1 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/http_abstract_invoke.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/http_abstract_invoke.h @@ -97,7 +97,7 @@ namespace epee return false; } - return serialization::load_t_from_binary(result_struct, pri->m_body); + return serialization::load_t_from_binary(result_struct, epee::strspan(pri->m_body)); } template diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/levin_abstract_invoke2.h b/src/Native/libcryptonote/contrib/epee/include/storages/levin_abstract_invoke2.h index d77e7a1f8..06eb9bdaf 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/levin_abstract_invoke2.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -28,6 +28,7 @@ #include "portable_storage_template_helper.h" #include +#include "span.h" #include "net/levin_base.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -114,7 +115,7 @@ namespace epee const_cast(out_struct).store(stg);//TODO: add true const support to searilzation std::string buff_to_send; stg.store_to_binary(buff_to_send); - int res = transport.invoke_async(command, buff_to_send, conn_id, [cb, command](int code, const std::string& buff, typename t_transport::connection_context& context)->bool + int res = transport.invoke_async(command, epee::strspan(buff_to_send), conn_id, [cb, command](int code, const epee::span buff, typename t_transport::connection_context& context)->bool { t_result result_struct = AUTO_VAL_INIT(result_struct); if( code <=0 ) @@ -156,7 +157,7 @@ namespace epee std::string buff_to_send; stg.store_to_binary(buff_to_send); - int res = transport.notify(command, buff_to_send, conn_id); + int res = transport.notify(command, epee::strspan(buff_to_send), conn_id); if(res <=0 ) { MERROR("Failed to notify command " << command << " return code " << res); @@ -167,7 +168,7 @@ namespace epee //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- template - int buff_to_t_adapter(int command, const std::string& in_buff, std::string& buff_out, callback_t cb, t_context& context ) + int buff_to_t_adapter(int command, const epee::span in_buff, std::string& buff_out, callback_t cb, t_context& context ) { serialization::portable_storage strg; if(!strg.load_from_binary(in_buff)) @@ -197,7 +198,7 @@ namespace epee } template - int buff_to_t_adapter(t_owner* powner, int command, const std::string& in_buff, callback_t cb, t_context& context) + int buff_to_t_adapter(t_owner* powner, int command, const epee::span in_buff, callback_t cb, t_context& context) { serialization::portable_storage strg; if(!strg.load_from_binary(in_buff)) @@ -215,14 +216,14 @@ namespace epee } #define CHAIN_LEVIN_INVOKE_MAP2(context_type) \ - int invoke(int command, const std::string& in_buff, std::string& buff_out, context_type& context) \ + int invoke(int command, const epee::span in_buff, std::string& buff_out, context_type& context) \ { \ bool handled = false; \ return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ } #define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \ - int notify(int command, const std::string& in_buff, context_type& context) \ + int notify(int command, const epee::span in_buff, context_type& context) \ { \ bool handled = false; std::string fake_str;\ return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ @@ -230,27 +231,27 @@ namespace epee #define CHAIN_LEVIN_INVOKE_MAP() \ - int invoke(int command, const std::string& in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \ + int invoke(int command, const epee::span in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \ { \ bool handled = false; \ return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ } #define CHAIN_LEVIN_NOTIFY_MAP() \ - int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ + int notify(int command, const epee::span in_buff, epee::net_utils::connection_context_base& context) \ { \ bool handled = false; std::string fake_str;\ return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ } #define CHAIN_LEVIN_NOTIFY_STUB() \ - int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ + int notify(int command, const epee::span in_buff, epee::net_utils::connection_context_base& context) \ { \ return -1; \ } #define BEGIN_INVOKE_MAP2(owner_type) \ - template int handle_invoke_map(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, t_context& context, bool& handled) \ + template int handle_invoke_map(bool is_notify, int command, const epee::span in_buff, std::string& buff_out, t_context& context, bool& handled) \ { \ typedef owner_type internal_owner_type_name; diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/parserse_base_utils.h b/src/Native/libcryptonote/contrib/epee/include/storages/parserse_base_utils.h index c809392f4..b5c4138c5 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/parserse_base_utils.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/parserse_base_utils.h @@ -28,17 +28,61 @@ #pragma once +#include +#include + namespace epee { namespace misc_utils { namespace parse { + // 1: digit + // 2: .eE (floating point) + // 4: alpha + // 8: whitespace + // 16: allowed in float but doesn't necessarily mean it's a float + // 32: \ and " (end of verbatim string) + static const constexpr uint8_t lut[256]={ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 0, 0, // 16 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32 + 8, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 18, 0, // 48 + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, // 64 + 0, 4, 4, 4, 4, 22, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 80 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 32, 0, 0, 0, // 96 + 0, 4, 4, 4, 4, 22, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 112 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, // 128 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + inline bool isspace(char c) + { + return lut[(uint8_t)c] & 8; + } + + inline bool isdigit(char c) + { + return lut[(uint8_t)c] & 1; + } + inline std::string transform_to_escape_sequence(const std::string& src) { - //std::stringstream res; + static const char escaped[] = "\b\f\n\r\t\v\"\\/"; + std::string::const_iterator it = std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped)); + if (it == src.end()) + return src; + std::string res; - for(std::string::const_iterator it = src.begin(); it!=src.end(); ++it) + res.reserve(2 * src.size()); + res.assign(src.begin(), it); + for(; it!=src.end(); ++it) { switch(*it) { @@ -83,10 +127,15 @@ namespace misc_utils */ inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) { - val.clear(); bool escape_mode = false; std::string::const_iterator it = star_end_string; ++it; + std::string::const_iterator fi = it; + while (fi != buf_end && ((lut[(uint8_t)*fi] & 32)) == 0) + ++fi; + val.assign(it, fi); + val.reserve(std::distance(star_end_string, buf_end)); + it = fi; for(;it != buf_end;it++) { if(escape_mode/*prev_ch == '\\'*/) @@ -146,25 +195,34 @@ namespace misc_utils return false; } } - inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val, bool& is_float_val, bool& is_signed_val) + inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val) { val.clear(); - is_float_val = false; - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + uint8_t float_flag = 0; + is_signed_val = false; + size_t chars = 0; + std::string::const_iterator it = star_end_string; + if (it != buf_end && *it == '-') { - if(isdigit(*it) || (it == star_end_string && *it == '-') || (val.size() && *it == '.' ) || (is_float_val && (*it == 'e' || *it == 'E' || *it == '-' || *it == '+' )) ) + is_signed_val = true; + ++chars; + ++it; + } + for(;it != buf_end;it++) + { + const uint8_t flags = lut[(uint8_t)*it]; + if (flags & 16) { - if(!val.size() && *it == '-') - is_signed_val = true; - if(*it == '.' ) - is_float_val = true; - val.push_back(*it); + float_flag |= flags; + ++chars; } else { + val = boost::string_ref(&*star_end_string, chars); if(val.size()) { star_end_string = --it; + is_float_val = !!(float_flag & 2); return; } else @@ -173,7 +231,7 @@ namespace misc_utils } ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); } - inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) { try { @@ -186,15 +244,15 @@ namespace misc_utils return false; } } - inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) { val.clear(); for(std::string::const_iterator it = star_end_string;it != buf_end;it++) { - if(!isalpha(*it)) + if (!(lut[(uint8_t)*it] & 4)) { - val.assign(star_end_string, it); + val = boost::string_ref(&*star_end_string, std::distance(star_end_string, it)); if(val.size()) { star_end_string = --it; @@ -205,7 +263,7 @@ namespace misc_utils } ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); } - inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) { try { diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage.h b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage.h index 2023e2f2a..523597db6 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage.h @@ -35,6 +35,9 @@ #include "portable_storage_to_json.h" #include "portable_storage_from_json.h" #include "portable_storage_val_converters.h" +#include "span.h" +#include "int-util.h" +#include namespace epee { @@ -80,7 +83,8 @@ namespace epee //------------------------------------------------------------------------------- bool store_to_binary(binarybuffer& target); - bool load_from_binary(const binarybuffer& target); + bool load_from_binary(const epee::span target); + bool load_from_binary(const std::string& target) { return load_from_binary(epee::strspan(target)); } template bool dump_as_xml(std::string& targetObj, const std::string& root_name = ""); bool dump_as_json(std::string& targetObj, size_t indent = 0, bool insert_newlines = true); @@ -135,8 +139,8 @@ namespace epee TRY_ENTRY(); std::stringstream ss; storage_block_header sbh = AUTO_VAL_INIT(sbh); - sbh.m_signature_a = PORTABLE_STORAGE_SIGNATUREA; - sbh.m_signature_b = PORTABLE_STORAGE_SIGNATUREB; + sbh.m_signature_a = SWAP32LE(PORTABLE_STORAGE_SIGNATUREA); + sbh.m_signature_b = SWAP32LE(PORTABLE_STORAGE_SIGNATUREB); sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER; ss.write((const char*)&sbh, sizeof(storage_block_header)); pack_entry_to_buff(ss, m_root); @@ -145,7 +149,7 @@ namespace epee CATCH_ENTRY("portable_storage::store_to_binary", false) } inline - bool portable_storage::load_from_binary(const binarybuffer& source) + bool portable_storage::load_from_binary(const epee::span source) { m_root.m_entries.clear(); if(source.size() < sizeof(storage_block_header)) @@ -154,8 +158,8 @@ namespace epee return false; } storage_block_header* pbuff = (storage_block_header*)source.data(); - if(pbuff->m_signature_a != PORTABLE_STORAGE_SIGNATUREA || - pbuff->m_signature_b != PORTABLE_STORAGE_SIGNATUREB + if(pbuff->m_signature_a != SWAP32LE(PORTABLE_STORAGE_SIGNATUREA) || + pbuff->m_signature_b != SWAP32LE(PORTABLE_STORAGE_SIGNATUREB) ) { LOG_ERROR("portable_storage: wrong binary format - signature mismatch"); diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_base.h b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_base.h index 93132548b..ca7c81ddc 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_base.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_base.h @@ -31,7 +31,8 @@ #include #include #include -#include +#include +#include #define PORTABLE_STORAGE_SIGNATUREA 0x01011101 #define PORTABLE_STORAGE_SIGNATUREB 0x01020101 // bender's nightmare @@ -71,6 +72,9 @@ namespace epee { struct section; + template struct entry_container { typedef std::vector type; static void reserve(type &t, size_t n) { t.reserve(n); } }; + template<> struct entry_container { typedef std::deque type; static void reserve(type &t, size_t n) {} }; + /************************************************************************/ /* */ /************************************************************************/ @@ -78,6 +82,7 @@ namespace epee struct array_entry_t { array_entry_t():m_it(m_array.end()){} + array_entry_t(const array_entry_t& other):m_array(other.m_array), m_it(m_array.end()){} const t_entry_type* get_first_val() const { @@ -119,8 +124,13 @@ namespace epee return m_array.back(); } - std::list m_array; - mutable typename std::list::const_iterator m_it; + void reserve(size_t n) + { + entry_container::reserve(m_array, n); + } + + typename entry_container::type m_array; + mutable typename entry_container::type::const_iterator m_it; }; diff --git a/src/Native/libcryptonote/cryptonote_basic/account_boost_serialization.h b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_bin_utils.h similarity index 63% rename from src/Native/libcryptonote/cryptonote_basic/account_boost_serialization.h rename to src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_bin_utils.h index 7379d787f..bcde64487 100644 --- a/src/Native/libcryptonote/cryptonote_basic/account_boost_serialization.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_bin_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2019, The Monero Project // // All rights reserved. // @@ -25,33 +25,22 @@ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include "account.h" -#include "cryptonote_boost_serialization.h" +#pragma once -//namespace cryptonote { -namespace boost -{ - namespace serialization - { - template - inline void serialize(Archive &a, cryptonote::account_keys &x, const boost::serialization::version_type ver) - { - a & x.m_account_address; - a & x.m_spend_secret_key; - a & x.m_view_secret_key; - } +#include "int-util.h" - template - inline void serialize(Archive &a, cryptonote::account_public_address &x, const boost::serialization::version_type ver) - { - a & x.m_spend_public_key; - a & x.m_view_public_key; - } +template T convert_swapper(T t) { return t; } +template<> inline uint16_t convert_swapper(uint16_t t) { return SWAP16LE(t); } +template<> inline int16_t convert_swapper(int16_t t) { return SWAP16LE((uint16_t&)t); } +template<> inline uint32_t convert_swapper(uint32_t t) { return SWAP32LE(t); } +template<> inline int32_t convert_swapper(int32_t t) { return SWAP32LE((uint32_t&)t); } +template<> inline uint64_t convert_swapper(uint64_t t) { return SWAP64LE(t); } +template<> inline int64_t convert_swapper(int64_t t) { return SWAP64LE((uint64_t&)t); } +template<> inline double convert_swapper(double t) { union { uint64_t u; double d; } u; u.d = t; u.u = SWAP64LE(u.u); return u.d; } - } -} +#if BYTE_ORDER == BIG_ENDIAN +#define CONVERT_POD(x) convert_swapper(x) +#else +#define CONVERT_POD(x) (x) +#endif diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_from_bin.h b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_from_bin.h index 44a80cb21..e0a32b3ca 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_from_bin.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_from_bin.h @@ -59,6 +59,7 @@ namespace epee storage_entry load_storage_entry(); void read(section& sec); void read(std::string& str); + void read(array_entry &ae); private: struct recursuion_limitation_guard { @@ -114,6 +115,7 @@ namespace epee void throwable_buffer_reader::read(t_pod_type& pod_val) { RECURSION_LIMITATION(); + static_assert(std::is_pod::value, "POD type expected"); read(&pod_val, sizeof(pod_val)); } @@ -134,6 +136,8 @@ namespace epee //for pod types array_entry_t sa; size_t size = read_varint(); + CHECK_AND_ASSERT_THROW_MES(size <= m_count, "Size sanity check failed"); + sa.reserve(size); //TODO: add some optimization here later while(size--) sa.m_array.push_back(read()); @@ -277,5 +281,11 @@ namespace epee m_ptr+=len; m_count -= len; } + inline + void throwable_buffer_reader::read(array_entry &ae) + { + RECURSION_LIMITATION(); + CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported"); + } } } diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_from_json.h b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_from_json.h index 727f36552..3e3052541 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_from_json.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_from_json.h @@ -30,6 +30,8 @@ #include "parserse_base_utils.h" #include "file_io_utils.h" +#define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100 + namespace epee { using namespace misc_utils::parse; @@ -37,15 +39,16 @@ namespace epee { namespace json { -#define CHECK_ISSPACE() if(!isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));} +#define CHECK_ISSPACE() if(!epee::misc_utils::parse::isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));} /*inline void parse_error() { ASSERT_MES_AND_THROW("json parse error"); }*/ template - inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg) + inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg, unsigned int recursion) { + CHECK_AND_ASSERT_THROW_MES(recursion < EPEE_JSON_RECURSION_LIMIT_INTERNAL, "Wrong JSON data: recursion limitation (" << EPEE_JSON_RECURSION_LIMIT_INTERNAL << ") exceeded"); std::string::const_iterator sub_element_start; std::string name; @@ -111,33 +114,39 @@ namespace epee std::string val; match_string2(it, buf_end, val); //insert text value - stg.set_value(name, val, current_section); + stg.set_value(name, std::move(val), current_section); state = match_state_wonder_after_value; - }else if (isdigit(*it) || *it == '-') + }else if (epee::misc_utils::parse::isdigit(*it) || *it == '-') {//just a named number value started - std::string val; + boost::string_ref val; bool is_v_float = false;bool is_signed = false; match_number2(it, buf_end, val, is_v_float, is_signed); if(!is_v_float) { if(is_signed) { - int64_t nval = boost::lexical_cast(val); + errno = 0; + int64_t nval = strtoll(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); stg.set_value(name, nval, current_section); }else { - uint64_t nval = boost::lexical_cast(val); + errno = 0; + uint64_t nval = strtoull(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); stg.set_value(name, nval, current_section); } }else { - double nval = boost::lexical_cast(val); + errno = 0; + double nval = strtod(val.data(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); stg.set_value(name, nval, current_section); } state = match_state_wonder_after_value; }else if(isalpha(*it) ) {// could be null, true or false - std::string word; + boost::string_ref word; match_word2(it, buf_end, word); if(boost::iequals(word, "null")) { @@ -157,7 +166,7 @@ namespace epee //sub section here typename t_storage::hsection new_sec = stg.open_section(name, current_section, true); CHECK_AND_ASSERT_THROW_MES(new_sec, "Failed to insert new section in json: " << std::string(it, buf_end)); - run_handler(new_sec, it, buf_end, stg); + run_handler(new_sec, it, buf_end, stg, recursion + 1); state = match_state_wonder_after_value; }else if(*it == '[') {//array of something @@ -186,7 +195,7 @@ namespace epee typename t_storage::hsection new_sec = nullptr; h_array = stg.insert_first_section(name, new_sec, current_section); CHECK_AND_ASSERT_THROW_MES(h_array&&new_sec, "failed to create new section"); - run_handler(new_sec, it, buf_end, stg); + run_handler(new_sec, it, buf_end, stg, recursion + 1); state = match_state_array_after_value; array_md = array_mode_sections; }else if(*it == '"') @@ -194,23 +203,36 @@ namespace epee //mean array of strings std::string val; match_string2(it, buf_end, val); - h_array = stg.insert_first_value(name, val, current_section); + h_array = stg.insert_first_value(name, std::move(val), current_section); CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values entry"); state = match_state_array_after_value; array_md = array_mode_string; - }else if (isdigit(*it) || *it == '-') + }else if (epee::misc_utils::parse::isdigit(*it) || *it == '-') {//array of numbers value started - std::string val; + boost::string_ref val; bool is_v_float = false;bool is_signed_val = false; match_number2(it, buf_end, val, is_v_float, is_signed_val); if(!is_v_float) { - int64_t nval = boost::lexical_cast(val);//bool res = string_tools::string_to_num_fast(val, nval); - h_array = stg.insert_first_value(name, nval, current_section); + if (is_signed_val) + { + errno = 0; + int64_t nval = strtoll(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); + h_array = stg.insert_first_value(name, nval, current_section); + }else + { + errno = 0; + uint64_t nval = strtoull(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); + h_array = stg.insert_first_value(name, nval, current_section); + } CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); }else { - double nval = boost::lexical_cast(val);//bool res = string_tools::string_to_num_fast(val, nval); + errno = 0; + double nval = strtod(val.data(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); h_array = stg.insert_first_value(name, nval, current_section); CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); } @@ -223,7 +245,7 @@ namespace epee state = match_state_wonder_after_value; }else if(isalpha(*it) ) {// array of booleans - std::string word; + boost::string_ref word; match_word2(it, buf_end, word); if(boost::iequals(word, "true")) { @@ -260,7 +282,7 @@ namespace epee typename t_storage::hsection new_sec = NULL; bool res = stg.insert_next_section(h_array, new_sec); CHECK_AND_ASSERT_THROW_MES(res&&new_sec, "failed to insert next section"); - run_handler(new_sec, it, buf_end, stg); + run_handler(new_sec, it, buf_end, stg, recursion + 1); state = match_state_array_after_value; }else CHECK_ISSPACE(); break; @@ -269,27 +291,38 @@ namespace epee { std::string val; match_string2(it, buf_end, val); - bool res = stg.insert_next_value(h_array, val); + bool res = stg.insert_next_value(h_array, std::move(val)); CHECK_AND_ASSERT_THROW_MES(res, "failed to insert values"); state = match_state_array_after_value; }else CHECK_ISSPACE(); break; case array_mode_numbers: - if (isdigit(*it) || *it == '-') + if (epee::misc_utils::parse::isdigit(*it) || *it == '-') {//array of numbers value started - std::string val; + boost::string_ref val; bool is_v_float = false;bool is_signed_val = false; match_number2(it, buf_end, val, is_v_float, is_signed_val); bool insert_res = false; if(!is_v_float) { - int64_t nval = boost::lexical_cast(val); //bool res = string_tools::string_to_num_fast(val, nval); - insert_res = stg.insert_next_value(h_array, nval); - + if (is_signed_val) + { + errno = 0; + int64_t nval = strtoll(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); + insert_res = stg.insert_next_value(h_array, nval); + }else + { + errno = 0; + uint64_t nval = strtoull(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); + insert_res = stg.insert_next_value(h_array, nval); + } }else { - //TODO: optimize here if need - double nval = boost::lexical_cast(val); //string_tools::string_to_num_fast(val, nval); + errno = 0; + double nval = strtod(val.data(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); insert_res = stg.insert_next_value(h_array, nval); } CHECK_AND_ASSERT_THROW_MES(insert_res, "Failed to insert next value"); @@ -300,7 +333,7 @@ namespace epee case array_mode_booleans: if(isalpha(*it) ) {// array of booleans - std::string word; + boost::string_ref word; match_word2(it, buf_end, word); if(boost::iequals(word, "true")) { @@ -362,7 +395,7 @@ namespace epee std::string::const_iterator sec_buf_begin = buff_json.begin(); try { - run_handler(nullptr, sec_buf_begin, buff_json.end(), stg); + run_handler(nullptr, sec_buf_begin, buff_json.end(), stg, 0); return true; } catch(const std::exception& ex) diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_template_helper.h b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_template_helper.h index bbd8413fc..13c870d44 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_template_helper.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_template_helper.h @@ -84,7 +84,7 @@ namespace epee } //----------------------------------------------------------------------------------------------------------- template - bool load_t_from_binary(t_struct& out, const std::string& binary_buff) + bool load_t_from_binary(t_struct& out, const epee::span binary_buff) { portable_storage ps; bool rs = ps.load_from_binary(binary_buff); @@ -95,6 +95,12 @@ namespace epee } //----------------------------------------------------------------------------------------------------------- template + bool load_t_from_binary(t_struct& out, const std::string& binary_buff) + { + return load_t_from_binary(out, epee::strspan(binary_buff)); + } + //----------------------------------------------------------------------------------------------------------- + template bool load_t_from_binary_file(t_struct& out, const std::string& binary_file) { std::string f_buff; diff --git a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_val_converters.h b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_val_converters.h index 36bb28627..e54cda828 100644 --- a/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_val_converters.h +++ b/src/Native/libcryptonote/contrib/epee/include/storages/portable_storage_val_converters.h @@ -144,7 +144,7 @@ POP_WARNINGS { MTRACE("Converting std::string to uint64_t. Source: " << from); // String only contains digits - if(std::all_of(from.begin(), from.end(), ::isdigit)) + if(std::all_of(from.begin(), from.end(), epee::misc_utils::parse::isdigit)) to = boost::lexical_cast(from); // MyMonero ISO 8061 timestamp (2017-05-06T16:27:06Z) else if (boost::regex_match (from, boost::regex("\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\dZ"))) diff --git a/src/Native/libcryptonote/contrib/epee/include/string_coding.h b/src/Native/libcryptonote/contrib/epee/include/string_coding.h deleted file mode 100644 index 82050ef96..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/string_coding.h +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _STRING_CODING_H_ -#define _STRING_CODING_H_ - -#include - -namespace epee -{ -namespace string_encoding -{ - inline std::string convert_to_ansii(const std::wstring& str_from) - { - - std::string res(str_from.begin(), str_from.end()); - return res; - /* - std::string result; - std::locale loc; - for(unsigned int i= 0; i < str_from.size(); ++i) - { - result += std::use_facet >(loc).narrow(str_from[i]); - } - return result; - */ - - //return boost::lexical_cast(str_from); - /* - std::string str_trgt; - if(!str_from.size()) - return str_trgt; - int cb = ::WideCharToMultiByte( code_page, 0, str_from.data(), (__int32)str_from.size(), 0, 0, 0, 0 ); - if(!cb) - return str_trgt; - str_trgt.resize(cb); - ::WideCharToMultiByte( code_page, 0, str_from.data(), (int)str_from.size(), - (char*)str_trgt.data(), (int)str_trgt.size(), 0, 0); - return str_trgt;*/ - } - - inline std::string convert_to_ansii(const std::string& str_from) - { - return str_from; - } - - inline std::wstring convert_to_unicode(const std::string& str_from) - { - std::wstring result; - std::locale loc; - for(unsigned int i= 0; i < str_from.size(); ++i) - { - result += std::use_facet >(loc).widen(str_from[i]); - } - return result; - - //return boost::lexical_cast(str_from); - /* - std::wstring str_trgt; - if(!str_from.size()) - return str_trgt; - - int cb = ::MultiByteToWideChar( code_page, 0, str_from.data(), (int)str_from.size(), 0, 0 ); - if(!cb) - return str_trgt; - - str_trgt.resize(cb); - ::MultiByteToWideChar( code_page, 0, str_from.data(),(int)str_from.size(), - (wchar_t*)str_trgt.data(),(int)str_trgt.size()); - return str_trgt;*/ - } - inline std::wstring convert_to_unicode(const std::wstring& str_from) - { - return str_from; - } - - template - inline target_string convert_to_t(const std::wstring& str_from); - - template<> - inline std::string convert_to_t(const std::wstring& str_from) - { - return convert_to_ansii(str_from); - } - - template<> - inline std::wstring convert_to_t(const std::wstring& str_from) - { - return str_from; - } - - template - inline target_string convert_to_t(const std::string& str_from); - - template<> - inline std::string convert_to_t(const std::string& str_from) - { - return str_from; - } - - template<> - inline std::wstring convert_to_t(const std::string& str_from) - { - return convert_to_unicode(str_from); - } - - inline - std::string& base64_chars() - { - - static std::string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - - return chars; - - } - - inline - std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len) { - std::string ret; - int i = 0; - int j = 0; - unsigned char char_array_3[3]; - unsigned char char_array_4[4]; - - while (in_len--) { - char_array_3[i++] = *(bytes_to_encode++); - if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for(i = 0; (i <4) ; i++) - ret += base64_chars()[char_array_4[i]]; - i = 0; - } - } - - if (i) - { - for(j = i; j < 3; j++) - char_array_3[j] = '\0'; - - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (j = 0; (j < i + 1); j++) - ret += base64_chars()[char_array_4[j]]; - - while((i++ < 3)) - ret += '='; - - } - - return ret; - - } - - inline - std::string base64_encode(const std::string& str) - { - return base64_encode((unsigned char const* )str.data(), str.size()); - } - - inline bool is_base64(unsigned char c) { - return (isalnum(c) || (c == '+') || (c == '/')); - } - - - inline - std::string base64_decode(std::string const& encoded_string) { - size_t in_len = encoded_string.size(); - size_t i = 0; - size_t j = 0; - size_t in_ = 0; - unsigned char char_array_4[4], char_array_3[3]; - std::string ret; - - while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { - char_array_4[i++] = encoded_string[in_]; in_++; - if (i ==4) { - for (i = 0; i <4; i++) - char_array_4[i] = (unsigned char)base64_chars().find(char_array_4[i]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (i = 0; (i < 3); i++) - ret += char_array_3[i]; - i = 0; - } - } - - if (i) { - for (j = i; j <4; j++) - char_array_4[j] = 0; - - for (j = 0; j <4; j++) - char_array_4[j] = (unsigned char)base64_chars().find(char_array_4[j]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; - } - - return ret; - } - -} -} - -#endif //_STRING_CODING_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/string_tools.h b/src/Native/libcryptonote/contrib/epee/include/string_tools.h index 63705e401..da47b7d55 100644 --- a/src/Native/libcryptonote/contrib/epee/include/string_tools.h +++ b/src/Native/libcryptonote/contrib/epee/include/string_tools.h @@ -40,12 +40,13 @@ #include #include #include -#include -#include #include #include +#include "misc_log_ex.h" +#include "storages/parserse_base_utils.h" #include "hex.h" #include "memwipe.h" +#include "mlocker.h" #include "span.h" #include "warnings.h" @@ -58,89 +59,64 @@ #pragma comment (lib, "Rpcrt4.lib") #endif +static const constexpr unsigned char isx[256] = +{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + namespace epee { namespace string_tools { - //---------------------------------------------------------------------------- - inline std::string get_str_from_guid_a(const boost::uuids::uuid& rid) - { - return boost::lexical_cast(rid); - } - //---------------------------------------------------------------------------- - inline bool get_guid_from_string(OUT boost::uuids::uuid& inetifer, const std::string& str_id) - { - std::string local_str_id = str_id; - if(local_str_id.size() < 36) - return false; - - if('{' == *local_str_id.begin()) - local_str_id.erase(0, 1); - - if('}' == *(--local_str_id.end())) - local_str_id.erase(--local_str_id.end()); - - try - { - inetifer = boost::lexical_cast(local_str_id); - return true; - } - catch(...) - { - return false; - } - } //---------------------------------------------------------------------------- inline std::string buff_to_hex_nodelimer(const std::string& src) { return to_hex::string(to_byte_span(to_span(src))); } //---------------------------------------------------------------------------- - template - bool parse_hexstr_to_binbuff(const std::basic_string& s, std::basic_string& res, bool allow_partial_byte = false) + inline bool parse_hexstr_to_binbuff(const epee::span s, epee::span& res) { - res.clear(); - if (!allow_partial_byte && (s.size() & 1)) - return false; - try - { - long v = 0; - for(size_t i = 0; i < (s.size() + 1) / 2; i++) + if (s.size() != res.size() * 2) + return false; + + unsigned char *dst = (unsigned char *)&res[0]; + const unsigned char *src = (const unsigned char *)s.data(); + for(size_t i = 0; i < s.size(); i += 2) { - CharT byte_str[3]; - size_t copied = s.copy(byte_str, 2, 2 * i); - byte_str[copied] = CharT(0); - CharT* endptr; - v = strtoul(byte_str, &endptr, 16); - if (v < 0 || 0xFF < v || endptr != byte_str + copied) - { - return false; - } - res.push_back(static_cast(v)); + int tmp = *src++; + tmp = isx[tmp]; + if (tmp == 0xff) return false; + int t2 = *src++; + t2 = isx[t2]; + if (t2 == 0xff) return false; + *dst++ = (tmp << 4) | t2; } return true; - }catch(...) - { - return false; - } } //---------------------------------------------------------------------------- - template - bool parse_tpod_from_hex_string(const std::string& str_hash, t_pod_type& t_pod) + inline bool parse_hexstr_to_binbuff(const std::string& s, std::string& res) { - static_assert(std::is_pod::value, "expected pod type"); - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(t_pod_type)) - { + if (s.size() & 1) return false; - } - else - { - buf.copy(reinterpret_cast(&t_pod), sizeof(t_pod_type)); - return true; - } + res.resize(s.size() / 2); + epee::span rspan((char*)&res[0], res.size()); + return parse_hexstr_to_binbuff(epee::to_span(s), rspan); } //---------------------------------------------------------------------------- PUSH_WARNINGS @@ -152,7 +128,7 @@ DISABLE_GCC_WARNING(maybe-uninitialized) { for (char c : str_id) { - if (!std::isdigit(c)) + if (!epee::misc_utils::parse::isdigit(c)) return false; } } @@ -232,6 +208,15 @@ POP_WARNINGS return boost::lexical_cast(val); } //---------------------------------------------------------------------------- + inline std::string to_string_hex(uint32_t val) + { + std::stringstream ss; + ss << std::hex << val; + std::string s; + ss >> s; + return s; + } + //---------------------------------------------------------------------------- inline bool compare_no_case(const std::string& str1, const std::string& str2) { @@ -339,17 +324,10 @@ POP_WARNINGS bool hex_to_pod(const std::string& hex_str, t_pod_type& s) { static_assert(std::is_pod::value, "expected pod type"); - std::string hex_str_tr = trim(hex_str); if(sizeof(s)*2 != hex_str.size()) return false; - std::string bin_buff; - if(!parse_hexstr_to_binbuff(hex_str_tr, bin_buff)) - return false; - if(bin_buff.size()!=sizeof(s)) - return false; - - s = *(t_pod_type*)bin_buff.data(); - return true; + epee::span rspan((char*)&s, sizeof(s)); + return parse_hexstr_to_binbuff(epee::to_span(hex_str), rspan); } //---------------------------------------------------------------------------- template @@ -358,6 +336,12 @@ POP_WARNINGS return hex_to_pod(hex_str, unwrap(s)); } //---------------------------------------------------------------------------- + template + bool hex_to_pod(const std::string& hex_str, epee::mlocked& s) + { + return hex_to_pod(hex_str, unwrap(s)); + } + //---------------------------------------------------------------------------- bool validate_hex(uint64_t length, const std::string& str); //---------------------------------------------------------------------------- inline std::string get_extension(const std::string& str) @@ -381,6 +365,41 @@ POP_WARNINGS res = str.substr(0, pos); return res; } + //---------------------------------------------------------------------------- +#ifdef _WIN32 + inline std::wstring utf8_to_utf16(const std::string& str) + { + if (str.empty()) + return {}; + int wstr_size = MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), NULL, 0); + if (wstr_size == 0) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + std::wstring wstr(wstr_size, wchar_t{}); + if (!MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), &wstr[0], wstr_size)) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + return wstr; + } + inline std::string utf16_to_utf8(const std::wstring& wstr) + { + if (wstr.empty()) + return {}; + int str_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), NULL, 0, NULL, NULL); + if (str_size == 0) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + std::string str(str_size, char{}); + if (!WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), &str[0], str_size, NULL, NULL)) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + return str; + } +#endif } } #endif //_STRING_TOOLS_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/syncobj.h b/src/Native/libcryptonote/contrib/epee/include/syncobj.h index a770f09b9..9f2404856 100644 --- a/src/Native/libcryptonote/contrib/epee/include/syncobj.h +++ b/src/Native/libcryptonote/contrib/epee/include/syncobj.h @@ -31,11 +31,11 @@ #define __WINH_OBJ_H__ #include +#include #include #include #include #include -#include namespace epee { diff --git a/src/Native/libcryptonote/contrib/epee/include/tiny_ini.h b/src/Native/libcryptonote/contrib/epee/include/tiny_ini.h deleted file mode 100644 index 2bc71fc1a..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/tiny_ini.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _TINY_INI_H_ -#define _TINY_INI_H_ - -#include -#include -#include "string_tools.h" - -namespace epee -{ -namespace tiny_ini -{ - - inline - bool get_param_value(const std::string& param_name, const std::string& ini_entry, std::string& res) - { - std::string expr_str = std::string() + "^("+ param_name +") *=(.*?)$"; - const boost::regex match_ini_entry( expr_str, boost::regex::icase | boost::regex::normal); - boost::smatch result; - if(!boost::regex_search(ini_entry, result, match_ini_entry, boost::match_default)) - return false; - res = result[2]; - string_tools::trim(res); - return true; - } - inline - std::string get_param_value(const std::string& param_name, const std::string& ini_entry) - { - std::string buff; - get_param_value(param_name, ini_entry, buff); - return buff; - } - - template - bool get_param_value_as_t(const std::string& param_name, const std::string& ini_entry, T& res) - { - std::string str_res = get_param_value(param_name, ini_entry); - - string_tools::trim(str_res); - if(!str_res.size()) - return false; - - return string_tools::get_xtype_from_string(res, str_res); - } - -} -} - -#endif //_TINY_INI_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/to_nonconst_iterator.h b/src/Native/libcryptonote/contrib/epee/include/to_nonconst_iterator.h deleted file mode 100644 index 729b0e8b2..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/to_nonconst_iterator.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _TO_NONCONST_ITERATOR_H_ -#define _TO_NONCONST_ITERATOR_H_ - -namespace epee -{ - -template -typename Type::iterator to_nonsonst_iterator(Type& obj, typename Type::const_iterator it) -{ - typename Type::difference_type dist = std::distance(static_cast(obj.begin()), it); - typename Type::iterator res_it = obj.begin()+dist; - return res_it; -} - - -template -typename Type::iterator to_nonsonst_iterator(typename Type::iterator base_it, typename Type::const_iterator it) -{ - typename Type::difference_type dist = std::distance(static_cast(base_it), it); - typename Type::iterator res_it = base_it+dist; - return res_it; -} -}//namespace epee -#endif //_TO_NONCONST_ITERATOR_H_ diff --git a/src/Native/libcryptonote/contrib/epee/include/winobj.h b/src/Native/libcryptonote/contrib/epee/include/winobj.h deleted file mode 100644 index 3279cdac6..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/winobj.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef __WINH_OBJ_H__ -#define __WINH_OBJ_H__ - -#include - -namespace epee -{ -class critical_region; - -class critical_section { - - boost::mutex m_section; - -public: - - critical_section( const critical_section& section ) { - InitializeCriticalSection( &m_section ); - } - - critical_section() { - InitializeCriticalSection( &m_section ); - } - - ~critical_section() { - DeleteCriticalSection( &m_section ); - } - - void lock() { - EnterCriticalSection( &m_section ); - } - - void unlock() { - LeaveCriticalSection( &m_section ); - } - - bool tryLock() { - return TryEnterCriticalSection( &m_section )? true:false; - } - - critical_section& operator=( const critical_section& section ) - { - return *this; - } - - -}; - -class critical_region { - - ::critical_section *m_locker; - - critical_region( const critical_region& ){} - -public: - - critical_region(critical_section &cs ) { - m_locker = &cs; - cs.lock(); - } - - ~critical_region() - { - m_locker->unlock(); - } -}; - - -class shared_critical_section -{ -public: - shared_critical_section() - { - ::InitializeSRWLock(&m_srw_lock); - } - ~shared_critical_section() - {} - - bool lock_shared() - { - AcquireSRWLockShared(&m_srw_lock); - return true; - } - bool unlock_shared() - { - ReleaseSRWLockShared(&m_srw_lock); - return true; - } - bool lock_exclusive() - { - ::AcquireSRWLockExclusive(&m_srw_lock); - return true; - } - bool unlock_exclusive() - { - ::ReleaseSRWLockExclusive(&m_srw_lock); - return true; - } -private: - SRWLOCK m_srw_lock; - -}; - - -class shared_guard -{ -public: - shared_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_shared(); - } - - ~shared_guard() - { - m_ref_sec.unlock_shared(); - } - -private: - shared_critical_section& m_ref_sec; -}; - - -class exclusive_guard -{ -public: - exclusive_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_exclusive(); - } - - ~exclusive_guard() - { - m_ref_sec.unlock_exclusive(); - } - -private: - shared_critical_section& m_ref_sec; -}; - - -class event -{ -public: - event() - { - m_hevent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - } - ~event() - { - ::CloseHandle(m_hevent); - - } - - bool set() - { - return ::SetEvent(m_hevent) ? true:false; - } - - bool reset() - { - return ::ResetEvent(m_hevent) ? true:false; - } - - HANDLE get_handle() - { - return m_hevent; - } -private: - HANDLE m_hevent; - -}; - - -#define SHARED_CRITICAL_REGION_BEGIN(x) { shared_guard critical_region_var(x) -#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { exclusive_guard critical_region_var(x) - - - -#define CRITICAL_REGION_LOCAL(x) critical_region critical_region_var(x) -#define CRITICAL_REGION_BEGIN(x) { critical_region critical_region_var(x) -#define CRITICAL_REGION_END() } - - - inline const char* get_wait_for_result_as_text(DWORD res) - { - switch(res) - { - case WAIT_ABANDONED: return "WAIT_ABANDONED"; - case WAIT_TIMEOUT: return "WAIT_TIMEOUT"; - case WAIT_OBJECT_0: return "WAIT_OBJECT_0"; - case WAIT_OBJECT_0+1: return "WAIT_OBJECT_1"; - case WAIT_OBJECT_0+2: return "WAIT_OBJECT_2"; - default: - return "UNKNOWN CODE"; - } - - } - -}// namespace epee - -#endif diff --git a/src/Native/libcryptonote/contrib/epee/include/wipeable_string.h b/src/Native/libcryptonote/contrib/epee/include/wipeable_string.h index 70d1a9586..f0e526b92 100644 --- a/src/Native/libcryptonote/contrib/epee/include/wipeable_string.h +++ b/src/Native/libcryptonote/contrib/epee/include/wipeable_string.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // @@ -28,28 +28,46 @@ #pragma once +#include #include #include #include +#include "memwipe.h" +#include "fnv1.h" namespace epee { class wipeable_string { public: + typedef char value_type; + wipeable_string() {} wipeable_string(const wipeable_string &other); wipeable_string(wipeable_string &&other); wipeable_string(const std::string &other); wipeable_string(std::string &&other); wipeable_string(const char *s); + wipeable_string(const char *s, size_t len); ~wipeable_string(); void wipe(); void push_back(char c); - void pop_back(); + void operator+=(char c); + void operator+=(const std::string &s); + void operator+=(const epee::wipeable_string &s); + void operator+=(const char *s); + void append(const char *ptr, size_t len); + char pop_back(); const char *data() const noexcept { return buffer.data(); } + char *data() noexcept { return buffer.data(); } size_t size() const noexcept { return buffer.size(); } + size_t length() const noexcept { return buffer.size(); } bool empty() const noexcept { return buffer.empty(); } + void trim(); + void split(std::vector &fields) const; + boost::optional parse_hexstr() const; + template inline bool hex_to_pod(T &pod) const; + template inline bool hex_to_pod(tools::scrubbed &pod) const { return hex_to_pod(unwrap(pod)); } void resize(size_t sz); void reserve(size_t sz); void clear(); @@ -64,4 +82,29 @@ namespace epee private: std::vector buffer; }; + + template inline bool wipeable_string::hex_to_pod(T &pod) const + { + static_assert(std::is_pod::value, "expected pod type"); + if (size() != sizeof(T) * 2) + return false; + boost::optional blob = parse_hexstr(); + if (!blob) + return false; + if (blob->size() != sizeof(T)) + return false; + pod = *(const T*)blob->data(); + return true; + } +} + +namespace std +{ + template<> struct hash + { + size_t operator()(const epee::wipeable_string &s) const + { + return epee::fnv::FNV1a(s.data(), s.size()); + } + }; } diff --git a/src/Native/libcryptonote/contrib/epee/include/zlib_helper.h b/src/Native/libcryptonote/contrib/epee/include/zlib_helper.h deleted file mode 100644 index 46c7f48e6..000000000 --- a/src/Native/libcryptonote/contrib/epee/include/zlib_helper.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -extern "C" { -#include "zlib/zlib.h" -} -#pragma comment(lib, "zlibstat.lib") - -namespace epee -{ -namespace zlib_helper -{ - inline - bool pack(std::string& target){ - std::string result_packed_buff; - - z_stream zstream = {0}; - int ret = deflateInit(&zstream, Z_DEFAULT_COMPRESSION); - if(target.size()) - { - - - result_packed_buff.resize(target.size()*2, 'X'); - - zstream.next_in = (Bytef*)target.data(); - zstream.avail_in = (uInt)target.size(); - zstream.next_out = (Bytef*)result_packed_buff.data(); - zstream.avail_out = (uInt)result_packed_buff.size(); - - ret = deflate(&zstream, Z_FINISH); - CHECK_AND_ASSERT_MES(ret>=0, false, "Failed to deflate. err = " << ret); - - if(result_packed_buff.size() != zstream.avail_out) - result_packed_buff.resize(result_packed_buff.size()-zstream.avail_out); - - - result_packed_buff.erase(0, 2); - target.swap(result_packed_buff); - } - - deflateEnd(& zstream ); - return true; - } - - inline bool unpack(std::string& target) - { - z_stream zstream = {0}; - int ret = inflateInit(&zstream);// - - std::string decode_summary_buff; - size_t ungzip_buff_size = target.size() * 0x30; - std::string current_decode_buff(ungzip_buff_size, 'X'); - - while(target.size()) - { - - - zstream.next_out = (Bytef*)current_decode_buff.data(); - zstream.avail_out = (uInt)ungzip_buff_size; - - int flag = Z_SYNC_FLUSH; - - static char dummy_head[2] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, - }; - zstream.next_in = (Bytef*) dummy_head; - zstream.avail_in = sizeof(dummy_head); - ret = inflate(&zstream, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - return false; - } - - zstream.next_in = (Bytef*)target.data(); - zstream.avail_in = (uInt)target.size(); - - ret = inflate(&zstream, Z_SYNC_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - LOCAL_ASSERT(0); - return false; - } - - - target.erase(0, target.size()-zstream.avail_in); - - - if(ungzip_buff_size == zstream.avail_out) - { - LOG_ERROR("Can't unpack buffer"); - return false; - } - - - current_decode_buff.resize(ungzip_buff_size - zstream.avail_out); - if(decode_summary_buff.size()) - decode_summary_buff += current_decode_buff; - else - current_decode_buff.swap(decode_summary_buff); - - current_decode_buff.resize(ungzip_buff_size); - } - - inflateEnd(&zstream ); - - decode_summary_buff.swap(target); - return 1; - } - -}; -}//namespace epee diff --git a/src/Native/libcryptonote/contrib/epee/src/hex.cpp b/src/Native/libcryptonote/contrib/epee/src/hex.cpp deleted file mode 100644 index c143b2dc2..000000000 --- a/src/Native/libcryptonote/contrib/epee/src/hex.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2017-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "hex.h" - -#include -#include -#include -#include - -namespace epee -{ - namespace - { - template - void write_hex(T&& out, const span src) - { - static constexpr const char hex[] = u8"0123456789abcdef"; - static_assert(sizeof(hex) == 17, "bad string size"); - for (const std::uint8_t byte : src) - { - *out = hex[byte >> 4]; - ++out; - *out = hex[byte & 0x0F]; - ++out; - } - } - } - - std::string to_hex::string(const span src) - { - if (std::numeric_limits::max() / 2 < src.size()) - throw std::range_error("hex_view::to_string exceeded maximum size"); - - std::string out{}; - out.resize(src.size() * 2); - buffer_unchecked(std::addressof(out[0]), src); - return out; - } - - void to_hex::buffer(std::ostream& out, const span src) - { - write_hex(std::ostreambuf_iterator{out}, src); - } - - void to_hex::formatted(std::ostream& out, const span src) - { - out.put('<'); - buffer(out, src); - out.put('>'); - } - - void to_hex::buffer_unchecked(char* out, const span src) noexcept - { - return write_hex(out, src); - } -} diff --git a/src/Native/libcryptonote/contrib/epee/src/memwipe.c b/src/Native/libcryptonote/contrib/epee/src/memwipe.c deleted file mode 100644 index 026ef7277..000000000 --- a/src/Native/libcryptonote/contrib/epee/src/memwipe.c +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2017-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file Copyright (c) 2009-2015 The Bitcoin Core developers - -#define __STDC_WANT_LIB_EXT1__ 1 -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - -#ifdef HAVE_EXPLICIT_BZERO -#include -#endif -#include "memwipe.h" - -#if defined(_MSC_VER) -#define SCARECROW -#else -#define SCARECROW \ - __asm__ __volatile__("" : : "r"(ptr) : "memory"); -#endif - -#ifdef HAVE_MEMSET_S - -void *memwipe(void *ptr, size_t n) -{ - if (memset_s(ptr, n, 0, n)) - { -#ifdef NDEBUG - fprintf(stderr, "Error: memset_s failed\n"); - _exit(1); -#else - abort(); -#endif - } - SCARECROW // might as well... - return ptr; -} - -#elif defined HAVE_EXPLICIT_BZERO - -void *memwipe(void *ptr, size_t n) -{ - explicit_bzero(ptr, n); - SCARECROW - return ptr; -} - -#else - -/* The memory_cleanse implementation is taken from Bitcoin */ - -/* Compilers have a bad habit of removing "superfluous" memset calls that - * are trying to zero memory. For example, when memset()ing a buffer and - * then free()ing it, the compiler might decide that the memset is - * unobservable and thus can be removed. - * - * Previously we used OpenSSL which tried to stop this by a) implementing - * memset in assembly on x86 and b) putting the function in its own file - * for other platforms. - * - * This change removes those tricks in favour of using asm directives to - * scare the compiler away. As best as our compiler folks can tell, this is - * sufficient and will continue to be so. - * - * Adam Langley - * Commit: ad1907fe73334d6c696c8539646c21b11178f20f - * BoringSSL (LICENSE: ISC) - */ -static void memory_cleanse(void *ptr, size_t len) -{ - memset(ptr, 0, len); - - /* As best as we can tell, this is sufficient to break any optimisations that - might try to eliminate "superfluous" memsets. If there's an easy way to - detect memset_s, it would be better to use that. */ - SCARECROW -} - -void *memwipe(void *ptr, size_t n) -{ - memory_cleanse(ptr, n); - SCARECROW - return ptr; -} - -#endif diff --git a/src/Native/libcryptonote/contrib/epee/src/wipeable_string.cpp b/src/Native/libcryptonote/contrib/epee/src/wipeable_string.cpp deleted file mode 100644 index 6ed4ee8a2..000000000 --- a/src/Native/libcryptonote/contrib/epee/src/wipeable_string.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2017-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include "memwipe.h" -#include "misc_log_ex.h" -#include "wipeable_string.h" - -namespace epee -{ - -wipeable_string::wipeable_string(const wipeable_string &other): - buffer(other.buffer) -{ -} - -wipeable_string::wipeable_string(wipeable_string &&other) -{ - if (&other == this) - return; - buffer = std::move(other.buffer); -} - -wipeable_string::wipeable_string(const std::string &other) -{ - grow(other.size()); - memcpy(buffer.data(), other.c_str(), size()); -} - -wipeable_string::wipeable_string(std::string &&other) -{ - grow(other.size()); - memcpy(buffer.data(), other.c_str(), size()); - if (!other.empty()) - { - memwipe(&other[0], other.size()); // we're kinda left with this again aren't we - other = std::string(); - } -} - -wipeable_string::wipeable_string(const char *s) -{ - grow(strlen(s)); - memcpy(buffer.data(), s, size()); -} - -wipeable_string::~wipeable_string() -{ - wipe(); -} - -void wipeable_string::wipe() -{ - if (!buffer.empty()) - memwipe(buffer.data(), buffer.size() * sizeof(char)); -} - -void wipeable_string::grow(size_t sz, size_t reserved) -{ - if (reserved < sz) - reserved = sz; - if (reserved <= buffer.capacity()) - { - if (sz < buffer.size()) - memwipe(buffer.data() + sz, buffer.size() - sz); - buffer.resize(sz); - return; - } - size_t old_sz = buffer.size(); - std::unique_ptr tmp{new char[old_sz]}; - memcpy(tmp.get(), buffer.data(), old_sz * sizeof(char)); - if (old_sz > 0) - memwipe(buffer.data(), old_sz * sizeof(char)); - buffer.reserve(reserved); - buffer.resize(sz); - memcpy(buffer.data(), tmp.get(), old_sz * sizeof(char)); - if (old_sz > 0) - memwipe(tmp.get(), old_sz * sizeof(char)); -} - -void wipeable_string::push_back(char c) -{ - grow(size() + 1); - buffer.back() = c; -} - -void wipeable_string::pop_back() -{ - resize(size() - 1); -} - -void wipeable_string::resize(size_t sz) -{ - grow(sz); -} - -void wipeable_string::reserve(size_t sz) -{ - grow(size(), sz); -} - -void wipeable_string::clear() -{ - resize(0); -} - -wipeable_string &wipeable_string::operator=(wipeable_string &&other) -{ - if (&other != this) - buffer = std::move(other.buffer); - return *this; -} - -wipeable_string &wipeable_string::operator=(const wipeable_string &other) -{ - if (&other != this) - buffer = other.buffer; - return *this; -} - -} diff --git a/src/Native/libcryptonote/crypto/CMakeLists.txt b/src/Native/libcryptonote/crypto/CMakeLists.txt deleted file mode 100644 index 71dcedcab..000000000 --- a/src/Native/libcryptonote/crypto/CMakeLists.txt +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright (c) 2014-2018, The Monero Project -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, are -# permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, this list of -# conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright notice, this list -# of conditions and the following disclaimer in the documentation and/or other -# materials provided with the distribution. -# -# 3. Neither the name of the copyright holder nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set(crypto_sources - aesb.c - blake256.c - chacha.c - crypto-ops-data.c - crypto-ops.c - crypto.cpp - groestl.c - hash-extra-blake.c - hash-extra-groestl.c - hash-extra-jh.c - hash-extra-skein.c - hash.c - jh.c - keccak.c - oaes_lib.c - random.c - skein.c - slow-hash.c - tree-hash.c) - -set(crypto_headers) - -set(crypto_private_headers - blake256.h - chacha.h - crypto-ops.h - crypto.h - generic-ops.h - groestl.h - groestl_tables.h - hash-ops.h - hash.h - initializer.h - jh.h - keccak.h - oaes_config.h - oaes_lib.h - random.h - skein.h - skein_port.h) - -monero_private_headers(cncrypto - ${crypto_private_headers}) -monero_add_library(cncrypto - ${crypto_sources} - ${crypto_headers} - ${crypto_private_headers}) -target_link_libraries(cncrypto - PUBLIC - epee - ${Boost_SYSTEM_LIBRARY} - PRIVATE - ${EXTRA_LIBRARIES}) - -if (ARM) - option(NO_OPTIMIZED_MULTIPLY_ON_ARM - "Compute multiply using generic C implementation instead of ARM ASM" OFF) - if(NO_OPTIMIZED_MULTIPLY_ON_ARM) - message(STATUS "Using generic C implementation for multiply") - set_property(SOURCE slow-hash.c - PROPERTY COMPILE_DEFINITIONS "NO_OPTIMIZED_MULTIPLY_ON_ARM") - endif() -endif() - -# Because of the way Qt works on android with JNI, the code does not live in the main android thread -# So this code runs with a 1 MB default stack size. -# This will force the use of the heap for the allocation of the scratchpad -if (ANDROID OR IOS) - if( BUILD_GUI_DEPS ) - add_definitions(-DFORCE_USE_HEAP=1) - endif() -endif() - - diff --git a/src/Native/libcryptonote/crypto/aesb.c b/src/Native/libcryptonote/crypto/aesb.c deleted file mode 100644 index 5d57b8af4..000000000 --- a/src/Native/libcryptonote/crypto/aesb.c +++ /dev/null @@ -1,185 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 -*/ - -#include - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#define TABLE_ALIGN 32 -#define WPOLY 0x011b -#define N_COLS 4 -#define AES_BLOCK_SIZE 16 -#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) - -#if defined(_MSC_VER) -#define ALIGN __declspec(align(TABLE_ALIGN)) -#elif defined(__GNUC__) -#define ALIGN __attribute__ ((aligned(16))) -#else -#define ALIGN -#endif - -#define rf1(r,c) (r) -#define word_in(x,c) (*((uint32_t*)(x)+(c))) -#define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = (v)) - -#define s(x,c) x[c] -#define si(y,x,c) (s(y,c) = word_in(x, c)) -#define so(y,x,c) word_out(y, c, s(x,c)) -#define state_in(y,x) si(y,x,0); si(y,x,1); si(y,x,2); si(y,x,3) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) -#define to_byte(x) ((x) & 0xff) -#define bval(x,n) to_byte((x) >> (8 * (n))) - -#define fwd_var(x,r,c)\ - ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ - : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ - : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ - : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) - -#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) - -#define sb_data(w) {\ - w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ - w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ - w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ - w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ - w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ - w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ - w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ - w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ - w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ - w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ - w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ - w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ - w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ - w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ - w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ - w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ - w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ - w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ - w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ - w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ - w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ - w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ - w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ - w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ - w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ - w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ - w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ - w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ - w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ - w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ - w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ - w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } - -#define rc_data(w) {\ - w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ - w(0x1b), w(0x36) } - -#define bytes2word(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | \ - ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0)) - -#define h0(x) (x) -#define w0(p) bytes2word(p, 0, 0, 0) -#define w1(p) bytes2word(0, p, 0, 0) -#define w2(p) bytes2word(0, 0, p, 0) -#define w3(p) bytes2word(0, 0, 0, p) - -#define u0(p) bytes2word(f2(p), p, p, f3(p)) -#define u1(p) bytes2word(f3(p), f2(p), p, p) -#define u2(p) bytes2word(p, f3(p), f2(p), p) -#define u3(p) bytes2word(p, p, f3(p), f2(p)) - -#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) -#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) -#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) -#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) - -#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) -#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) -#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) ^ (((x>>5) & 4) * WPOLY)) -#define f3(x) (f2(x) ^ x) -#define f9(x) (f8(x) ^ x) -#define fb(x) (f8(x) ^ f2(x) ^ x) -#define fd(x) (f8(x) ^ f4(x) ^ x) -#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) - -#define t_dec(m,n) t_##m##n -#define t_set(m,n) t_##m##n -#define t_use(m,n) t_##m##n - -#define d_4(t,n,b,e,f,g,h) ALIGN const t n[4][256] = { b(e), b(f), b(g), b(h) } - -#define four_tables(x,tab,vf,rf,c) \ - (tab[0][bval(vf(x,0,c),rf(0,c))] \ - ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ - ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ - ^ tab[3][bval(vf(x,3,c),rf(3,c))]) - -d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3); - -#if !defined(STATIC) -#define STATIC -#endif - -#if !defined(INLINE) -#define INLINE -#endif - -STATIC INLINE void aesb_single_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey) -{ - uint32_t b0[4], b1[4]; - const uint32_t *kp = (uint32_t *) expandedKey; - state_in(b0, in); - - round(fwd_rnd, b1, b0, kp); - - state_out(out, b1); -} - -STATIC INLINE void aesb_pseudo_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey) -{ - uint32_t b0[4], b1[4]; - const uint32_t *kp = (uint32_t *) expandedKey; - state_in(b0, in); - - round(fwd_rnd, b1, b0, kp); - round(fwd_rnd, b0, b1, kp + 1 * N_COLS); - round(fwd_rnd, b1, b0, kp + 2 * N_COLS); - round(fwd_rnd, b0, b1, kp + 3 * N_COLS); - round(fwd_rnd, b1, b0, kp + 4 * N_COLS); - round(fwd_rnd, b0, b1, kp + 5 * N_COLS); - round(fwd_rnd, b1, b0, kp + 6 * N_COLS); - round(fwd_rnd, b0, b1, kp + 7 * N_COLS); - round(fwd_rnd, b1, b0, kp + 8 * N_COLS); - round(fwd_rnd, b0, b1, kp + 9 * N_COLS); - - state_out(out, b0); -} - - -#if defined(__cplusplus) -} -#endif diff --git a/src/Native/libcryptonote/crypto/blake256.c b/src/Native/libcryptonote/crypto/blake256.c deleted file mode 100644 index d503c47e0..000000000 --- a/src/Native/libcryptonote/crypto/blake256.c +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -/* - * The blake256_* and blake224_* functions are largely copied from - * blake256_light.c and blake224_light.c from the BLAKE website: - * - * http://131002.net/blake/ - * - * The hmac_* functions implement HMAC-BLAKE-256 and HMAC-BLAKE-224. - * HMAC is specified by RFC 2104. - */ - -#include -#include -#include -#include "blake256.h" - -#define U8TO32(p) \ - (((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \ - ((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]) )) -#define U32TO8(p, v) \ - (p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \ - (p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) ); - -const uint8_t sigma[][16] = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}, - {14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3}, - {11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4}, - { 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8}, - { 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13}, - { 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9}, - {12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11}, - {13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10}, - { 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5}, - {10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13, 0}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}, - {14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3}, - {11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4}, - { 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8} -}; - -const uint32_t cst[16] = { - 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, - 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, - 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, - 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917 -}; - -static const uint8_t padding[] = { - 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; - - -void blake256_compress(state *S, const uint8_t *block) { - uint32_t v[16], m[16], i; - -#define ROT(x,n) (((x)<<(32-n))|((x)>>(n))) -#define G(a,b,c,d,e) \ - v[a] += (m[sigma[i][e]] ^ cst[sigma[i][e+1]]) + v[b]; \ - v[d] = ROT(v[d] ^ v[a],16); \ - v[c] += v[d]; \ - v[b] = ROT(v[b] ^ v[c],12); \ - v[a] += (m[sigma[i][e+1]] ^ cst[sigma[i][e]])+v[b]; \ - v[d] = ROT(v[d] ^ v[a], 8); \ - v[c] += v[d]; \ - v[b] = ROT(v[b] ^ v[c], 7); - - for (i = 0; i < 16; ++i) m[i] = U8TO32(block + i * 4); - for (i = 0; i < 8; ++i) v[i] = S->h[i]; - v[ 8] = S->s[0] ^ 0x243F6A88; - v[ 9] = S->s[1] ^ 0x85A308D3; - v[10] = S->s[2] ^ 0x13198A2E; - v[11] = S->s[3] ^ 0x03707344; - v[12] = 0xA4093822; - v[13] = 0x299F31D0; - v[14] = 0x082EFA98; - v[15] = 0xEC4E6C89; - - if (S->nullt == 0) { - v[12] ^= S->t[0]; - v[13] ^= S->t[0]; - v[14] ^= S->t[1]; - v[15] ^= S->t[1]; - } - - for (i = 0; i < 14; ++i) { - G(0, 4, 8, 12, 0); - G(1, 5, 9, 13, 2); - G(2, 6, 10, 14, 4); - G(3, 7, 11, 15, 6); - G(3, 4, 9, 14, 14); - G(2, 7, 8, 13, 12); - G(0, 5, 10, 15, 8); - G(1, 6, 11, 12, 10); - } - - for (i = 0; i < 16; ++i) S->h[i % 8] ^= v[i]; - for (i = 0; i < 8; ++i) S->h[i] ^= S->s[i % 4]; -} - -void blake256_init(state *S) { - S->h[0] = 0x6A09E667; - S->h[1] = 0xBB67AE85; - S->h[2] = 0x3C6EF372; - S->h[3] = 0xA54FF53A; - S->h[4] = 0x510E527F; - S->h[5] = 0x9B05688C; - S->h[6] = 0x1F83D9AB; - S->h[7] = 0x5BE0CD19; - S->t[0] = S->t[1] = S->buflen = S->nullt = 0; - S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; -} - -void blake224_init(state *S) { - S->h[0] = 0xC1059ED8; - S->h[1] = 0x367CD507; - S->h[2] = 0x3070DD17; - S->h[3] = 0xF70E5939; - S->h[4] = 0xFFC00B31; - S->h[5] = 0x68581511; - S->h[6] = 0x64F98FA7; - S->h[7] = 0xBEFA4FA4; - S->t[0] = S->t[1] = S->buflen = S->nullt = 0; - S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; -} - -// datalen = number of bits -void blake256_update(state *S, const uint8_t *data, uint64_t datalen) { - int left = S->buflen >> 3; - int fill = 64 - left; - - if (left && (((datalen >> 3)) >= (unsigned) fill)) { - memcpy((void *) (S->buf + left), (void *) data, fill); - S->t[0] += 512; - if (S->t[0] == 0) S->t[1]++; - blake256_compress(S, S->buf); - data += fill; - datalen -= (fill << 3); - left = 0; - } - - while (datalen >= 512) { - S->t[0] += 512; - if (S->t[0] == 0) S->t[1]++; - blake256_compress(S, data); - data += 64; - datalen -= 512; - } - - if (datalen > 0) { - memcpy((void *) (S->buf + left), (void *) data, datalen >> 3); - S->buflen = (left << 3) + datalen; - } else { - S->buflen = 0; - } -} - -// datalen = number of bits -void blake224_update(state *S, const uint8_t *data, uint64_t datalen) { - blake256_update(S, data, datalen); -} - -void blake256_final_h(state *S, uint8_t *digest, uint8_t pa, uint8_t pb) { - uint8_t msglen[8]; - uint32_t lo = S->t[0] + S->buflen, hi = S->t[1]; - if (lo < (unsigned) S->buflen) hi++; - U32TO8(msglen + 0, hi); - U32TO8(msglen + 4, lo); - - if (S->buflen == 440) { /* one padding byte */ - S->t[0] -= 8; - blake256_update(S, &pa, 8); - } else { - if (S->buflen < 440) { /* enough space to fill the block */ - if (S->buflen == 0) S->nullt = 1; - S->t[0] -= 440 - S->buflen; - blake256_update(S, padding, 440 - S->buflen); - } else { /* need 2 compressions */ - S->t[0] -= 512 - S->buflen; - blake256_update(S, padding, 512 - S->buflen); - S->t[0] -= 440; - blake256_update(S, padding + 1, 440); - S->nullt = 1; - } - blake256_update(S, &pb, 8); - S->t[0] -= 8; - } - S->t[0] -= 64; - blake256_update(S, msglen, 64); - - U32TO8(digest + 0, S->h[0]); - U32TO8(digest + 4, S->h[1]); - U32TO8(digest + 8, S->h[2]); - U32TO8(digest + 12, S->h[3]); - U32TO8(digest + 16, S->h[4]); - U32TO8(digest + 20, S->h[5]); - U32TO8(digest + 24, S->h[6]); - U32TO8(digest + 28, S->h[7]); -} - -void blake256_final(state *S, uint8_t *digest) { - blake256_final_h(S, digest, 0x81, 0x01); -} - -void blake224_final(state *S, uint8_t *digest) { - blake256_final_h(S, digest, 0x80, 0x00); -} - -// inlen = number of bytes -void blake256_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) { - state S; - blake256_init(&S); - blake256_update(&S, in, inlen * 8); - blake256_final(&S, out); -} - -// inlen = number of bytes -void blake224_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) { - state S; - blake224_init(&S); - blake224_update(&S, in, inlen * 8); - blake224_final(&S, out); -} - -// keylen = number of bytes -void hmac_blake256_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) { - const uint8_t *key = _key; - uint8_t keyhash[32]; - uint8_t pad[64]; - uint64_t i; - - if (keylen > 64) { - blake256_hash(keyhash, key, keylen); - key = keyhash; - keylen = 32; - } - - blake256_init(&S->inner); - memset(pad, 0x36, 64); - for (i = 0; i < keylen; ++i) { - pad[i] ^= key[i]; - } - blake256_update(&S->inner, pad, 512); - - blake256_init(&S->outer); - memset(pad, 0x5c, 64); - for (i = 0; i < keylen; ++i) { - pad[i] ^= key[i]; - } - blake256_update(&S->outer, pad, 512); - - memset(keyhash, 0, 32); -} - -// keylen = number of bytes -void hmac_blake224_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) { - const uint8_t *key = _key; - uint8_t keyhash[32]; - uint8_t pad[64]; - uint64_t i; - - if (keylen > 64) { - blake256_hash(keyhash, key, keylen); - key = keyhash; - keylen = 28; - } - - blake224_init(&S->inner); - memset(pad, 0x36, 64); - for (i = 0; i < keylen; ++i) { - pad[i] ^= key[i]; - } - blake224_update(&S->inner, pad, 512); - - blake224_init(&S->outer); - memset(pad, 0x5c, 64); - for (i = 0; i < keylen; ++i) { - pad[i] ^= key[i]; - } - blake224_update(&S->outer, pad, 512); - - memset(keyhash, 0, 32); -} - -// datalen = number of bits -void hmac_blake256_update(hmac_state *S, const uint8_t *data, uint64_t datalen) { - // update the inner state - blake256_update(&S->inner, data, datalen); -} - -// datalen = number of bits -void hmac_blake224_update(hmac_state *S, const uint8_t *data, uint64_t datalen) { - // update the inner state - blake224_update(&S->inner, data, datalen); -} - -void hmac_blake256_final(hmac_state *S, uint8_t *digest) { - uint8_t ihash[32]; - blake256_final(&S->inner, ihash); - blake256_update(&S->outer, ihash, 256); - blake256_final(&S->outer, digest); - memset(ihash, 0, 32); -} - -void hmac_blake224_final(hmac_state *S, uint8_t *digest) { - uint8_t ihash[32]; - blake224_final(&S->inner, ihash); - blake224_update(&S->outer, ihash, 224); - blake224_final(&S->outer, digest); - memset(ihash, 0, 32); -} - -// keylen = number of bytes; inlen = number of bytes -void hmac_blake256_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint64_t inlen) { - hmac_state S; - hmac_blake256_init(&S, key, keylen); - hmac_blake256_update(&S, in, inlen * 8); - hmac_blake256_final(&S, out); -} - -// keylen = number of bytes; inlen = number of bytes -void hmac_blake224_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint64_t inlen) { - hmac_state S; - hmac_blake224_init(&S, key, keylen); - hmac_blake224_update(&S, in, inlen * 8); - hmac_blake224_final(&S, out); -} diff --git a/src/Native/libcryptonote/crypto/blake256.h b/src/Native/libcryptonote/crypto/blake256.h deleted file mode 100644 index 073772289..000000000 --- a/src/Native/libcryptonote/crypto/blake256.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#ifndef _BLAKE256_H_ -#define _BLAKE256_H_ - -#include - -typedef struct { - uint32_t h[8], s[4], t[2]; - int buflen, nullt; - uint8_t buf[64]; -} state; - -typedef struct { - state inner; - state outer; -} hmac_state; - -void blake256_init(state *); -void blake224_init(state *); - -void blake256_update(state *, const uint8_t *, uint64_t); -void blake224_update(state *, const uint8_t *, uint64_t); - -void blake256_final(state *, uint8_t *); -void blake224_final(state *, uint8_t *); - -void blake256_hash(uint8_t *, const uint8_t *, uint64_t); -void blake224_hash(uint8_t *, const uint8_t *, uint64_t); - -/* HMAC functions: */ - -void hmac_blake256_init(hmac_state *, const uint8_t *, uint64_t); -void hmac_blake224_init(hmac_state *, const uint8_t *, uint64_t); - -void hmac_blake256_update(hmac_state *, const uint8_t *, uint64_t); -void hmac_blake224_update(hmac_state *, const uint8_t *, uint64_t); - -void hmac_blake256_final(hmac_state *, uint8_t *); -void hmac_blake224_final(hmac_state *, uint8_t *); - -void hmac_blake256_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t); -void hmac_blake224_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t); - -#endif /* _BLAKE256_H_ */ diff --git a/src/Native/libcryptonote/crypto/chacha.c b/src/Native/libcryptonote/crypto/chacha.c deleted file mode 100644 index 5d3edb98d..000000000 --- a/src/Native/libcryptonote/crypto/chacha.c +++ /dev/null @@ -1,182 +0,0 @@ -/* -chacha-merged.c version 20080118 -D. J. Bernstein -Public domain. -*/ - -#include -#include -#ifndef _MSC_VER -#include -#endif - -#include "chacha.h" -#include "common/int-util.h" -#include "warnings.h" - -/* - * The following macros are used to obtain exact-width results. - */ -#define U8V(v) ((uint8_t)(v) & UINT8_C(0xFF)) -#define U32V(v) ((uint32_t)(v) & UINT32_C(0xFFFFFFFF)) - -/* - * The following macros load words from an array of bytes with - * different types of endianness, and vice versa. - */ -#define U8TO32_LITTLE(p) SWAP32LE(((uint32_t*)(p))[0]) -#define U32TO8_LITTLE(p, v) (((uint32_t*)(p))[0] = SWAP32LE(v)) - -#define ROTATE(v,c) (rol32(v,c)) -#define XOR(v,w) ((v) ^ (w)) -#define PLUS(v,w) (U32V((v) + (w))) -#define PLUSONE(v) (PLUS((v),1)) - -#define QUARTERROUND(a,b,c,d) \ - a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ - c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ - a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ - c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); - -static const char sigma[] = "expand 32-byte k"; - -DISABLE_GCC_AND_CLANG_WARNING(strict-aliasing) - -static void chacha(unsigned rounds, const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher) { - uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; - uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; - char* ctarget = 0; - char tmp[64]; - int i; - - if (!length) return; - - j0 = U8TO32_LITTLE(sigma + 0); - j1 = U8TO32_LITTLE(sigma + 4); - j2 = U8TO32_LITTLE(sigma + 8); - j3 = U8TO32_LITTLE(sigma + 12); - j4 = U8TO32_LITTLE(key + 0); - j5 = U8TO32_LITTLE(key + 4); - j6 = U8TO32_LITTLE(key + 8); - j7 = U8TO32_LITTLE(key + 12); - j8 = U8TO32_LITTLE(key + 16); - j9 = U8TO32_LITTLE(key + 20); - j10 = U8TO32_LITTLE(key + 24); - j11 = U8TO32_LITTLE(key + 28); - j12 = 0; - j13 = 0; - j14 = U8TO32_LITTLE(iv + 0); - j15 = U8TO32_LITTLE(iv + 4); - - for (;;) { - if (length < 64) { - memcpy(tmp, data, length); - data = tmp; - ctarget = cipher; - cipher = tmp; - } - x0 = j0; - x1 = j1; - x2 = j2; - x3 = j3; - x4 = j4; - x5 = j5; - x6 = j6; - x7 = j7; - x8 = j8; - x9 = j9; - x10 = j10; - x11 = j11; - x12 = j12; - x13 = j13; - x14 = j14; - x15 = j15; - for (i = rounds;i > 0;i -= 2) { - QUARTERROUND( x0, x4, x8,x12) - QUARTERROUND( x1, x5, x9,x13) - QUARTERROUND( x2, x6,x10,x14) - QUARTERROUND( x3, x7,x11,x15) - QUARTERROUND( x0, x5,x10,x15) - QUARTERROUND( x1, x6,x11,x12) - QUARTERROUND( x2, x7, x8,x13) - QUARTERROUND( x3, x4, x9,x14) - } - x0 = PLUS( x0, j0); - x1 = PLUS( x1, j1); - x2 = PLUS( x2, j2); - x3 = PLUS( x3, j3); - x4 = PLUS( x4, j4); - x5 = PLUS( x5, j5); - x6 = PLUS( x6, j6); - x7 = PLUS( x7, j7); - x8 = PLUS( x8, j8); - x9 = PLUS( x9, j9); - x10 = PLUS(x10,j10); - x11 = PLUS(x11,j11); - x12 = PLUS(x12,j12); - x13 = PLUS(x13,j13); - x14 = PLUS(x14,j14); - x15 = PLUS(x15,j15); - - x0 = XOR( x0,U8TO32_LITTLE((uint8_t*)data + 0)); - x1 = XOR( x1,U8TO32_LITTLE((uint8_t*)data + 4)); - x2 = XOR( x2,U8TO32_LITTLE((uint8_t*)data + 8)); - x3 = XOR( x3,U8TO32_LITTLE((uint8_t*)data + 12)); - x4 = XOR( x4,U8TO32_LITTLE((uint8_t*)data + 16)); - x5 = XOR( x5,U8TO32_LITTLE((uint8_t*)data + 20)); - x6 = XOR( x6,U8TO32_LITTLE((uint8_t*)data + 24)); - x7 = XOR( x7,U8TO32_LITTLE((uint8_t*)data + 28)); - x8 = XOR( x8,U8TO32_LITTLE((uint8_t*)data + 32)); - x9 = XOR( x9,U8TO32_LITTLE((uint8_t*)data + 36)); - x10 = XOR(x10,U8TO32_LITTLE((uint8_t*)data + 40)); - x11 = XOR(x11,U8TO32_LITTLE((uint8_t*)data + 44)); - x12 = XOR(x12,U8TO32_LITTLE((uint8_t*)data + 48)); - x13 = XOR(x13,U8TO32_LITTLE((uint8_t*)data + 52)); - x14 = XOR(x14,U8TO32_LITTLE((uint8_t*)data + 56)); - x15 = XOR(x15,U8TO32_LITTLE((uint8_t*)data + 60)); - - j12 = PLUSONE(j12); - if (!j12) - { - j13 = PLUSONE(j13); - /* stopping at 2^70 bytes per iv is user's responsibility */ - } - - U32TO8_LITTLE(cipher + 0,x0); - U32TO8_LITTLE(cipher + 4,x1); - U32TO8_LITTLE(cipher + 8,x2); - U32TO8_LITTLE(cipher + 12,x3); - U32TO8_LITTLE(cipher + 16,x4); - U32TO8_LITTLE(cipher + 20,x5); - U32TO8_LITTLE(cipher + 24,x6); - U32TO8_LITTLE(cipher + 28,x7); - U32TO8_LITTLE(cipher + 32,x8); - U32TO8_LITTLE(cipher + 36,x9); - U32TO8_LITTLE(cipher + 40,x10); - U32TO8_LITTLE(cipher + 44,x11); - U32TO8_LITTLE(cipher + 48,x12); - U32TO8_LITTLE(cipher + 52,x13); - U32TO8_LITTLE(cipher + 56,x14); - U32TO8_LITTLE(cipher + 60,x15); - - if (length <= 64) { - if (length < 64) { - memcpy(ctarget, cipher, length); - } - return; - } - length -= 64; - cipher += 64; - data = (uint8_t*)data + 64; - } -} - -void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher) -{ - chacha(8, data, length, key, iv, cipher); -} - -void chacha20(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher) -{ - chacha(20, data, length, key, iv, cipher); -} diff --git a/src/Native/libcryptonote/crypto/chacha.h b/src/Native/libcryptonote/crypto/chacha.h deleted file mode 100644 index 7a120931a..000000000 --- a/src/Native/libcryptonote/crypto/chacha.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include -#include - -#define CHACHA_KEY_SIZE 32 -#define CHACHA_IV_SIZE 8 - -#if defined(__cplusplus) -#include - -#include "memwipe.h" -#include "hash.h" - -namespace crypto { - extern "C" { -#endif - void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher); - void chacha20(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher); -#if defined(__cplusplus) - } - - using chacha_key = tools::scrubbed_arr; - -#pragma pack(push, 1) - // MS VC 2012 doesn't interpret `class chacha_iv` as POD in spite of [9.0.10], so it is a struct - struct chacha_iv { - uint8_t data[CHACHA_IV_SIZE]; - }; -#pragma pack(pop) - - static_assert(sizeof(chacha_key) == CHACHA_KEY_SIZE && sizeof(chacha_iv) == CHACHA_IV_SIZE, "Invalid structure size"); - - inline void chacha8(const void* data, std::size_t length, const chacha_key& key, const chacha_iv& iv, char* cipher) { - chacha8(data, length, key.data(), reinterpret_cast(&iv), cipher); - } - - inline void chacha20(const void* data, std::size_t length, const chacha_key& key, const chacha_iv& iv, char* cipher) { - chacha20(data, length, key.data(), reinterpret_cast(&iv), cipher); - } - - inline void generate_chacha_key(const void *data, size_t size, chacha_key& key) { - static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key"); - tools::scrubbed_arr pwd_hash; - crypto::cn_slow_hash(data, size, pwd_hash.data(), 0/*variant*/, 0/*prehashed*/); - memcpy(&key, pwd_hash.data(), sizeof(key)); - } - - inline void generate_chacha_key_prehashed(const void *data, size_t size, chacha_key& key) { - static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key"); - tools::scrubbed_arr pwd_hash; - crypto::cn_slow_hash(data, size, pwd_hash.data(), 0/*variant*/, 1/*prehashed*/); - memcpy(&key, pwd_hash.data(), sizeof(key)); - } - - inline void generate_chacha_key(std::string password, chacha_key& key) { - return generate_chacha_key(password.data(), password.size(), key); - } -} - -#endif diff --git a/src/Native/libcryptonote/crypto/chacha8.c b/src/Native/libcryptonote/crypto/chacha8.c deleted file mode 100644 index 81d047d2b..000000000 --- a/src/Native/libcryptonote/crypto/chacha8.c +++ /dev/null @@ -1,173 +0,0 @@ -/* -chacha-merged.c version 20080118 -D. J. Bernstein -Public domain. -*/ - -#include -#include - -#if !defined(_MSC_VER) -#include -#endif - -#include "chacha8.h" -#include "common/int-util.h" -#include "warnings.h" - -/* - * The following macros are used to obtain exact-width results. - */ -#define U8V(v) ((uint8_t)(v) & UINT8_C(0xFF)) -#define U32V(v) ((uint32_t)(v) & UINT32_C(0xFFFFFFFF)) - -/* - * The following macros load words from an array of bytes with - * different types of endianness, and vice versa. - */ -#define U8TO32_LITTLE(p) SWAP32LE(((uint32_t*)(p))[0]) -#define U32TO8_LITTLE(p, v) (((uint32_t*)(p))[0] = SWAP32LE(v)) - -#define ROTATE(v,c) (rol32(v,c)) -#define XOR(v,w) ((v) ^ (w)) -#define PLUS(v,w) (U32V((v) + (w))) -#define PLUSONE(v) (PLUS((v),1)) - -#define QUARTERROUND(a,b,c,d) \ - a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ - c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ - a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ - c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); - -static const char sigma[] = "expand 32-byte k"; - -DISABLE_GCC_AND_CLANG_WARNING(strict-aliasing) - -void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher) { - uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; - uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; - char* ctarget = 0; - char tmp[64]; - int i; - - if (!length) return; - - j0 = U8TO32_LITTLE(sigma + 0); - j1 = U8TO32_LITTLE(sigma + 4); - j2 = U8TO32_LITTLE(sigma + 8); - j3 = U8TO32_LITTLE(sigma + 12); - j4 = U8TO32_LITTLE(key + 0); - j5 = U8TO32_LITTLE(key + 4); - j6 = U8TO32_LITTLE(key + 8); - j7 = U8TO32_LITTLE(key + 12); - j8 = U8TO32_LITTLE(key + 16); - j9 = U8TO32_LITTLE(key + 20); - j10 = U8TO32_LITTLE(key + 24); - j11 = U8TO32_LITTLE(key + 28); - j12 = 0; - j13 = 0; - j14 = U8TO32_LITTLE(iv + 0); - j15 = U8TO32_LITTLE(iv + 4); - - for (;;) { - if (length < 64) { - memcpy(tmp, data, length); - data = tmp; - ctarget = cipher; - cipher = tmp; - } - x0 = j0; - x1 = j1; - x2 = j2; - x3 = j3; - x4 = j4; - x5 = j5; - x6 = j6; - x7 = j7; - x8 = j8; - x9 = j9; - x10 = j10; - x11 = j11; - x12 = j12; - x13 = j13; - x14 = j14; - x15 = j15; - for (i = 8;i > 0;i -= 2) { - QUARTERROUND( x0, x4, x8,x12) - QUARTERROUND( x1, x5, x9,x13) - QUARTERROUND( x2, x6,x10,x14) - QUARTERROUND( x3, x7,x11,x15) - QUARTERROUND( x0, x5,x10,x15) - QUARTERROUND( x1, x6,x11,x12) - QUARTERROUND( x2, x7, x8,x13) - QUARTERROUND( x3, x4, x9,x14) - } - x0 = PLUS( x0, j0); - x1 = PLUS( x1, j1); - x2 = PLUS( x2, j2); - x3 = PLUS( x3, j3); - x4 = PLUS( x4, j4); - x5 = PLUS( x5, j5); - x6 = PLUS( x6, j6); - x7 = PLUS( x7, j7); - x8 = PLUS( x8, j8); - x9 = PLUS( x9, j9); - x10 = PLUS(x10,j10); - x11 = PLUS(x11,j11); - x12 = PLUS(x12,j12); - x13 = PLUS(x13,j13); - x14 = PLUS(x14,j14); - x15 = PLUS(x15,j15); - - x0 = XOR( x0,U8TO32_LITTLE((uint8_t*)data + 0)); - x1 = XOR( x1,U8TO32_LITTLE((uint8_t*)data + 4)); - x2 = XOR( x2,U8TO32_LITTLE((uint8_t*)data + 8)); - x3 = XOR( x3,U8TO32_LITTLE((uint8_t*)data + 12)); - x4 = XOR( x4,U8TO32_LITTLE((uint8_t*)data + 16)); - x5 = XOR( x5,U8TO32_LITTLE((uint8_t*)data + 20)); - x6 = XOR( x6,U8TO32_LITTLE((uint8_t*)data + 24)); - x7 = XOR( x7,U8TO32_LITTLE((uint8_t*)data + 28)); - x8 = XOR( x8,U8TO32_LITTLE((uint8_t*)data + 32)); - x9 = XOR( x9,U8TO32_LITTLE((uint8_t*)data + 36)); - x10 = XOR(x10,U8TO32_LITTLE((uint8_t*)data + 40)); - x11 = XOR(x11,U8TO32_LITTLE((uint8_t*)data + 44)); - x12 = XOR(x12,U8TO32_LITTLE((uint8_t*)data + 48)); - x13 = XOR(x13,U8TO32_LITTLE((uint8_t*)data + 52)); - x14 = XOR(x14,U8TO32_LITTLE((uint8_t*)data + 56)); - x15 = XOR(x15,U8TO32_LITTLE((uint8_t*)data + 60)); - - j12 = PLUSONE(j12); - if (!j12) - { - j13 = PLUSONE(j13); - /* stopping at 2^70 bytes per iv is user's responsibility */ - } - - U32TO8_LITTLE(cipher + 0,x0); - U32TO8_LITTLE(cipher + 4,x1); - U32TO8_LITTLE(cipher + 8,x2); - U32TO8_LITTLE(cipher + 12,x3); - U32TO8_LITTLE(cipher + 16,x4); - U32TO8_LITTLE(cipher + 20,x5); - U32TO8_LITTLE(cipher + 24,x6); - U32TO8_LITTLE(cipher + 28,x7); - U32TO8_LITTLE(cipher + 32,x8); - U32TO8_LITTLE(cipher + 36,x9); - U32TO8_LITTLE(cipher + 40,x10); - U32TO8_LITTLE(cipher + 44,x11); - U32TO8_LITTLE(cipher + 48,x12); - U32TO8_LITTLE(cipher + 52,x13); - U32TO8_LITTLE(cipher + 56,x14); - U32TO8_LITTLE(cipher + 60,x15); - - if (length <= 64) { - if (length < 64) { - memcpy(ctarget, cipher, length); - } - return; - } - length -= 64; - cipher += 64; - data = (uint8_t*)data + 64; - } -} diff --git a/src/Native/libcryptonote/crypto/chacha8.h b/src/Native/libcryptonote/crypto/chacha8.h index 80557e9f5..e4fe46799 100644 --- a/src/Native/libcryptonote/crypto/chacha8.h +++ b/src/Native/libcryptonote/crypto/chacha8.h @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2017, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once @@ -70,17 +44,13 @@ namespace crypto { chacha8(data, length, reinterpret_cast(&key), reinterpret_cast(&iv), cipher); } - inline void generate_chacha8_key(const void *data, size_t size, chacha8_key& key) { + inline void generate_chacha8_key(std::string password, chacha8_key& key) { static_assert(sizeof(chacha8_key) <= sizeof(hash), "Size of hash must be at least that of chacha8_key"); char pwd_hash[HASH_SIZE]; - crypto::cn_slow_hash(data, size, pwd_hash); + crypto::cn_slow_hash(password.data(), password.size(), pwd_hash); memcpy(&key, pwd_hash, sizeof(key)); memset(pwd_hash, 0, sizeof(pwd_hash)); } - - inline void generate_chacha8_key(std::string password, chacha8_key& key) { - return generate_chacha8_key(password.data(), password.size(), key); - } } #endif diff --git a/src/Native/libcryptonote/crypto/crypto-ops-data.c b/src/Native/libcryptonote/crypto/crypto-ops-data.c index 4ff4310de..48bfe21a2 100644 --- a/src/Native/libcryptonote/crypto/crypto-ops-data.c +++ b/src/Native/libcryptonote/crypto/crypto-ops-data.c @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #include @@ -870,4 +844,3 @@ const fe fe_fffb1 = {-31702527, -2466483, -26106795, -12203692, -12169197, -3210 const fe fe_fffb2 = {8166131, -6741800, -17040804, 3154616, 21461005, 1466302, -30876704, -6368709, 10503587, -13363080}; /* sqrt(2 * A * (A + 2)) */ const fe fe_fffb3 = {-13620103, 14639558, 4532995, 7679154, 16815101, -15883539, -22863840, -14813421, 13716513, -6477756}; /* sqrt(-sqrt(-1) * A * (A + 2)) */ const fe fe_fffb4 = {-21786234, -12173074, 21573800, 4524538, -4645904, 16204591, 8012863, -8444712, 3212926, 6885324}; /* sqrt(sqrt(-1) * A * (A + 2)) */ -const ge_p3 ge_p3_identity = { {0}, {1, 0}, {1, 0}, {0} }; diff --git a/src/Native/libcryptonote/crypto/crypto-ops.c b/src/Native/libcryptonote/crypto/crypto-ops.c index 45d412ac6..97e7df50e 100644 --- a/src/Native/libcryptonote/crypto/crypto-ops.c +++ b/src/Native/libcryptonote/crypto/crypto-ops.c @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include @@ -40,15 +14,17 @@ DISABLE_VS_WARNINGS(4146 4244) static void fe_mul(fe, const fe, const fe); static void fe_sq(fe, const fe); +static void fe_tobytes(unsigned char *, const fe); static void ge_madd(ge_p1p1 *, const ge_p3 *, const ge_precomp *); static void ge_msub(ge_p1p1 *, const ge_p3 *, const ge_precomp *); static void ge_p2_0(ge_p2 *); static void ge_p3_dbl(ge_p1p1 *, const ge_p3 *); +static void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *); static void fe_divpowm1(fe, const fe, const fe); /* Common functions */ -uint64_t load_3(const unsigned char *in) { +static uint64_t load_3(const unsigned char *in) { uint64_t result; result = (uint64_t) in[0]; result |= ((uint64_t) in[1]) << 8; @@ -56,7 +32,7 @@ uint64_t load_3(const unsigned char *in) { return result; } -uint64_t load_4(const unsigned char *in) +static uint64_t load_4(const unsigned char *in) { uint64_t result; result = (uint64_t) in[0]; @@ -118,7 +94,7 @@ Can overlap h with f or g. |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ -void fe_add(fe h, const fe f, const fe g) { +static void fe_add(fe h, const fe f, const fe g) { int32_t f0 = f[0]; int32_t f1 = f[1]; int32_t f2 = f[2]; @@ -256,7 +232,7 @@ static void fe_copy(fe h, const fe f) { /* From fe_invert.c */ -void fe_invert(fe out, const fe z) { +static void fe_invert(fe out, const fe z) { fe t0; fe t1; fe t2; @@ -1029,7 +1005,7 @@ Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q. */ -void fe_tobytes(unsigned char *s, const fe h) { +static void fe_tobytes(unsigned char *s, const fe h) { int32_t h0 = h[0]; int32_t h1 = h[1]; int32_t h2 = h[2]; @@ -1234,51 +1210,6 @@ void ge_double_scalarmult_base_vartime(ge_p2 *r, const unsigned char *a, const g } } -void ge_double_scalarmult_base_vartime_p3(ge_p3 *r3, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { - signed char aslide[256]; - signed char bslide[256]; - ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ - ge_p1p1 t; - ge_p3 u; - ge_p2 r; - int i; - - slide(aslide, a); - slide(bslide, b); - ge_dsm_precomp(Ai, A); - - ge_p2_0(&r); - - for (i = 255; i >= 0; --i) { - if (aslide[i] || bslide[i]) break; - } - - for (; i >= 0; --i) { - ge_p2_dbl(&t, &r); - - if (aslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Ai[aslide[i]/2]); - } else if (aslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Ai[(-aslide[i])/2]); - } - - if (bslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_madd(&t, &u, &ge_Bi[bslide[i]/2]); - } else if (bslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_msub(&t, &u, &ge_Bi[(-bslide[i])/2]); - } - - if (i == 0) - ge_p1p1_to_p3(r3, &t); - else - ge_p1p1_to_p2(&r, &t); - } -} - /* From ge_frombytes.c, modified */ int ge_frombytes_vartime(ge_p3 *h, const unsigned char *s) { @@ -1634,7 +1565,7 @@ void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) { r = p - q */ -void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { +static void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { fe t0; fe_add(r->X, p->Y, p->X); fe_sub(r->Y, p->Y, p->X); @@ -2045,79 +1976,17 @@ void ge_scalarmult(ge_p2 *r, const unsigned char *a, const ge_p3 *A) { } } -void ge_scalarmult_p3(ge_p3 *r3, const unsigned char *a, const ge_p3 *A) { - signed char e[64]; - int carry, carry2, i; - ge_cached Ai[8]; /* 1 * A, 2 * A, ..., 8 * A */ - ge_p1p1 t; - ge_p3 u; - ge_p2 r; - - carry = 0; /* 0..1 */ - for (i = 0; i < 31; i++) { - carry += a[i]; /* 0..256 */ - carry2 = (carry + 8) >> 4; /* 0..16 */ - e[2 * i] = carry - (carry2 << 4); /* -8..7 */ - carry = (carry2 + 8) >> 4; /* 0..1 */ - e[2 * i + 1] = carry2 - (carry << 4); /* -8..7 */ - } - carry += a[31]; /* 0..128 */ - carry2 = (carry + 8) >> 4; /* 0..8 */ - e[62] = carry - (carry2 << 4); /* -8..7 */ - e[63] = carry2; /* 0..8 */ - - ge_p3_to_cached(&Ai[0], A); - for (i = 0; i < 7; i++) { - ge_add(&t, A, &Ai[i]); - ge_p1p1_to_p3(&u, &t); - ge_p3_to_cached(&Ai[i + 1], &u); - } - - ge_p2_0(&r); - for (i = 63; i >= 0; i--) { - signed char b = e[i]; - unsigned char bnegative = negative(b); - unsigned char babs = b - (((-bnegative) & b) << 1); - ge_cached cur, minuscur; - ge_p2_dbl(&t, &r); - ge_p1p1_to_p2(&r, &t); - ge_p2_dbl(&t, &r); - ge_p1p1_to_p2(&r, &t); - ge_p2_dbl(&t, &r); - ge_p1p1_to_p2(&r, &t); - ge_p2_dbl(&t, &r); - ge_p1p1_to_p3(&u, &t); - ge_cached_0(&cur); - ge_cached_cmov(&cur, &Ai[0], equal(babs, 1)); - ge_cached_cmov(&cur, &Ai[1], equal(babs, 2)); - ge_cached_cmov(&cur, &Ai[2], equal(babs, 3)); - ge_cached_cmov(&cur, &Ai[3], equal(babs, 4)); - ge_cached_cmov(&cur, &Ai[4], equal(babs, 5)); - ge_cached_cmov(&cur, &Ai[5], equal(babs, 6)); - ge_cached_cmov(&cur, &Ai[6], equal(babs, 7)); - ge_cached_cmov(&cur, &Ai[7], equal(babs, 8)); - fe_copy(minuscur.YplusX, cur.YminusX); - fe_copy(minuscur.YminusX, cur.YplusX); - fe_copy(minuscur.Z, cur.Z); - fe_neg(minuscur.T2d, cur.T2d); - ge_cached_cmov(&cur, &minuscur, bnegative); - ge_add(&t, &u, &cur); - if (i == 0) - ge_p1p1_to_p3(r3, &t); - else - ge_p1p1_to_p2(&r, &t); - } -} - -void ge_double_scalarmult_precomp_vartime2(ge_p2 *r, const unsigned char *a, const ge_dsmp Ai, const unsigned char *b, const ge_dsmp Bi) { +void ge_double_scalarmult_precomp_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b, const ge_dsmp Bi) { signed char aslide[256]; signed char bslide[256]; + ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ ge_p1p1 t; ge_p3 u; int i; slide(aslide, a); slide(bslide, b); + ge_dsm_precomp(Ai, A); ge_p2_0(r); @@ -2148,56 +2017,6 @@ void ge_double_scalarmult_precomp_vartime2(ge_p2 *r, const unsigned char *a, con } } -void ge_double_scalarmult_precomp_vartime2_p3(ge_p3 *r3, const unsigned char *a, const ge_dsmp Ai, const unsigned char *b, const ge_dsmp Bi) { - signed char aslide[256]; - signed char bslide[256]; - ge_p1p1 t; - ge_p3 u; - ge_p2 r; - int i; - - slide(aslide, a); - slide(bslide, b); - - ge_p2_0(&r); - - for (i = 255; i >= 0; --i) { - if (aslide[i] || bslide[i]) break; - } - - for (; i >= 0; --i) { - ge_p2_dbl(&t, &r); - - if (aslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Ai[aslide[i]/2]); - } else if (aslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Ai[(-aslide[i])/2]); - } - - if (bslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Bi[bslide[i]/2]); - } else if (bslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Bi[(-bslide[i])/2]); - } - - if (i == 0) - ge_p1p1_to_p3(r3, &t); - else - ge_p1p1_to_p2(&r, &t); - } -} - -void ge_double_scalarmult_precomp_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b, const ge_dsmp Bi) { - ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ - - ge_dsm_precomp(Ai, A); - ge_double_scalarmult_precomp_vartime2(r, a, Ai, b, Bi); -} - void ge_mul8(ge_p1p1 *r, const ge_p2 *t) { ge_p2 u; ge_p2_dbl(r, t); @@ -3055,658 +2874,6 @@ void sc_mulsub(unsigned char *s, const unsigned char *a, const unsigned char *b, s[31] = s11 >> 17; } -//copied from above and modified -/* -Input: - a[0]+256*a[1]+...+256^31*a[31] = a - b[0]+256*b[1]+...+256^31*b[31] = b - -Output: - s[0]+256*s[1]+...+256^31*s[31] = (ab) mod l - where l = 2^252 + 27742317777372353535851937790883648493. -*/ -void sc_mul(unsigned char *s, const unsigned char *a, const unsigned char *b) { - int64_t a0 = 2097151 & load_3(a); - int64_t a1 = 2097151 & (load_4(a + 2) >> 5); - int64_t a2 = 2097151 & (load_3(a + 5) >> 2); - int64_t a3 = 2097151 & (load_4(a + 7) >> 7); - int64_t a4 = 2097151 & (load_4(a + 10) >> 4); - int64_t a5 = 2097151 & (load_3(a + 13) >> 1); - int64_t a6 = 2097151 & (load_4(a + 15) >> 6); - int64_t a7 = 2097151 & (load_3(a + 18) >> 3); - int64_t a8 = 2097151 & load_3(a + 21); - int64_t a9 = 2097151 & (load_4(a + 23) >> 5); - int64_t a10 = 2097151 & (load_3(a + 26) >> 2); - int64_t a11 = (load_4(a + 28) >> 7); - int64_t b0 = 2097151 & load_3(b); - int64_t b1 = 2097151 & (load_4(b + 2) >> 5); - int64_t b2 = 2097151 & (load_3(b + 5) >> 2); - int64_t b3 = 2097151 & (load_4(b + 7) >> 7); - int64_t b4 = 2097151 & (load_4(b + 10) >> 4); - int64_t b5 = 2097151 & (load_3(b + 13) >> 1); - int64_t b6 = 2097151 & (load_4(b + 15) >> 6); - int64_t b7 = 2097151 & (load_3(b + 18) >> 3); - int64_t b8 = 2097151 & load_3(b + 21); - int64_t b9 = 2097151 & (load_4(b + 23) >> 5); - int64_t b10 = 2097151 & (load_3(b + 26) >> 2); - int64_t b11 = (load_4(b + 28) >> 7); - int64_t s0; - int64_t s1; - int64_t s2; - int64_t s3; - int64_t s4; - int64_t s5; - int64_t s6; - int64_t s7; - int64_t s8; - int64_t s9; - int64_t s10; - int64_t s11; - int64_t s12; - int64_t s13; - int64_t s14; - int64_t s15; - int64_t s16; - int64_t s17; - int64_t s18; - int64_t s19; - int64_t s20; - int64_t s21; - int64_t s22; - int64_t s23; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - int64_t carry12; - int64_t carry13; - int64_t carry14; - int64_t carry15; - int64_t carry16; - int64_t carry17; - int64_t carry18; - int64_t carry19; - int64_t carry20; - int64_t carry21; - int64_t carry22; - - s0 = a0*b0; - s1 = (a0*b1 + a1*b0); - s2 = (a0*b2 + a1*b1 + a2*b0); - s3 = (a0*b3 + a1*b2 + a2*b1 + a3*b0); - s4 = (a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0); - s5 = (a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0); - s6 = (a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0); - s7 = (a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0); - s8 = (a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0); - s9 = (a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0); - s10 = (a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0); - s11 = (a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0); - s12 = (a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1); - s13 = (a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2); - s14 = (a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3); - s15 = (a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4); - s16 = (a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5); - s17 = (a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6); - s18 = (a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7); - s19 = (a8*b11 + a9*b10 + a10*b9 + a11*b8); - s20 = (a9*b11 + a10*b10 + a11*b9); - s21 = (a10*b11 + a11*b10); - s22 = a11*b11; - s23 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21; - carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21; - carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21; - carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21; - carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21; - - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -//copied from above and modified -/* -Input: - a[0]+256*a[1]+...+256^31*a[31] = a - b[0]+256*b[1]+...+256^31*b[31] = b - c[0]+256*c[1]+...+256^31*c[31] = c - -Output: - s[0]+256*s[1]+...+256^31*s[31] = (c+ab) mod l - where l = 2^252 + 27742317777372353535851937790883648493. -*/ - -void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) { - int64_t a0 = 2097151 & load_3(a); - int64_t a1 = 2097151 & (load_4(a + 2) >> 5); - int64_t a2 = 2097151 & (load_3(a + 5) >> 2); - int64_t a3 = 2097151 & (load_4(a + 7) >> 7); - int64_t a4 = 2097151 & (load_4(a + 10) >> 4); - int64_t a5 = 2097151 & (load_3(a + 13) >> 1); - int64_t a6 = 2097151 & (load_4(a + 15) >> 6); - int64_t a7 = 2097151 & (load_3(a + 18) >> 3); - int64_t a8 = 2097151 & load_3(a + 21); - int64_t a9 = 2097151 & (load_4(a + 23) >> 5); - int64_t a10 = 2097151 & (load_3(a + 26) >> 2); - int64_t a11 = (load_4(a + 28) >> 7); - int64_t b0 = 2097151 & load_3(b); - int64_t b1 = 2097151 & (load_4(b + 2) >> 5); - int64_t b2 = 2097151 & (load_3(b + 5) >> 2); - int64_t b3 = 2097151 & (load_4(b + 7) >> 7); - int64_t b4 = 2097151 & (load_4(b + 10) >> 4); - int64_t b5 = 2097151 & (load_3(b + 13) >> 1); - int64_t b6 = 2097151 & (load_4(b + 15) >> 6); - int64_t b7 = 2097151 & (load_3(b + 18) >> 3); - int64_t b8 = 2097151 & load_3(b + 21); - int64_t b9 = 2097151 & (load_4(b + 23) >> 5); - int64_t b10 = 2097151 & (load_3(b + 26) >> 2); - int64_t b11 = (load_4(b + 28) >> 7); - int64_t c0 = 2097151 & load_3(c); - int64_t c1 = 2097151 & (load_4(c + 2) >> 5); - int64_t c2 = 2097151 & (load_3(c + 5) >> 2); - int64_t c3 = 2097151 & (load_4(c + 7) >> 7); - int64_t c4 = 2097151 & (load_4(c + 10) >> 4); - int64_t c5 = 2097151 & (load_3(c + 13) >> 1); - int64_t c6 = 2097151 & (load_4(c + 15) >> 6); - int64_t c7 = 2097151 & (load_3(c + 18) >> 3); - int64_t c8 = 2097151 & load_3(c + 21); - int64_t c9 = 2097151 & (load_4(c + 23) >> 5); - int64_t c10 = 2097151 & (load_3(c + 26) >> 2); - int64_t c11 = (load_4(c + 28) >> 7); - int64_t s0; - int64_t s1; - int64_t s2; - int64_t s3; - int64_t s4; - int64_t s5; - int64_t s6; - int64_t s7; - int64_t s8; - int64_t s9; - int64_t s10; - int64_t s11; - int64_t s12; - int64_t s13; - int64_t s14; - int64_t s15; - int64_t s16; - int64_t s17; - int64_t s18; - int64_t s19; - int64_t s20; - int64_t s21; - int64_t s22; - int64_t s23; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - int64_t carry12; - int64_t carry13; - int64_t carry14; - int64_t carry15; - int64_t carry16; - int64_t carry17; - int64_t carry18; - int64_t carry19; - int64_t carry20; - int64_t carry21; - int64_t carry22; - - s0 = c0 + a0*b0; - s1 = c1 + (a0*b1 + a1*b0); - s2 = c2 + (a0*b2 + a1*b1 + a2*b0); - s3 = c3 + (a0*b3 + a1*b2 + a2*b1 + a3*b0); - s4 = c4 + (a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0); - s5 = c5 + (a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0); - s6 = c6 + (a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0); - s7 = c7 + (a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0); - s8 = c8 + (a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0); - s9 = c9 + (a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0); - s10 = c10 + (a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0); - s11 = c11 + (a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0); - s12 = (a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1); - s13 = (a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2); - s14 = (a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3); - s15 = (a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4); - s16 = (a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5); - s17 = (a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6); - s18 = (a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7); - s19 = (a8*b11 + a9*b10 + a10*b9 + a11*b8); - s20 = (a9*b11 + a10*b10 + a11*b9); - s21 = (a10*b11 + a11*b10); - s22 = a11*b11; - s23 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21; - carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21; - carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21; - carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21; - carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21; - - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - /* Assumes that a != INT64_MIN */ static int64_t signum(int64_t a) { return (a >> 63) - ((-a) >> 63); diff --git a/src/Native/libcryptonote/crypto/crypto-ops.h b/src/Native/libcryptonote/crypto/crypto-ops.h index dc3c60794..9d07fc8b0 100644 --- a/src/Native/libcryptonote/crypto/crypto-ops.h +++ b/src/Native/libcryptonote/crypto/crypto-ops.h @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once @@ -79,7 +53,6 @@ typedef ge_cached ge_dsmp[8]; extern const ge_precomp ge_Bi[8]; void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s); void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *); -void ge_double_scalarmult_base_vartime_p3(ge_p3 *, const unsigned char *, const ge_p3 *, const unsigned char *); /* From ge_frombytes.c, modified */ @@ -128,10 +101,7 @@ void sc_reduce(unsigned char *); /* New code */ void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *); -void ge_scalarmult_p3(ge_p3 *, const unsigned char *, const ge_p3 *); void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp); -void ge_double_scalarmult_precomp_vartime2(ge_p2 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp); -void ge_double_scalarmult_precomp_vartime2_p3(ge_p3 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp); void ge_mul8(ge_p1p1 *, const ge_p2 *); extern const fe fe_ma2; extern const fe fe_ma; @@ -139,22 +109,11 @@ extern const fe fe_fffb1; extern const fe fe_fffb2; extern const fe fe_fffb3; extern const fe fe_fffb4; -extern const ge_p3 ge_p3_identity; void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *); void sc_0(unsigned char *); void sc_reduce32(unsigned char *); void sc_add(unsigned char *, const unsigned char *, const unsigned char *); void sc_sub(unsigned char *, const unsigned char *, const unsigned char *); void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *); -void sc_mul(unsigned char *, const unsigned char *, const unsigned char *); -void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); int sc_check(const unsigned char *); int sc_isnonzero(const unsigned char *); /* Doesn't normalize */ - -// internal -uint64_t load_3(const unsigned char *in); -uint64_t load_4(const unsigned char *in); -void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); -void fe_add(fe h, const fe f, const fe g); -void fe_tobytes(unsigned char *, const fe); -void fe_invert(fe out, const fe z); diff --git a/src/Native/libcryptonote/crypto/crypto.cpp b/src/Native/libcryptonote/crypto/crypto.cpp index 105b00c18..a52d45ff0 100644 --- a/src/Native/libcryptonote/crypto/crypto.cpp +++ b/src/Native/libcryptonote/crypto/crypto.cpp @@ -1,32 +1,12 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if !defined(WIN32) +#include +#else +#include +#endif #include #include @@ -34,32 +14,20 @@ #include #include #include -#include -#include -#include +#include #include "common/varint.h" #include "warnings.h" #include "crypto.h" #include "hash.h" -namespace { - static void local_abort(const char *msg) - { - fprintf(stderr, "%s\n", msg); -#ifdef NDEBUG - _exit(1); -#else - abort(); -#endif - } -} - namespace crypto { using std::abort; using std::int32_t; using std::int64_t; + using std::lock_guard; + using std::mutex; using std::size_t; using std::uint32_t; using std::uint64_t; @@ -69,7 +37,7 @@ namespace crypto { #include "random.h" } - boost::mutex random_lock; + mutex random_lock; static inline unsigned char *operator &(ec_point &point) { return &reinterpret_cast(point); @@ -87,490 +55,8 @@ namespace crypto { return &reinterpret_cast(scalar); } - /* generate a random 32-byte (256-bit) integer and copy it to res */ - static inline void random_scalar_not_thread_safe(ec_scalar &res) { - unsigned char tmp[64]; - generate_random_bytes_not_thread_safe(64, tmp); - sc_reduce(tmp); - memcpy(&res, tmp, 32); - } - static inline void random_scalar(ec_scalar &res) { - boost::lock_guard lock(random_lock); - random_scalar_not_thread_safe(res); - } - - void hash_to_scalar(const void *data, size_t length, ec_scalar &res) { - cn_fast_hash(data, length, reinterpret_cast(res)); - sc_reduce32(&res); - } - - /* - * generate public and secret keys from a random 256-bit integer - * TODO: allow specifying random value (for wallet recovery) - * - */ - secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) { - ge_p3 point; - - secret_key rng; - - if (recover) - { - rng = recovery_key; - } - else - { - random_scalar(rng); - } - sec = rng; - sc_reduce32(&sec); // reduce in case second round of keys (sendkeys) - - ge_scalarmult_base(&point, &sec); - ge_p3_tobytes(&pub, &point); - - return rng; - } - bool crypto_ops::check_key(const public_key &key) { ge_p3 point; return ge_frombytes_vartime(&point, &key) == 0; } - - bool crypto_ops::secret_key_to_public_key(const secret_key &sec, public_key &pub) { - ge_p3 point; - if (sc_check(&sec) != 0) { - return false; - } - ge_scalarmult_base(&point, &sec); - ge_p3_tobytes(&pub, &point); - return true; - } - - bool crypto_ops::generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) { - ge_p3 point; - ge_p2 point2; - ge_p1p1 point3; - assert(sc_check(&key2) == 0); - if (ge_frombytes_vartime(&point, &key1) != 0) { - return false; - } - ge_scalarmult(&point2, &key2, &point); - ge_mul8(&point3, &point2); - ge_p1p1_to_p2(&point2, &point3); - ge_tobytes(&derivation, &point2); - return true; - } - - void crypto_ops::derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) { - struct { - key_derivation derivation; - char output_index[(sizeof(size_t) * 8 + 6) / 7]; - } buf; - char *end = buf.output_index; - buf.derivation = derivation; - tools::write_varint(end, output_index); - assert(end <= buf.output_index + sizeof buf.output_index); - hash_to_scalar(&buf, end - reinterpret_cast(&buf), res); - } - - bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index, - const public_key &base, public_key &derived_key) { - ec_scalar scalar; - ge_p3 point1; - ge_p3 point2; - ge_cached point3; - ge_p1p1 point4; - ge_p2 point5; - if (ge_frombytes_vartime(&point1, &base) != 0) { - return false; - } - derivation_to_scalar(derivation, output_index, scalar); - ge_scalarmult_base(&point2, &scalar); - ge_p3_to_cached(&point3, &point2); - ge_add(&point4, &point1, &point3); - ge_p1p1_to_p2(&point5, &point4); - ge_tobytes(&derived_key, &point5); - return true; - } - - void crypto_ops::derive_secret_key(const key_derivation &derivation, size_t output_index, - const secret_key &base, secret_key &derived_key) { - ec_scalar scalar; - assert(sc_check(&base) == 0); - derivation_to_scalar(derivation, output_index, scalar); - sc_add(&derived_key, &base, &scalar); - } - - bool crypto_ops::derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &derived_key) { - ec_scalar scalar; - ge_p3 point1; - ge_p3 point2; - ge_cached point3; - ge_p1p1 point4; - ge_p2 point5; - if (ge_frombytes_vartime(&point1, &out_key) != 0) { - return false; - } - derivation_to_scalar(derivation, output_index, scalar); - ge_scalarmult_base(&point2, &scalar); - ge_p3_to_cached(&point3, &point2); - ge_sub(&point4, &point1, &point3); - ge_p1p1_to_p2(&point5, &point4); - ge_tobytes(&derived_key, &point5); - return true; - } - - struct s_comm { - hash h; - ec_point key; - ec_point comm; - }; - - struct s_comm_2 { - hash msg; - ec_point D; - ec_point X; - ec_point Y; - }; - - void crypto_ops::generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) { - ge_p3 tmp3; - ec_scalar k; - s_comm buf; -#if !defined(NDEBUG) - { - ge_p3 t; - public_key t2; - assert(sc_check(&sec) == 0); - ge_scalarmult_base(&t, &sec); - ge_p3_tobytes(&t2, &t); - assert(pub == t2); - } -#endif - buf.h = prefix_hash; - buf.key = pub; - random_scalar(k); - ge_scalarmult_base(&tmp3, &k); - ge_p3_tobytes(&buf.comm, &tmp3); - hash_to_scalar(&buf, sizeof(s_comm), sig.c); - sc_mulsub(&sig.r, &sig.c, &sec, &k); - } - - bool crypto_ops::check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) { - ge_p2 tmp2; - ge_p3 tmp3; - ec_scalar c; - s_comm buf; - assert(check_key(pub)); - buf.h = prefix_hash; - buf.key = pub; - if (ge_frombytes_vartime(&tmp3, &pub) != 0) { - return false; - } - if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0) { - return false; - } - ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r); - ge_tobytes(&buf.comm, &tmp2); - hash_to_scalar(&buf, sizeof(s_comm), c); - sc_sub(&c, &c, &sig.c); - return sc_isnonzero(&c) == 0; - } - - void crypto_ops::generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional &B, const public_key &D, const secret_key &r, signature &sig) { - // sanity check - ge_p3 R_p3; - ge_p3 A_p3; - ge_p3 B_p3; - ge_p3 D_p3; - if (ge_frombytes_vartime(&R_p3, &R) != 0) throw std::runtime_error("tx pubkey is invalid"); - if (ge_frombytes_vartime(&A_p3, &A) != 0) throw std::runtime_error("recipient view pubkey is invalid"); - if (B && ge_frombytes_vartime(&B_p3, &*B) != 0) throw std::runtime_error("recipient spend pubkey is invalid"); - if (ge_frombytes_vartime(&D_p3, &D) != 0) throw std::runtime_error("key derivation is invalid"); -#if !defined(NDEBUG) - { - assert(sc_check(&r) == 0); - // check R == r*G or R == r*B - public_key dbg_R; - if (B) - { - ge_p2 dbg_R_p2; - ge_scalarmult(&dbg_R_p2, &r, &B_p3); - ge_tobytes(&dbg_R, &dbg_R_p2); - } - else - { - ge_p3 dbg_R_p3; - ge_scalarmult_base(&dbg_R_p3, &r); - ge_p3_tobytes(&dbg_R, &dbg_R_p3); - } - assert(R == dbg_R); - // check D == r*A - ge_p2 dbg_D_p2; - ge_scalarmult(&dbg_D_p2, &r, &A_p3); - public_key dbg_D; - ge_tobytes(&dbg_D, &dbg_D_p2); - assert(D == dbg_D); - } -#endif - - // pick random k - ec_scalar k; - random_scalar(k); - - s_comm_2 buf; - buf.msg = prefix_hash; - buf.D = D; - - if (B) - { - // compute X = k*B - ge_p2 X_p2; - ge_scalarmult(&X_p2, &k, &B_p3); - ge_tobytes(&buf.X, &X_p2); - } - else - { - // compute X = k*G - ge_p3 X_p3; - ge_scalarmult_base(&X_p3, &k); - ge_p3_tobytes(&buf.X, &X_p3); - } - - // compute Y = k*A - ge_p2 Y_p2; - ge_scalarmult(&Y_p2, &k, &A_p3); - ge_tobytes(&buf.Y, &Y_p2); - - // sig.c = Hs(Msg || D || X || Y) - hash_to_scalar(&buf, sizeof(buf), sig.c); - - // sig.r = k - sig.c*r - sc_mulsub(&sig.r, &sig.c, &r, &k); - } - - bool crypto_ops::check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional &B, const public_key &D, const signature &sig) { - // sanity check - ge_p3 R_p3; - ge_p3 A_p3; - ge_p3 B_p3; - ge_p3 D_p3; - if (ge_frombytes_vartime(&R_p3, &R) != 0) return false; - if (ge_frombytes_vartime(&A_p3, &A) != 0) return false; - if (B && ge_frombytes_vartime(&B_p3, &*B) != 0) return false; - if (ge_frombytes_vartime(&D_p3, &D) != 0) return false; - if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0) return false; - - // compute sig.c*R - ge_p3 cR_p3; - { - ge_p2 cR_p2; - ge_scalarmult(&cR_p2, &sig.c, &R_p3); - public_key cR; - ge_tobytes(&cR, &cR_p2); - if (ge_frombytes_vartime(&cR_p3, &cR) != 0) return false; - } - - ge_p1p1 X_p1p1; - if (B) - { - // compute X = sig.c*R + sig.r*B - ge_p2 rB_p2; - ge_scalarmult(&rB_p2, &sig.r, &B_p3); - public_key rB; - ge_tobytes(&rB, &rB_p2); - ge_p3 rB_p3; - if (ge_frombytes_vartime(&rB_p3, &rB) != 0) return false; - ge_cached rB_cached; - ge_p3_to_cached(&rB_cached, &rB_p3); - ge_add(&X_p1p1, &cR_p3, &rB_cached); - } - else - { - // compute X = sig.c*R + sig.r*G - ge_p3 rG_p3; - ge_scalarmult_base(&rG_p3, &sig.r); - ge_cached rG_cached; - ge_p3_to_cached(&rG_cached, &rG_p3); - ge_add(&X_p1p1, &cR_p3, &rG_cached); - } - ge_p2 X_p2; - ge_p1p1_to_p2(&X_p2, &X_p1p1); - - // compute sig.c*D - ge_p2 cD_p2; - ge_scalarmult(&cD_p2, &sig.c, &D_p3); - - // compute sig.r*A - ge_p2 rA_p2; - ge_scalarmult(&rA_p2, &sig.r, &A_p3); - - // compute Y = sig.c*D + sig.r*A - public_key cD; - public_key rA; - ge_tobytes(&cD, &cD_p2); - ge_tobytes(&rA, &rA_p2); - ge_p3 cD_p3; - ge_p3 rA_p3; - if (ge_frombytes_vartime(&cD_p3, &cD) != 0) return false; - if (ge_frombytes_vartime(&rA_p3, &rA) != 0) return false; - ge_cached rA_cached; - ge_p3_to_cached(&rA_cached, &rA_p3); - ge_p1p1 Y_p1p1; - ge_add(&Y_p1p1, &cD_p3, &rA_cached); - ge_p2 Y_p2; - ge_p1p1_to_p2(&Y_p2, &Y_p1p1); - - // compute c2 = Hs(Msg || D || X || Y) - s_comm_2 buf; - buf.msg = prefix_hash; - buf.D = D; - ge_tobytes(&buf.X, &X_p2); - ge_tobytes(&buf.Y, &Y_p2); - ec_scalar c2; - hash_to_scalar(&buf, sizeof(s_comm_2), c2); - - // test if c2 == sig.c - sc_sub(&c2, &c2, &sig.c); - return sc_isnonzero(&c2) == 0; - } - - static void hash_to_ec(const public_key &key, ge_p3 &res) { - hash h; - ge_p2 point; - ge_p1p1 point2; - cn_fast_hash(std::addressof(key), sizeof(public_key), h); - ge_fromfe_frombytes_vartime(&point, reinterpret_cast(&h)); - ge_mul8(&point2, &point); - ge_p1p1_to_p3(&res, &point2); - } - - void crypto_ops::generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) { - ge_p3 point; - ge_p2 point2; - assert(sc_check(&sec) == 0); - hash_to_ec(pub, point); - ge_scalarmult(&point2, &sec, &point); - ge_tobytes(&image, &point2); - } - -PUSH_WARNINGS -DISABLE_VS_WARNINGS(4200) - struct ec_point_pair { - ec_point a, b; - }; - struct rs_comm { - hash h; - struct ec_point_pair ab[]; - }; -POP_WARNINGS - - static inline size_t rs_comm_size(size_t pubs_count) { - return sizeof(rs_comm) + pubs_count * sizeof(ec_point_pair); - } - - void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image, - const public_key *const *pubs, size_t pubs_count, - const secret_key &sec, size_t sec_index, - signature *sig) { - size_t i; - ge_p3 image_unp; - ge_dsmp image_pre; - ec_scalar sum, k, h; - boost::shared_ptr buf(reinterpret_cast(malloc(rs_comm_size(pubs_count))), free); - if (!buf) - local_abort("malloc failure"); - assert(sec_index < pubs_count); -#if !defined(NDEBUG) - { - ge_p3 t; - public_key t2; - key_image t3; - assert(sc_check(&sec) == 0); - ge_scalarmult_base(&t, &sec); - ge_p3_tobytes(&t2, &t); - assert(*pubs[sec_index] == t2); - generate_key_image(*pubs[sec_index], sec, t3); - assert(image == t3); - for (i = 0; i < pubs_count; i++) { - assert(check_key(*pubs[i])); - } - } -#endif - if (ge_frombytes_vartime(&image_unp, &image) != 0) { - local_abort("invalid key image"); - } - ge_dsm_precomp(image_pre, &image_unp); - sc_0(&sum); - buf->h = prefix_hash; - for (i = 0; i < pubs_count; i++) { - ge_p2 tmp2; - ge_p3 tmp3; - if (i == sec_index) { - random_scalar(k); - ge_scalarmult_base(&tmp3, &k); - ge_p3_tobytes(&buf->ab[i].a, &tmp3); - hash_to_ec(*pubs[i], tmp3); - ge_scalarmult(&tmp2, &k, &tmp3); - ge_tobytes(&buf->ab[i].b, &tmp2); - } else { - random_scalar(sig[i].c); - random_scalar(sig[i].r); - if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { - local_abort("invalid pubkey"); - } - ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); - ge_tobytes(&buf->ab[i].a, &tmp2); - hash_to_ec(*pubs[i], tmp3); - ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); - ge_tobytes(&buf->ab[i].b, &tmp2); - sc_add(&sum, &sum, &sig[i].c); - } - } - hash_to_scalar(buf.get(), rs_comm_size(pubs_count), h); - sc_sub(&sig[sec_index].c, &h, &sum); - sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &sec, &k); - } - - bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image, - const public_key *const *pubs, size_t pubs_count, - const signature *sig) { - size_t i; - ge_p3 image_unp; - ge_dsmp image_pre; - ec_scalar sum, h; - boost::shared_ptr buf(reinterpret_cast(malloc(rs_comm_size(pubs_count))), free); - if (!buf) - return false; -#if !defined(NDEBUG) - for (i = 0; i < pubs_count; i++) { - assert(check_key(*pubs[i])); - } -#endif - if (ge_frombytes_vartime(&image_unp, &image) != 0) { - return false; - } - ge_dsm_precomp(image_pre, &image_unp); - sc_0(&sum); - buf->h = prefix_hash; - for (i = 0; i < pubs_count; i++) { - ge_p2 tmp2; - ge_p3 tmp3; - if (sc_check(&sig[i].c) != 0 || sc_check(&sig[i].r) != 0) { - return false; - } - if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { - return false; - } - ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); - ge_tobytes(&buf->ab[i].a, &tmp2); - hash_to_ec(*pubs[i], tmp3); - ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); - ge_tobytes(&buf->ab[i].b, &tmp2); - sc_add(&sum, &sum, &sig[i].c); - } - hash_to_scalar(buf.get(), rs_comm_size(pubs_count), h); - sc_sub(&h, &h, &sum); - return sc_isnonzero(&h) == 0; - } } diff --git a/src/Native/libcryptonote/crypto/crypto.h b/src/Native/libcryptonote/crypto/crypto.h index 81ebfb9e2..300f5af5a 100644 --- a/src/Native/libcryptonote/crypto/crypto.h +++ b/src/Native/libcryptonote/crypto/crypto.h @@ -1,50 +1,15 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once #include -#include -#include -#include -#include -#include -#include +#include #include #include "common/pod-class.h" -#include "common/util.h" -#include "memwipe.h" #include "generic-ops.h" -#include "hex.h" -#include "span.h" #include "hash.h" namespace crypto { @@ -53,7 +18,7 @@ namespace crypto { #include "random.h" } - extern boost::mutex random_lock; + extern std::mutex random_lock; #pragma pack(push, 1) POD_CLASS ec_point { @@ -68,22 +33,8 @@ namespace crypto { friend class crypto_ops; }; - using secret_key = tools::scrubbed; - - POD_CLASS public_keyV { - std::vector keys; - int rows; - }; - - POD_CLASS secret_keyV { - std::vector keys; - int rows; - }; - - POD_CLASS public_keyM { - int cols; - int rows; - std::vector column_vectors; + POD_CLASS secret_key: ec_scalar { + friend class crypto_ops; }; POD_CLASS key_derivation: ec_point { @@ -98,14 +49,16 @@ namespace crypto { ec_scalar c, r; friend class crypto_ops; }; -#pragma pack(pop) - void hash_to_scalar(const void *data, size_t length, ec_scalar &res); + POD_CLASS view_tag { + char data; + }; +#pragma pack(pop) static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 && sizeof(public_key) == 32 && sizeof(secret_key) == 32 && sizeof(key_derivation) == 32 && sizeof(key_image) == 32 && - sizeof(signature) == 64, "Invalid structure size"); + sizeof(signature) == 64 && sizeof(view_tag) == 1, "Invalid structure size"); class crypto_ops { crypto_ops(); @@ -113,177 +66,28 @@ namespace crypto { void operator=(const crypto_ops &); ~crypto_ops(); - static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false); - friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover); static bool check_key(const public_key &); friend bool check_key(const public_key &); - static bool secret_key_to_public_key(const secret_key &, public_key &); - friend bool secret_key_to_public_key(const secret_key &, public_key &); - static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); - friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); - static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res); - friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res); - static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); - friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); - static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); - friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); - static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &); - friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &); - static void generate_signature(const hash &, const public_key &, const secret_key &, signature &); - friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &); - static bool check_signature(const hash &, const public_key &, const signature &); - friend bool check_signature(const hash &, const public_key &, const signature &); - static void generate_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional &, const public_key &, const secret_key &, signature &); - friend void generate_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional &, const public_key &, const secret_key &, signature &); - static bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional &, const public_key &, const signature &); - friend bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional &, const public_key &, const signature &); - static void generate_key_image(const public_key &, const secret_key &, key_image &); - friend void generate_key_image(const public_key &, const secret_key &, key_image &); - static void generate_ring_signature(const hash &, const key_image &, - const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *); - friend void generate_ring_signature(const hash &, const key_image &, - const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *); - static bool check_ring_signature(const hash &, const key_image &, - const public_key *const *, std::size_t, const signature *); - friend bool check_ring_signature(const hash &, const key_image &, - const public_key *const *, std::size_t, const signature *); }; - /* Generate N random bytes - */ - inline void rand(size_t N, uint8_t *bytes) { - boost::lock_guard lock(random_lock); - generate_random_bytes_not_thread_safe(N, bytes); - } - /* Generate a value filled with random bytes. */ template typename std::enable_if::value, T>::type rand() { typename std::remove_cv::type res; - boost::lock_guard lock(random_lock); - generate_random_bytes_not_thread_safe(sizeof(T), &res); + std::lock_guard lock(random_lock); + generate_random_bytes(sizeof(T), &res); return res; } - /* Generate a new key pair - */ - inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) { - return crypto_ops::generate_keys(pub, sec, recovery_key, recover); - } - /* Check a public key. Returns true if it is valid, false otherwise. */ inline bool check_key(const public_key &key) { return crypto_ops::check_key(key); } - - /* Checks a private key and computes the corresponding public key. - */ - inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) { - return crypto_ops::secret_key_to_public_key(sec, pub); - } - - /* To generate an ephemeral key used to send money to: - * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field. - * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index. - * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key. - * * The receiver can either derive the public key (to check that the transaction is addressed to him) or the private key (to spend the money). - */ - inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) { - return crypto_ops::generate_key_derivation(key1, key2, derivation); - } - inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index, - const public_key &base, public_key &derived_key) { - return crypto_ops::derive_public_key(derivation, output_index, base, derived_key); - } - inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) { - return crypto_ops::derivation_to_scalar(derivation, output_index, res); - } - inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index, - const secret_key &base, secret_key &derived_key) { - crypto_ops::derive_secret_key(derivation, output_index, base, derived_key); - } - inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result) { - return crypto_ops::derive_subaddress_public_key(out_key, derivation, output_index, result); - } - - /* Generation and checking of a standard signature. - */ - inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) { - crypto_ops::generate_signature(prefix_hash, pub, sec, sig); - } - inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) { - return crypto_ops::check_signature(prefix_hash, pub, sig); - } - - /* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key - * derivation D, the signature proves the knowledge of the tx secret key r such that R=r*G and D=r*A - * When the recipient's address is a subaddress, the tx pubkey R is defined as R=r*B where B is the recipient's spend pubkey - */ - inline void generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional &B, const public_key &D, const secret_key &r, signature &sig) { - crypto_ops::generate_tx_proof(prefix_hash, R, A, B, D, r, sig); - } - inline bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional &B, const public_key &D, const signature &sig) { - return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig); - } - - /* To send money to a key: - * * The sender generates an ephemeral key and includes it in transaction output. - * * To spend the money, the receiver generates a key image from it. - * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature. - * To check the signature, it is necessary to collect all the keys that were used to generate it. To detect double spends, it is necessary to check that each key image is used at most once. - */ - inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) { - crypto_ops::generate_key_image(pub, sec, image); - } - inline void generate_ring_signature(const hash &prefix_hash, const key_image &image, - const public_key *const *pubs, std::size_t pubs_count, - const secret_key &sec, std::size_t sec_index, - signature *sig) { - crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig); - } - inline bool check_ring_signature(const hash &prefix_hash, const key_image &image, - const public_key *const *pubs, std::size_t pubs_count, - const signature *sig) { - return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig); - } - - /* Variants with vector parameters. - */ - inline void generate_ring_signature(const hash &prefix_hash, const key_image &image, - const std::vector &pubs, - const secret_key &sec, std::size_t sec_index, - signature *sig) { - generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig); - } - inline bool check_ring_signature(const hash &prefix_hash, const key_image &image, - const std::vector &pubs, - const signature *sig) { - return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig); - } - - inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { - epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; - } - inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) { - epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; - } - inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) { - epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; - } - inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { - epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; - } - inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { - epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; - } - - const static crypto::public_key null_pkey = boost::value_initialized(); - const static crypto::secret_key null_skey = boost::value_initialized(); } -CRYPTO_MAKE_HASHABLE(public_key) -CRYPTO_MAKE_HASHABLE(secret_key) +CRYPTO_MAKE_COMPARABLE(public_key) CRYPTO_MAKE_HASHABLE(key_image) CRYPTO_MAKE_COMPARABLE(signature) +CRYPTO_MAKE_COMPARABLE(view_tag) diff --git a/src/Native/libcryptonote/crypto/generic-ops.h b/src/Native/libcryptonote/crypto/generic-ops.h index 62bc758c9..8cade72a8 100644 --- a/src/Native/libcryptonote/crypto/generic-ops.h +++ b/src/Native/libcryptonote/crypto/generic-ops.h @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once diff --git a/src/Native/libcryptonote/crypto/groestl.c b/src/Native/libcryptonote/crypto/groestl.c deleted file mode 100644 index c8258add3..000000000 --- a/src/Native/libcryptonote/crypto/groestl.c +++ /dev/null @@ -1,360 +0,0 @@ -/* hash.c April 2012 - * Groestl ANSI C code optimised for 32-bit machines - * Author: Thomas Krinninger - * - * This work is based on the implementation of - * Soeren S. Thomsen and Krystian Matusiewicz - * - * - */ - -#include -#include "groestl.h" -#include "groestl_tables.h" - -#define P_TYPE 0 -#define Q_TYPE 1 - -const uint8_t shift_Values[2][8] = {{0,1,2,3,4,5,6,7},{1,3,5,7,0,2,4,6}}; - -const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6}; - - -#define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \ - v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \ - v1 = temp_var;} - - -#define COLUMN(x,y,i,c0,c1,c2,c3,c4,c5,c6,c7,tv1,tv2,tu,tl,t) \ - tu = T[2*(uint32_t)x[4*c0+0]]; \ - tl = T[2*(uint32_t)x[4*c0+0]+1]; \ - tv1 = T[2*(uint32_t)x[4*c1+1]]; \ - tv2 = T[2*(uint32_t)x[4*c1+1]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \ - tu ^= tv1; \ - tl ^= tv2; \ - tv1 = T[2*(uint32_t)x[4*c2+2]]; \ - tv2 = T[2*(uint32_t)x[4*c2+2]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \ - tu ^= tv1; \ - tl ^= tv2; \ - tv1 = T[2*(uint32_t)x[4*c3+3]]; \ - tv2 = T[2*(uint32_t)x[4*c3+3]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \ - tu ^= tv1; \ - tl ^= tv2; \ - tl ^= T[2*(uint32_t)x[4*c4+0]]; \ - tu ^= T[2*(uint32_t)x[4*c4+0]+1]; \ - tv1 = T[2*(uint32_t)x[4*c5+1]]; \ - tv2 = T[2*(uint32_t)x[4*c5+1]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \ - tl ^= tv1; \ - tu ^= tv2; \ - tv1 = T[2*(uint32_t)x[4*c6+2]]; \ - tv2 = T[2*(uint32_t)x[4*c6+2]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \ - tl ^= tv1; \ - tu ^= tv2; \ - tv1 = T[2*(uint32_t)x[4*c7+3]]; \ - tv2 = T[2*(uint32_t)x[4*c7+3]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \ - tl ^= tv1; \ - tu ^= tv2; \ - y[i] = tu; \ - y[i+1] = tl; - - -/* compute one round of P (short variants) */ -static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) { - uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; - uint32_t* x32 = (uint32_t*)x; - x32[ 0] ^= 0x00000000^r; - x32[ 2] ^= 0x00000010^r; - x32[ 4] ^= 0x00000020^r; - x32[ 6] ^= 0x00000030^r; - x32[ 8] ^= 0x00000040^r; - x32[10] ^= 0x00000050^r; - x32[12] ^= 0x00000060^r; - x32[14] ^= 0x00000070^r; - COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); -} - -/* compute one round of Q (short variants) */ -static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) { - uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; - uint32_t* x32 = (uint32_t*)x; - x32[ 0] = ~x32[ 0]; - x32[ 1] ^= 0xffffffff^r; - x32[ 2] = ~x32[ 2]; - x32[ 3] ^= 0xefffffff^r; - x32[ 4] = ~x32[ 4]; - x32[ 5] ^= 0xdfffffff^r; - x32[ 6] = ~x32[ 6]; - x32[ 7] ^= 0xcfffffff^r; - x32[ 8] = ~x32[ 8]; - x32[ 9] ^= 0xbfffffff^r; - x32[10] = ~x32[10]; - x32[11] ^= 0xafffffff^r; - x32[12] = ~x32[12]; - x32[13] ^= 0x9fffffff^r; - x32[14] = ~x32[14]; - x32[15] ^= 0x8fffffff^r; - COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); -} - -/* compute compression function (short variants) */ -static void F512(uint32_t *h, const uint32_t *m) { - int i; - uint32_t Ptmp[2*COLS512]; - uint32_t Qtmp[2*COLS512]; - uint32_t y[2*COLS512]; - uint32_t z[2*COLS512]; - - for (i = 0; i < 2*COLS512; i++) { - z[i] = m[i]; - Ptmp[i] = h[i]^m[i]; - } - - /* compute Q(m) */ - RND512Q((uint8_t*)z, y, 0x00000000); - RND512Q((uint8_t*)y, z, 0x01000000); - RND512Q((uint8_t*)z, y, 0x02000000); - RND512Q((uint8_t*)y, z, 0x03000000); - RND512Q((uint8_t*)z, y, 0x04000000); - RND512Q((uint8_t*)y, z, 0x05000000); - RND512Q((uint8_t*)z, y, 0x06000000); - RND512Q((uint8_t*)y, z, 0x07000000); - RND512Q((uint8_t*)z, y, 0x08000000); - RND512Q((uint8_t*)y, Qtmp, 0x09000000); - - /* compute P(h+m) */ - RND512P((uint8_t*)Ptmp, y, 0x00000000); - RND512P((uint8_t*)y, z, 0x00000001); - RND512P((uint8_t*)z, y, 0x00000002); - RND512P((uint8_t*)y, z, 0x00000003); - RND512P((uint8_t*)z, y, 0x00000004); - RND512P((uint8_t*)y, z, 0x00000005); - RND512P((uint8_t*)z, y, 0x00000006); - RND512P((uint8_t*)y, z, 0x00000007); - RND512P((uint8_t*)z, y, 0x00000008); - RND512P((uint8_t*)y, Ptmp, 0x00000009); - - /* compute P(h+m) + Q(m) + h */ - for (i = 0; i < 2*COLS512; i++) { - h[i] ^= Ptmp[i]^Qtmp[i]; - } -} - - -/* digest up to msglen bytes of input (full blocks only) */ -static void Transform(hashState *ctx, - const uint8_t *input, - int msglen) { - - /* digest message, one block at a time */ - for (; msglen >= SIZE512; - msglen -= SIZE512, input += SIZE512) { - F512(ctx->chaining,(uint32_t*)input); - - /* increment block counter */ - ctx->block_counter1++; - if (ctx->block_counter1 == 0) ctx->block_counter2++; - } -} - -/* given state h, do h <- P(h)+h */ -static void OutputTransformation(hashState *ctx) { - int j; - uint32_t temp[2*COLS512]; - uint32_t y[2*COLS512]; - uint32_t z[2*COLS512]; - - - - for (j = 0; j < 2*COLS512; j++) { - temp[j] = ctx->chaining[j]; - } - RND512P((uint8_t*)temp, y, 0x00000000); - RND512P((uint8_t*)y, z, 0x00000001); - RND512P((uint8_t*)z, y, 0x00000002); - RND512P((uint8_t*)y, z, 0x00000003); - RND512P((uint8_t*)z, y, 0x00000004); - RND512P((uint8_t*)y, z, 0x00000005); - RND512P((uint8_t*)z, y, 0x00000006); - RND512P((uint8_t*)y, z, 0x00000007); - RND512P((uint8_t*)z, y, 0x00000008); - RND512P((uint8_t*)y, temp, 0x00000009); - for (j = 0; j < 2*COLS512; j++) { - ctx->chaining[j] ^= temp[j]; - } -} - -/* initialise context */ -static void Init(hashState* ctx) { - /* allocate memory for state and data buffer */ - - for(size_t i = 0; i < (SIZE512/sizeof(uint32_t)); i++) - { - ctx->chaining[i] = 0; - } - - /* set initial value */ - ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN); - - /* set other variables */ - ctx->buf_ptr = 0; - ctx->block_counter1 = 0; - ctx->block_counter2 = 0; - ctx->bits_in_last_byte = 0; -} - -/* update state with databitlen bits of input */ -static void Update(hashState* ctx, - const BitSequence* input, - DataLength databitlen) { - int index = 0; - int msglen = (int)(databitlen/8); - int rem = (int)(databitlen%8); - - /* if the buffer contains data that has not yet been digested, first - add data to buffer until full */ - if (ctx->buf_ptr) { - while (ctx->buf_ptr < SIZE512 && index < msglen) { - ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; - } - if (ctx->buf_ptr < SIZE512) { - /* buffer still not full, return */ - if (rem) { - ctx->bits_in_last_byte = rem; - ctx->buffer[(int)ctx->buf_ptr++] = input[index]; - } - return; - } - - /* digest buffer */ - ctx->buf_ptr = 0; - Transform(ctx, ctx->buffer, SIZE512); - } - - /* digest bulk of message */ - Transform(ctx, input+index, msglen-index); - index += ((msglen-index)/SIZE512)*SIZE512; - - /* store remaining data in buffer */ - while (index < msglen) { - ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; - } - - /* if non-integral number of bytes have been supplied, store - remaining bits in last byte, together with information about - number of bits */ - if (rem) { - ctx->bits_in_last_byte = rem; - ctx->buffer[(int)ctx->buf_ptr++] = input[index]; - } -} - -#define BILB ctx->bits_in_last_byte - -/* finalise: process remaining data (including padding), perform - output transformation, and write hash result to 'output' */ -static void Final(hashState* ctx, - BitSequence* output) { - int i, j = 0, hashbytelen = HASH_BIT_LEN/8; - uint8_t *s = (BitSequence*)ctx->chaining; - - /* pad with '1'-bit and first few '0'-bits */ - if (BILB) { - ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB); - BILB = 0; - } - else ctx->buffer[(int)ctx->buf_ptr++] = 0x80; - - /* pad with '0'-bits */ - if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) { - /* padding requires two blocks */ - while (ctx->buf_ptr < SIZE512) { - ctx->buffer[(int)ctx->buf_ptr++] = 0; - } - /* digest first padding block */ - Transform(ctx, ctx->buffer, SIZE512); - ctx->buf_ptr = 0; - } - while (ctx->buf_ptr < SIZE512-LENGTHFIELDLEN) { - ctx->buffer[(int)ctx->buf_ptr++] = 0; - } - - /* length padding */ - ctx->block_counter1++; - if (ctx->block_counter1 == 0) ctx->block_counter2++; - ctx->buf_ptr = SIZE512; - - while (ctx->buf_ptr > SIZE512-(int)sizeof(uint32_t)) { - ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1; - ctx->block_counter1 >>= 8; - } - while (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) { - ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2; - ctx->block_counter2 >>= 8; - } - /* digest final padding block */ - Transform(ctx, ctx->buffer, SIZE512); - /* perform output transformation */ - OutputTransformation(ctx); - - /* store hash result in output */ - for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) { - output[j] = s[i]; - } - - /* zeroise relevant variables and deallocate memory */ - for (i = 0; i < COLS512; i++) { - ctx->chaining[i] = 0; - } - for (i = 0; i < SIZE512; i++) { - ctx->buffer[i] = 0; - } -} - -/* hash bit sequence */ -void groestl(const BitSequence* data, - DataLength databitlen, - BitSequence* hashval) { - - hashState context; - - /* initialise */ - Init(&context); - - - /* process message */ - Update(&context, data, databitlen); - - /* finalise */ - Final(&context, hashval); -} -/* -static int crypto_hash(unsigned char *out, - const unsigned char *in, - unsigned long long len) -{ - groestl(in, 8*len, out); - return 0; -} - -*/ diff --git a/src/Native/libcryptonote/crypto/groestl.h b/src/Native/libcryptonote/crypto/groestl.h deleted file mode 100644 index 19837f309..000000000 --- a/src/Native/libcryptonote/crypto/groestl.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef __hash_h -#define __hash_h -/* -#include "crypto_uint8.h" -#include "crypto_uint32.h" -#include "crypto_uint64.h" -#include "crypto_hash.h" - -typedef crypto_uint8 uint8_t; -typedef crypto_uint32 uint32_t; -typedef crypto_uint64 uint64_t; -*/ -#include - -/* some sizes (number of bytes) */ -#define ROWS 8 -#define LENGTHFIELDLEN ROWS -#define COLS512 8 - -#define SIZE512 (ROWS*COLS512) - -#define ROUNDS512 10 -#define HASH_BIT_LEN 256 - -#define ROTL32(v, n) ((((v)<<(n))|((v)>>(32-(n))))&li_32(ffffffff)) - - -#define li_32(h) 0x##h##u -#define EXT_BYTE(var,n) ((uint8_t)((uint32_t)(var) >> (8*n))) -#define u32BIG(a) \ - ((ROTL32(a,8) & li_32(00FF00FF)) | \ - (ROTL32(a,24) & li_32(FF00FF00))) - - -/* NIST API begin */ -typedef unsigned char BitSequence; -typedef unsigned long long DataLength; -typedef struct { - uint32_t chaining[SIZE512/sizeof(uint32_t)]; /* actual state */ - uint32_t block_counter1, - block_counter2; /* message block counter(s) */ - BitSequence buffer[SIZE512]; /* data buffer */ - int buf_ptr; /* data buffer pointer */ - int bits_in_last_byte; /* no. of message bits in last byte of - data buffer */ -} hashState; - -/*void Init(hashState*); -void Update(hashState*, const BitSequence*, DataLength); -void Final(hashState*, BitSequence*); */ -void groestl(const BitSequence*, DataLength, BitSequence*); -/* NIST API end */ - -/* -int crypto_hash(unsigned char *out, - const unsigned char *in, - unsigned long long len); -*/ - -#endif /* __hash_h */ diff --git a/src/Native/libcryptonote/crypto/groestl_tables.h b/src/Native/libcryptonote/crypto/groestl_tables.h deleted file mode 100644 index c4b368584..000000000 --- a/src/Native/libcryptonote/crypto/groestl_tables.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef __tables_h -#define __tables_h - - -const uint32_t T[512] = {0xa5f432c6, 0xc6a597f4, 0x84976ff8, 0xf884eb97, 0x99b05eee, 0xee99c7b0, 0x8d8c7af6, 0xf68df78c, 0xd17e8ff, 0xff0de517, 0xbddc0ad6, 0xd6bdb7dc, 0xb1c816de, 0xdeb1a7c8, 0x54fc6d91, 0x915439fc -, 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5 -, 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d -, 0xec2f6e41, 0x41ec822f, 0x67a91ab3, 0xb3677da9, 0xfd1c435f, 0x5ffdbe1c, 0xea256045, 0x45ea8a25, 0xbfdaf923, 0x23bf46da, 0xf7025153, 0x53f7a602, 0x96a145e4, 0xe496d3a1, 0x5bed769b, 0x9b5b2ded -, 0xc25d2875, 0x75c2ea5d, 0x1c24c5e1, 0xe11cd924, 0xaee9d43d, 0x3dae7ae9, 0x6abef24c, 0x4c6a98be, 0x5aee826c, 0x6c5ad8ee, 0x41c3bd7e, 0x7e41fcc3, 0x206f3f5, 0xf502f106, 0x4fd15283, 0x834f1dd1 -, 0x5ce48c68, 0x685cd0e4, 0xf4075651, 0x51f4a207, 0x345c8dd1, 0xd134b95c, 0x818e1f9, 0xf908e918, 0x93ae4ce2, 0xe293dfae, 0x73953eab, 0xab734d95, 0x53f59762, 0x6253c4f5, 0x3f416b2a, 0x2a3f5441 -, 0xc141c08, 0x80c1014, 0x52f66395, 0x955231f6, 0x65afe946, 0x46658caf, 0x5ee27f9d, 0x9d5e21e2, 0x28784830, 0x30286078, 0xa1f8cf37, 0x37a16ef8, 0xf111b0a, 0xa0f1411, 0xb5c4eb2f, 0x2fb55ec4 -, 0x91b150e, 0xe091c1b, 0x365a7e24, 0x2436485a, 0x9bb6ad1b, 0x1b9b36b6, 0x3d4798df, 0xdf3da547, 0x266aa7cd, 0xcd26816a, 0x69bbf54e, 0x4e699cbb, 0xcd4c337f, 0x7fcdfe4c, 0x9fba50ea, 0xea9fcfba -, 0x1b2d3f12, 0x121b242d, 0x9eb9a41d, 0x1d9e3ab9, 0x749cc458, 0x5874b09c, 0x2e724634, 0x342e6872, 0x2d774136, 0x362d6c77, 0xb2cd11dc, 0xdcb2a3cd, 0xee299db4, 0xb4ee7329, 0xfb164d5b, 0x5bfbb616 -, 0xf601a5a4, 0xa4f65301, 0x4dd7a176, 0x764decd7, 0x61a314b7, 0xb76175a3, 0xce49347d, 0x7dcefa49, 0x7b8ddf52, 0x527ba48d, 0x3e429fdd, 0xdd3ea142, 0x7193cd5e, 0x5e71bc93, 0x97a2b113, 0x139726a2 -, 0xf504a2a6, 0xa6f55704, 0x68b801b9, 0xb96869b8, 0x0, 0x0, 0x2c74b5c1, 0xc12c9974, 0x60a0e040, 0x406080a0, 0x1f21c2e3, 0xe31fdd21, 0xc8433a79, 0x79c8f243, 0xed2c9ab6, 0xb6ed772c -, 0xbed90dd4, 0xd4beb3d9, 0x46ca478d, 0x8d4601ca, 0xd9701767, 0x67d9ce70, 0x4bddaf72, 0x724be4dd, 0xde79ed94, 0x94de3379, 0xd467ff98, 0x98d42b67, 0xe82393b0, 0xb0e87b23, 0x4ade5b85, 0x854a11de -, 0x6bbd06bb, 0xbb6b6dbd, 0x2a7ebbc5, 0xc52a917e, 0xe5347b4f, 0x4fe59e34, 0x163ad7ed, 0xed16c13a, 0xc554d286, 0x86c51754, 0xd762f89a, 0x9ad72f62, 0x55ff9966, 0x6655ccff, 0x94a7b611, 0x119422a7 -, 0xcf4ac08a, 0x8acf0f4a, 0x1030d9e9, 0xe910c930, 0x60a0e04, 0x406080a, 0x819866fe, 0xfe81e798, 0xf00baba0, 0xa0f05b0b, 0x44ccb478, 0x7844f0cc, 0xbad5f025, 0x25ba4ad5, 0xe33e754b, 0x4be3963e -, 0xf30eaca2, 0xa2f35f0e, 0xfe19445d, 0x5dfeba19, 0xc05bdb80, 0x80c01b5b, 0x8a858005, 0x58a0a85, 0xadecd33f, 0x3fad7eec, 0xbcdffe21, 0x21bc42df, 0x48d8a870, 0x7048e0d8, 0x40cfdf1, 0xf104f90c -, 0xdf7a1963, 0x63dfc67a, 0xc1582f77, 0x77c1ee58, 0x759f30af, 0xaf75459f, 0x63a5e742, 0x426384a5, 0x30507020, 0x20304050, 0x1a2ecbe5, 0xe51ad12e, 0xe12effd, 0xfd0ee112, 0x6db708bf, 0xbf6d65b7 -, 0x4cd45581, 0x814c19d4, 0x143c2418, 0x1814303c, 0x355f7926, 0x26354c5f, 0x2f71b2c3, 0xc32f9d71, 0xe13886be, 0xbee16738, 0xa2fdc835, 0x35a26afd, 0xcc4fc788, 0x88cc0b4f, 0x394b652e, 0x2e395c4b -, 0x57f96a93, 0x93573df9, 0xf20d5855, 0x55f2aa0d, 0x829d61fc, 0xfc82e39d, 0x47c9b37a, 0x7a47f4c9, 0xacef27c8, 0xc8ac8bef, 0xe73288ba, 0xbae76f32, 0x2b7d4f32, 0x322b647d, 0x95a442e6, 0xe695d7a4 -, 0xa0fb3bc0, 0xc0a09bfb, 0x98b3aa19, 0x199832b3, 0xd168f69e, 0x9ed12768, 0x7f8122a3, 0xa37f5d81, 0x66aaee44, 0x446688aa, 0x7e82d654, 0x547ea882, 0xabe6dd3b, 0x3bab76e6, 0x839e950b, 0xb83169e -, 0xca45c98c, 0x8cca0345, 0x297bbcc7, 0xc729957b, 0xd36e056b, 0x6bd3d66e, 0x3c446c28, 0x283c5044, 0x798b2ca7, 0xa779558b, 0xe23d81bc, 0xbce2633d, 0x1d273116, 0x161d2c27, 0x769a37ad, 0xad76419a -, 0x3b4d96db, 0xdb3bad4d, 0x56fa9e64, 0x6456c8fa, 0x4ed2a674, 0x744ee8d2, 0x1e223614, 0x141e2822, 0xdb76e492, 0x92db3f76, 0xa1e120c, 0xc0a181e, 0x6cb4fc48, 0x486c90b4, 0xe4378fb8, 0xb8e46b37 -, 0x5de7789f, 0x9f5d25e7, 0x6eb20fbd, 0xbd6e61b2, 0xef2a6943, 0x43ef862a, 0xa6f135c4, 0xc4a693f1, 0xa8e3da39, 0x39a872e3, 0xa4f7c631, 0x31a462f7, 0x37598ad3, 0xd337bd59, 0x8b8674f2, 0xf28bff86 -, 0x325683d5, 0xd532b156, 0x43c54e8b, 0x8b430dc5, 0x59eb856e, 0x6e59dceb, 0xb7c218da, 0xdab7afc2, 0x8c8f8e01, 0x18c028f, 0x64ac1db1, 0xb16479ac, 0xd26df19c, 0x9cd2236d, 0xe03b7249, 0x49e0923b -, 0xb4c71fd8, 0xd8b4abc7, 0xfa15b9ac, 0xacfa4315, 0x709faf3, 0xf307fd09, 0x256fa0cf, 0xcf25856f, 0xafea20ca, 0xcaaf8fea, 0x8e897df4, 0xf48ef389, 0xe9206747, 0x47e98e20, 0x18283810, 0x10182028 -, 0xd5640b6f, 0x6fd5de64, 0x888373f0, 0xf088fb83, 0x6fb1fb4a, 0x4a6f94b1, 0x7296ca5c, 0x5c72b896, 0x246c5438, 0x3824706c, 0xf1085f57, 0x57f1ae08, 0xc7522173, 0x73c7e652, 0x51f36497, 0x975135f3 -, 0x2365aecb, 0xcb238d65, 0x7c8425a1, 0xa17c5984, 0x9cbf57e8, 0xe89ccbbf, 0x21635d3e, 0x3e217c63, 0xdd7cea96, 0x96dd377c, 0xdc7f1e61, 0x61dcc27f, 0x86919c0d, 0xd861a91, 0x85949b0f, 0xf851e94 -, 0x90ab4be0, 0xe090dbab, 0x42c6ba7c, 0x7c42f8c6, 0xc4572671, 0x71c4e257, 0xaae529cc, 0xccaa83e5, 0xd873e390, 0x90d83b73, 0x50f0906, 0x6050c0f, 0x103f4f7, 0xf701f503, 0x12362a1c, 0x1c123836 -, 0xa3fe3cc2, 0xc2a39ffe, 0x5fe18b6a, 0x6a5fd4e1, 0xf910beae, 0xaef94710, 0xd06b0269, 0x69d0d26b, 0x91a8bf17, 0x17912ea8, 0x58e87199, 0x995829e8, 0x2769533a, 0x3a277469, 0xb9d0f727, 0x27b94ed0 -, 0x384891d9, 0xd938a948, 0x1335deeb, 0xeb13cd35, 0xb3cee52b, 0x2bb356ce, 0x33557722, 0x22334455, 0xbbd604d2, 0xd2bbbfd6, 0x709039a9, 0xa9704990, 0x89808707, 0x7890e80, 0xa7f2c133, 0x33a766f2 -, 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e -, 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3 -, 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e}; - -#endif /* __tables_h */ diff --git a/src/Native/libcryptonote/crypto/hash-extra-blake.c b/src/Native/libcryptonote/crypto/hash-extra-blake.c deleted file mode 100644 index d33103c97..000000000 --- a/src/Native/libcryptonote/crypto/hash-extra-blake.c +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include - -#include "blake256.h" - -void hash_extra_blake(const void *data, size_t length, char *hash) { - blake256_hash((uint8_t*)hash, data, length); -} diff --git a/src/Native/libcryptonote/crypto/hash-extra-groestl.c b/src/Native/libcryptonote/crypto/hash-extra-groestl.c deleted file mode 100644 index 228853a44..000000000 --- a/src/Native/libcryptonote/crypto/hash-extra-groestl.c +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include - -#include "groestl.h" - -void hash_extra_groestl(const void *data, size_t length, char *hash) { - groestl(data, length * 8, (uint8_t*)hash); -} diff --git a/src/Native/libcryptonote/crypto/hash-extra-jh.c b/src/Native/libcryptonote/crypto/hash-extra-jh.c deleted file mode 100644 index e765a18f3..000000000 --- a/src/Native/libcryptonote/crypto/hash-extra-jh.c +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include -#include -#include - -#include "jh.h" -#include "hash-ops.h" - -void hash_extra_jh(const void *data, size_t length, char *hash) { - int r = jh_hash(HASH_SIZE * 8, data, 8 * length, (uint8_t*)hash); - assert(SUCCESS == r); -} diff --git a/src/Native/libcryptonote/crypto/hash-extra-skein.c b/src/Native/libcryptonote/crypto/hash-extra-skein.c deleted file mode 100644 index 06d8f87cc..000000000 --- a/src/Native/libcryptonote/crypto/hash-extra-skein.c +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include - -#include "hash-ops.h" -#include "skein.h" - -void hash_extra_skein(const void *data, size_t length, char *hash) { - int r = skein_hash(8 * HASH_SIZE, data, 8 * length, (uint8_t*)hash); - assert(SKEIN_SUCCESS == r); -} diff --git a/src/Native/libcryptonote/crypto/hash-ops.h b/src/Native/libcryptonote/crypto/hash-ops.h index d77d55cf3..4b737450d 100644 --- a/src/Native/libcryptonote/crypto/hash-ops.h +++ b/src/Native/libcryptonote/crypto/hash-ops.h @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once @@ -50,7 +24,7 @@ static inline const void *cpadd(const void *p, size_t i) { PUSH_WARNINGS DISABLE_VS_WARNINGS(4267) -static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t must be 4 or 8 bytes long"); +//static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t must be 4 or 8 bytes long"); static inline void place_length(uint8_t *buffer, size_t bufsize, size_t length) { if (sizeof(size_t) == 4) { *(uint32_t *) padd(buffer, bufsize - 4) = swap32be(length); @@ -66,7 +40,7 @@ union hash_state { uint64_t w[25]; }; #pragma pack(pop) -static_assert(sizeof(union hash_state) == 200, "Invalid structure size"); +//static_assert(sizeof(union hash_state) == 200, "Invalid structure size"); void hash_permutation(union hash_state *state); void hash_process(union hash_state *state, const uint8_t *buf, size_t count); @@ -79,7 +53,7 @@ enum { }; void cn_fast_hash(const void *data, size_t length, char *hash); -void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed); +void cn_slow_hash(const void *data, size_t length, char *hash); void hash_extra_blake(const void *data, size_t length, char *hash); void hash_extra_groestl(const void *data, size_t length, char *hash); @@ -87,3 +61,6 @@ void hash_extra_jh(const void *data, size_t length, char *hash); void hash_extra_skein(const void *data, size_t length, char *hash); void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash); +size_t tree_depth(size_t count); +void tree_branch(const char (*hashes)[HASH_SIZE], size_t count, char (*branch)[HASH_SIZE]); +void tree_hash_from_branch(const char (*branch)[HASH_SIZE], size_t depth, const char *leaf, const void *path, char *root_hash); diff --git a/src/Native/libcryptonote/crypto/hash.c b/src/Native/libcryptonote/crypto/hash.c index 42f272e34..a3989d88c 100644 --- a/src/Native/libcryptonote/crypto/hash.c +++ b/src/Native/libcryptonote/crypto/hash.c @@ -1,32 +1,6 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include diff --git a/src/Native/libcryptonote/crypto/hash.h b/src/Native/libcryptonote/crypto/hash.h index 8519af1f7..6fc578f23 100644 --- a/src/Native/libcryptonote/crypto/hash.h +++ b/src/Native/libcryptonote/crypto/hash.h @@ -1,43 +1,13 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once #include -#include -#include #include "common/pod-class.h" #include "generic-ops.h" -#include "hex.h" -#include "span.h" namespace crypto { @@ -46,6 +16,18 @@ namespace crypto { } #pragma pack(push, 1) + POD_CLASS cycle { + public: + uint32_t data[32]; + }; + POD_CLASS cycle40 { + public: + uint32_t data[40]; + }; + POD_CLASS cycle48 { + public: + uint32_t data[48]; + }; POD_CLASS hash { char data[HASH_SIZE]; }; @@ -65,41 +47,30 @@ namespace crypto { cn_fast_hash(data, length, reinterpret_cast(&hash)); } - inline void cn_fast_hash_old_sig(const void *data, std::size_t length, char *hash) { - cn_fast_hash(data, length, hash); - } - inline hash cn_fast_hash(const void *data, std::size_t length) { hash h; cn_fast_hash(data, length, reinterpret_cast(&h)); return h; } - inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0) { - cn_slow_hash(data, length, reinterpret_cast(&hash), variant, 0/*prehashed*/); - } - - inline void cn_slow_hash_old_sig(const void *data, std::size_t length, char *hash, int variant = 0) { - cn_slow_hash(data, length, hash, variant, 0/*prehashed*/); - } - - inline void cn_slow_hash_prehashed(const void *data, std::size_t length, hash &hash, int variant = 0) { - cn_slow_hash(data, length, reinterpret_cast(&hash), variant, 1/*prehashed*/); + inline void cn_slow_hash(const void *data, std::size_t length, hash &hash) { + cn_slow_hash(data, length, reinterpret_cast(&hash)); } inline void tree_hash(const hash *hashes, std::size_t count, hash &root_hash) { tree_hash(reinterpret_cast(hashes), count, reinterpret_cast(&root_hash)); } - inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { - epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; + inline void tree_branch(const hash* hashes, std::size_t count, hash* branch) + { + tree_branch(reinterpret_cast(hashes), count, reinterpret_cast(branch)); } - inline std::ostream &operator <<(std::ostream &o, const crypto::hash8 &v) { - epee::to_hex::formatted(o, epee::as_byte_span(v)); return o; + + inline void tree_hash_from_branch(const hash* branch, std::size_t depth, const hash& leaf, const void* path, hash& root_hash) + { + tree_hash_from_branch(reinterpret_cast(branch), depth, reinterpret_cast(&leaf), path, reinterpret_cast(&root_hash)); } - const static crypto::hash null_hash = boost::value_initialized(); - const static crypto::hash8 null_hash8 = boost::value_initialized(); } CRYPTO_MAKE_HASHABLE(hash) diff --git a/src/Native/libcryptonote/crypto/initializer.h b/src/Native/libcryptonote/crypto/initializer.h deleted file mode 100644 index afbace726..000000000 --- a/src/Native/libcryptonote/crypto/initializer.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#if defined(__GNUC__) -#if defined(__sun) && defined(__SVR4) -#define INITIALIZER(name) __attribute__((constructor)) static void name(void) -#define FINALIZER(name) __attribute__((destructor)) static void name(void) -#else -#define INITIALIZER(name) __attribute__((constructor(101))) static void name(void) -#define FINALIZER(name) __attribute__((destructor(101))) static void name(void) -#endif -#define REGISTER_FINALIZER(name) ((void) 0) - -#elif defined(_MSC_VER) -#include -#include -// http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc -// http://msdn.microsoft.com/en-us/library/bb918180.aspx -#pragma section(".CRT$XCT", read) -#define INITIALIZER(name) \ - static void __cdecl name(void); \ - __declspec(allocate(".CRT$XCT")) void (__cdecl *const _##name)(void) = &name; \ - static void __cdecl name(void) -#define FINALIZER(name) \ - static void __cdecl name(void) -#define REGISTER_FINALIZER(name) \ - do { \ - int _res = atexit(name); \ - assert(_res == 0); \ - } while (0); - -#else -#error Unsupported compiler -#endif diff --git a/src/Native/libcryptonote/crypto/jh.c b/src/Native/libcryptonote/crypto/jh.c deleted file mode 100644 index 12d536375..000000000 --- a/src/Native/libcryptonote/crypto/jh.c +++ /dev/null @@ -1,367 +0,0 @@ -/*This program gives the 64-bit optimized bitslice implementation of JH using ANSI C - - -------------------------------- - Performance - - Microprocessor: Intel CORE 2 processor (Core 2 Duo Mobile T6600 2.2GHz) - Operating System: 64-bit Ubuntu 10.04 (Linux kernel 2.6.32-22-generic) - Speed for long message: - 1) 45.8 cycles/byte compiler: Intel C++ Compiler 11.1 compilation option: icc -O2 - 2) 56.8 cycles/byte compiler: gcc 4.4.3 compilation option: gcc -O3 - - -------------------------------- - Last Modified: January 16, 2011 -*/ - -#include "jh.h" - -#include -#include - -/*typedef unsigned long long uint64;*/ -typedef uint64_t uint64; - -/*define data alignment for different C compilers*/ -#if defined(__GNUC__) - #define DATA_ALIGN16(x) x __attribute__ ((aligned(16))) -#else - #define DATA_ALIGN16(x) __declspec(align(16)) x -#endif - - -typedef struct { - int hashbitlen; /*the message digest size*/ - unsigned long long databitlen; /*the message size in bits*/ - unsigned long long datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/ - DATA_ALIGN16(uint64 x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/ - unsigned char buffer[64]; /*the 512-bit message block to be hashed;*/ -} hashState; - - -/*The initial hash value H(0)*/ -const unsigned char JH224_H0[128]={0x2d,0xfe,0xdd,0x62,0xf9,0x9a,0x98,0xac,0xae,0x7c,0xac,0xd6,0x19,0xd6,0x34,0xe7,0xa4,0x83,0x10,0x5,0xbc,0x30,0x12,0x16,0xb8,0x60,0x38,0xc6,0xc9,0x66,0x14,0x94,0x66,0xd9,0x89,0x9f,0x25,0x80,0x70,0x6f,0xce,0x9e,0xa3,0x1b,0x1d,0x9b,0x1a,0xdc,0x11,0xe8,0x32,0x5f,0x7b,0x36,0x6e,0x10,0xf9,0x94,0x85,0x7f,0x2,0xfa,0x6,0xc1,0x1b,0x4f,0x1b,0x5c,0xd8,0xc8,0x40,0xb3,0x97,0xf6,0xa1,0x7f,0x6e,0x73,0x80,0x99,0xdc,0xdf,0x93,0xa5,0xad,0xea,0xa3,0xd3,0xa4,0x31,0xe8,0xde,0xc9,0x53,0x9a,0x68,0x22,0xb4,0xa9,0x8a,0xec,0x86,0xa1,0xe4,0xd5,0x74,0xac,0x95,0x9c,0xe5,0x6c,0xf0,0x15,0x96,0xd,0xea,0xb5,0xab,0x2b,0xbf,0x96,0x11,0xdc,0xf0,0xdd,0x64,0xea,0x6e}; -const unsigned char JH256_H0[128]={0xeb,0x98,0xa3,0x41,0x2c,0x20,0xd3,0xeb,0x92,0xcd,0xbe,0x7b,0x9c,0xb2,0x45,0xc1,0x1c,0x93,0x51,0x91,0x60,0xd4,0xc7,0xfa,0x26,0x0,0x82,0xd6,0x7e,0x50,0x8a,0x3,0xa4,0x23,0x9e,0x26,0x77,0x26,0xb9,0x45,0xe0,0xfb,0x1a,0x48,0xd4,0x1a,0x94,0x77,0xcd,0xb5,0xab,0x26,0x2,0x6b,0x17,0x7a,0x56,0xf0,0x24,0x42,0xf,0xff,0x2f,0xa8,0x71,0xa3,0x96,0x89,0x7f,0x2e,0x4d,0x75,0x1d,0x14,0x49,0x8,0xf7,0x7d,0xe2,0x62,0x27,0x76,0x95,0xf7,0x76,0x24,0x8f,0x94,0x87,0xd5,0xb6,0x57,0x47,0x80,0x29,0x6c,0x5c,0x5e,0x27,0x2d,0xac,0x8e,0xd,0x6c,0x51,0x84,0x50,0xc6,0x57,0x5,0x7a,0xf,0x7b,0xe4,0xd3,0x67,0x70,0x24,0x12,0xea,0x89,0xe3,0xab,0x13,0xd3,0x1c,0xd7,0x69}; -const unsigned char JH384_H0[128]={0x48,0x1e,0x3b,0xc6,0xd8,0x13,0x39,0x8a,0x6d,0x3b,0x5e,0x89,0x4a,0xde,0x87,0x9b,0x63,0xfa,0xea,0x68,0xd4,0x80,0xad,0x2e,0x33,0x2c,0xcb,0x21,0x48,0xf,0x82,0x67,0x98,0xae,0xc8,0x4d,0x90,0x82,0xb9,0x28,0xd4,0x55,0xea,0x30,0x41,0x11,0x42,0x49,0x36,0xf5,0x55,0xb2,0x92,0x48,0x47,0xec,0xc7,0x25,0xa,0x93,0xba,0xf4,0x3c,0xe1,0x56,0x9b,0x7f,0x8a,0x27,0xdb,0x45,0x4c,0x9e,0xfc,0xbd,0x49,0x63,0x97,0xaf,0xe,0x58,0x9f,0xc2,0x7d,0x26,0xaa,0x80,0xcd,0x80,0xc0,0x8b,0x8c,0x9d,0xeb,0x2e,0xda,0x8a,0x79,0x81,0xe8,0xf8,0xd5,0x37,0x3a,0xf4,0x39,0x67,0xad,0xdd,0xd1,0x7a,0x71,0xa9,0xb4,0xd3,0xbd,0xa4,0x75,0xd3,0x94,0x97,0x6c,0x3f,0xba,0x98,0x42,0x73,0x7f}; -const unsigned char JH512_H0[128]={0x6f,0xd1,0x4b,0x96,0x3e,0x0,0xaa,0x17,0x63,0x6a,0x2e,0x5,0x7a,0x15,0xd5,0x43,0x8a,0x22,0x5e,0x8d,0xc,0x97,0xef,0xb,0xe9,0x34,0x12,0x59,0xf2,0xb3,0xc3,0x61,0x89,0x1d,0xa0,0xc1,0x53,0x6f,0x80,0x1e,0x2a,0xa9,0x5,0x6b,0xea,0x2b,0x6d,0x80,0x58,0x8e,0xcc,0xdb,0x20,0x75,0xba,0xa6,0xa9,0xf,0x3a,0x76,0xba,0xf8,0x3b,0xf7,0x1,0x69,0xe6,0x5,0x41,0xe3,0x4a,0x69,0x46,0xb5,0x8a,0x8e,0x2e,0x6f,0xe6,0x5a,0x10,0x47,0xa7,0xd0,0xc1,0x84,0x3c,0x24,0x3b,0x6e,0x71,0xb1,0x2d,0x5a,0xc1,0x99,0xcf,0x57,0xf6,0xec,0x9d,0xb1,0xf8,0x56,0xa7,0x6,0x88,0x7c,0x57,0x16,0xb1,0x56,0xe3,0xc2,0xfc,0xdf,0xe6,0x85,0x17,0xfb,0x54,0x5a,0x46,0x78,0xcc,0x8c,0xdd,0x4b}; - -/*42 round constants, each round constant is 32-byte (256-bit)*/ -const unsigned char E8_bitslice_roundconstant[42][32]={ -{0x72,0xd5,0xde,0xa2,0xdf,0x15,0xf8,0x67,0x7b,0x84,0x15,0xa,0xb7,0x23,0x15,0x57,0x81,0xab,0xd6,0x90,0x4d,0x5a,0x87,0xf6,0x4e,0x9f,0x4f,0xc5,0xc3,0xd1,0x2b,0x40}, -{0xea,0x98,0x3a,0xe0,0x5c,0x45,0xfa,0x9c,0x3,0xc5,0xd2,0x99,0x66,0xb2,0x99,0x9a,0x66,0x2,0x96,0xb4,0xf2,0xbb,0x53,0x8a,0xb5,0x56,0x14,0x1a,0x88,0xdb,0xa2,0x31}, -{0x3,0xa3,0x5a,0x5c,0x9a,0x19,0xe,0xdb,0x40,0x3f,0xb2,0xa,0x87,0xc1,0x44,0x10,0x1c,0x5,0x19,0x80,0x84,0x9e,0x95,0x1d,0x6f,0x33,0xeb,0xad,0x5e,0xe7,0xcd,0xdc}, -{0x10,0xba,0x13,0x92,0x2,0xbf,0x6b,0x41,0xdc,0x78,0x65,0x15,0xf7,0xbb,0x27,0xd0,0xa,0x2c,0x81,0x39,0x37,0xaa,0x78,0x50,0x3f,0x1a,0xbf,0xd2,0x41,0x0,0x91,0xd3}, -{0x42,0x2d,0x5a,0xd,0xf6,0xcc,0x7e,0x90,0xdd,0x62,0x9f,0x9c,0x92,0xc0,0x97,0xce,0x18,0x5c,0xa7,0xb,0xc7,0x2b,0x44,0xac,0xd1,0xdf,0x65,0xd6,0x63,0xc6,0xfc,0x23}, -{0x97,0x6e,0x6c,0x3,0x9e,0xe0,0xb8,0x1a,0x21,0x5,0x45,0x7e,0x44,0x6c,0xec,0xa8,0xee,0xf1,0x3,0xbb,0x5d,0x8e,0x61,0xfa,0xfd,0x96,0x97,0xb2,0x94,0x83,0x81,0x97}, -{0x4a,0x8e,0x85,0x37,0xdb,0x3,0x30,0x2f,0x2a,0x67,0x8d,0x2d,0xfb,0x9f,0x6a,0x95,0x8a,0xfe,0x73,0x81,0xf8,0xb8,0x69,0x6c,0x8a,0xc7,0x72,0x46,0xc0,0x7f,0x42,0x14}, -{0xc5,0xf4,0x15,0x8f,0xbd,0xc7,0x5e,0xc4,0x75,0x44,0x6f,0xa7,0x8f,0x11,0xbb,0x80,0x52,0xde,0x75,0xb7,0xae,0xe4,0x88,0xbc,0x82,0xb8,0x0,0x1e,0x98,0xa6,0xa3,0xf4}, -{0x8e,0xf4,0x8f,0x33,0xa9,0xa3,0x63,0x15,0xaa,0x5f,0x56,0x24,0xd5,0xb7,0xf9,0x89,0xb6,0xf1,0xed,0x20,0x7c,0x5a,0xe0,0xfd,0x36,0xca,0xe9,0x5a,0x6,0x42,0x2c,0x36}, -{0xce,0x29,0x35,0x43,0x4e,0xfe,0x98,0x3d,0x53,0x3a,0xf9,0x74,0x73,0x9a,0x4b,0xa7,0xd0,0xf5,0x1f,0x59,0x6f,0x4e,0x81,0x86,0xe,0x9d,0xad,0x81,0xaf,0xd8,0x5a,0x9f}, -{0xa7,0x5,0x6,0x67,0xee,0x34,0x62,0x6a,0x8b,0xb,0x28,0xbe,0x6e,0xb9,0x17,0x27,0x47,0x74,0x7,0x26,0xc6,0x80,0x10,0x3f,0xe0,0xa0,0x7e,0x6f,0xc6,0x7e,0x48,0x7b}, -{0xd,0x55,0xa,0xa5,0x4a,0xf8,0xa4,0xc0,0x91,0xe3,0xe7,0x9f,0x97,0x8e,0xf1,0x9e,0x86,0x76,0x72,0x81,0x50,0x60,0x8d,0xd4,0x7e,0x9e,0x5a,0x41,0xf3,0xe5,0xb0,0x62}, -{0xfc,0x9f,0x1f,0xec,0x40,0x54,0x20,0x7a,0xe3,0xe4,0x1a,0x0,0xce,0xf4,0xc9,0x84,0x4f,0xd7,0x94,0xf5,0x9d,0xfa,0x95,0xd8,0x55,0x2e,0x7e,0x11,0x24,0xc3,0x54,0xa5}, -{0x5b,0xdf,0x72,0x28,0xbd,0xfe,0x6e,0x28,0x78,0xf5,0x7f,0xe2,0xf,0xa5,0xc4,0xb2,0x5,0x89,0x7c,0xef,0xee,0x49,0xd3,0x2e,0x44,0x7e,0x93,0x85,0xeb,0x28,0x59,0x7f}, -{0x70,0x5f,0x69,0x37,0xb3,0x24,0x31,0x4a,0x5e,0x86,0x28,0xf1,0x1d,0xd6,0xe4,0x65,0xc7,0x1b,0x77,0x4,0x51,0xb9,0x20,0xe7,0x74,0xfe,0x43,0xe8,0x23,0xd4,0x87,0x8a}, -{0x7d,0x29,0xe8,0xa3,0x92,0x76,0x94,0xf2,0xdd,0xcb,0x7a,0x9,0x9b,0x30,0xd9,0xc1,0x1d,0x1b,0x30,0xfb,0x5b,0xdc,0x1b,0xe0,0xda,0x24,0x49,0x4f,0xf2,0x9c,0x82,0xbf}, -{0xa4,0xe7,0xba,0x31,0xb4,0x70,0xbf,0xff,0xd,0x32,0x44,0x5,0xde,0xf8,0xbc,0x48,0x3b,0xae,0xfc,0x32,0x53,0xbb,0xd3,0x39,0x45,0x9f,0xc3,0xc1,0xe0,0x29,0x8b,0xa0}, -{0xe5,0xc9,0x5,0xfd,0xf7,0xae,0x9,0xf,0x94,0x70,0x34,0x12,0x42,0x90,0xf1,0x34,0xa2,0x71,0xb7,0x1,0xe3,0x44,0xed,0x95,0xe9,0x3b,0x8e,0x36,0x4f,0x2f,0x98,0x4a}, -{0x88,0x40,0x1d,0x63,0xa0,0x6c,0xf6,0x15,0x47,0xc1,0x44,0x4b,0x87,0x52,0xaf,0xff,0x7e,0xbb,0x4a,0xf1,0xe2,0xa,0xc6,0x30,0x46,0x70,0xb6,0xc5,0xcc,0x6e,0x8c,0xe6}, -{0xa4,0xd5,0xa4,0x56,0xbd,0x4f,0xca,0x0,0xda,0x9d,0x84,0x4b,0xc8,0x3e,0x18,0xae,0x73,0x57,0xce,0x45,0x30,0x64,0xd1,0xad,0xe8,0xa6,0xce,0x68,0x14,0x5c,0x25,0x67}, -{0xa3,0xda,0x8c,0xf2,0xcb,0xe,0xe1,0x16,0x33,0xe9,0x6,0x58,0x9a,0x94,0x99,0x9a,0x1f,0x60,0xb2,0x20,0xc2,0x6f,0x84,0x7b,0xd1,0xce,0xac,0x7f,0xa0,0xd1,0x85,0x18}, -{0x32,0x59,0x5b,0xa1,0x8d,0xdd,0x19,0xd3,0x50,0x9a,0x1c,0xc0,0xaa,0xa5,0xb4,0x46,0x9f,0x3d,0x63,0x67,0xe4,0x4,0x6b,0xba,0xf6,0xca,0x19,0xab,0xb,0x56,0xee,0x7e}, -{0x1f,0xb1,0x79,0xea,0xa9,0x28,0x21,0x74,0xe9,0xbd,0xf7,0x35,0x3b,0x36,0x51,0xee,0x1d,0x57,0xac,0x5a,0x75,0x50,0xd3,0x76,0x3a,0x46,0xc2,0xfe,0xa3,0x7d,0x70,0x1}, -{0xf7,0x35,0xc1,0xaf,0x98,0xa4,0xd8,0x42,0x78,0xed,0xec,0x20,0x9e,0x6b,0x67,0x79,0x41,0x83,0x63,0x15,0xea,0x3a,0xdb,0xa8,0xfa,0xc3,0x3b,0x4d,0x32,0x83,0x2c,0x83}, -{0xa7,0x40,0x3b,0x1f,0x1c,0x27,0x47,0xf3,0x59,0x40,0xf0,0x34,0xb7,0x2d,0x76,0x9a,0xe7,0x3e,0x4e,0x6c,0xd2,0x21,0x4f,0xfd,0xb8,0xfd,0x8d,0x39,0xdc,0x57,0x59,0xef}, -{0x8d,0x9b,0xc,0x49,0x2b,0x49,0xeb,0xda,0x5b,0xa2,0xd7,0x49,0x68,0xf3,0x70,0xd,0x7d,0x3b,0xae,0xd0,0x7a,0x8d,0x55,0x84,0xf5,0xa5,0xe9,0xf0,0xe4,0xf8,0x8e,0x65}, -{0xa0,0xb8,0xa2,0xf4,0x36,0x10,0x3b,0x53,0xc,0xa8,0x7,0x9e,0x75,0x3e,0xec,0x5a,0x91,0x68,0x94,0x92,0x56,0xe8,0x88,0x4f,0x5b,0xb0,0x5c,0x55,0xf8,0xba,0xbc,0x4c}, -{0xe3,0xbb,0x3b,0x99,0xf3,0x87,0x94,0x7b,0x75,0xda,0xf4,0xd6,0x72,0x6b,0x1c,0x5d,0x64,0xae,0xac,0x28,0xdc,0x34,0xb3,0x6d,0x6c,0x34,0xa5,0x50,0xb8,0x28,0xdb,0x71}, -{0xf8,0x61,0xe2,0xf2,0x10,0x8d,0x51,0x2a,0xe3,0xdb,0x64,0x33,0x59,0xdd,0x75,0xfc,0x1c,0xac,0xbc,0xf1,0x43,0xce,0x3f,0xa2,0x67,0xbb,0xd1,0x3c,0x2,0xe8,0x43,0xb0}, -{0x33,0xa,0x5b,0xca,0x88,0x29,0xa1,0x75,0x7f,0x34,0x19,0x4d,0xb4,0x16,0x53,0x5c,0x92,0x3b,0x94,0xc3,0xe,0x79,0x4d,0x1e,0x79,0x74,0x75,0xd7,0xb6,0xee,0xaf,0x3f}, -{0xea,0xa8,0xd4,0xf7,0xbe,0x1a,0x39,0x21,0x5c,0xf4,0x7e,0x9,0x4c,0x23,0x27,0x51,0x26,0xa3,0x24,0x53,0xba,0x32,0x3c,0xd2,0x44,0xa3,0x17,0x4a,0x6d,0xa6,0xd5,0xad}, -{0xb5,0x1d,0x3e,0xa6,0xaf,0xf2,0xc9,0x8,0x83,0x59,0x3d,0x98,0x91,0x6b,0x3c,0x56,0x4c,0xf8,0x7c,0xa1,0x72,0x86,0x60,0x4d,0x46,0xe2,0x3e,0xcc,0x8,0x6e,0xc7,0xf6}, -{0x2f,0x98,0x33,0xb3,0xb1,0xbc,0x76,0x5e,0x2b,0xd6,0x66,0xa5,0xef,0xc4,0xe6,0x2a,0x6,0xf4,0xb6,0xe8,0xbe,0xc1,0xd4,0x36,0x74,0xee,0x82,0x15,0xbc,0xef,0x21,0x63}, -{0xfd,0xc1,0x4e,0xd,0xf4,0x53,0xc9,0x69,0xa7,0x7d,0x5a,0xc4,0x6,0x58,0x58,0x26,0x7e,0xc1,0x14,0x16,0x6,0xe0,0xfa,0x16,0x7e,0x90,0xaf,0x3d,0x28,0x63,0x9d,0x3f}, -{0xd2,0xc9,0xf2,0xe3,0x0,0x9b,0xd2,0xc,0x5f,0xaa,0xce,0x30,0xb7,0xd4,0xc,0x30,0x74,0x2a,0x51,0x16,0xf2,0xe0,0x32,0x98,0xd,0xeb,0x30,0xd8,0xe3,0xce,0xf8,0x9a}, -{0x4b,0xc5,0x9e,0x7b,0xb5,0xf1,0x79,0x92,0xff,0x51,0xe6,0x6e,0x4,0x86,0x68,0xd3,0x9b,0x23,0x4d,0x57,0xe6,0x96,0x67,0x31,0xcc,0xe6,0xa6,0xf3,0x17,0xa,0x75,0x5}, -{0xb1,0x76,0x81,0xd9,0x13,0x32,0x6c,0xce,0x3c,0x17,0x52,0x84,0xf8,0x5,0xa2,0x62,0xf4,0x2b,0xcb,0xb3,0x78,0x47,0x15,0x47,0xff,0x46,0x54,0x82,0x23,0x93,0x6a,0x48}, -{0x38,0xdf,0x58,0x7,0x4e,0x5e,0x65,0x65,0xf2,0xfc,0x7c,0x89,0xfc,0x86,0x50,0x8e,0x31,0x70,0x2e,0x44,0xd0,0xb,0xca,0x86,0xf0,0x40,0x9,0xa2,0x30,0x78,0x47,0x4e}, -{0x65,0xa0,0xee,0x39,0xd1,0xf7,0x38,0x83,0xf7,0x5e,0xe9,0x37,0xe4,0x2c,0x3a,0xbd,0x21,0x97,0xb2,0x26,0x1,0x13,0xf8,0x6f,0xa3,0x44,0xed,0xd1,0xef,0x9f,0xde,0xe7}, -{0x8b,0xa0,0xdf,0x15,0x76,0x25,0x92,0xd9,0x3c,0x85,0xf7,0xf6,0x12,0xdc,0x42,0xbe,0xd8,0xa7,0xec,0x7c,0xab,0x27,0xb0,0x7e,0x53,0x8d,0x7d,0xda,0xaa,0x3e,0xa8,0xde}, -{0xaa,0x25,0xce,0x93,0xbd,0x2,0x69,0xd8,0x5a,0xf6,0x43,0xfd,0x1a,0x73,0x8,0xf9,0xc0,0x5f,0xef,0xda,0x17,0x4a,0x19,0xa5,0x97,0x4d,0x66,0x33,0x4c,0xfd,0x21,0x6a}, -{0x35,0xb4,0x98,0x31,0xdb,0x41,0x15,0x70,0xea,0x1e,0xf,0xbb,0xed,0xcd,0x54,0x9b,0x9a,0xd0,0x63,0xa1,0x51,0x97,0x40,0x72,0xf6,0x75,0x9d,0xbf,0x91,0x47,0x6f,0xe2}}; - - -static void E8(hashState *state); /*The bijective function E8, in bitslice form*/ -static void F8(hashState *state); /*The compression function F8 */ - -/*The API functions*/ -static HashReturn Init(hashState *state, int hashbitlen); -static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); -static HashReturn Final(hashState *state, BitSequence *hashval); -HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval); - -/*swapping bit 2i with bit 2i+1 of 64-bit x*/ -#define SWAP1(x) (x) = ((((x) & 0x5555555555555555ULL) << 1) | (((x) & 0xaaaaaaaaaaaaaaaaULL) >> 1)); -/*swapping bits 4i||4i+1 with bits 4i+2||4i+3 of 64-bit x*/ -#define SWAP2(x) (x) = ((((x) & 0x3333333333333333ULL) << 2) | (((x) & 0xccccccccccccccccULL) >> 2)); -/*swapping bits 8i||8i+1||8i+2||8i+3 with bits 8i+4||8i+5||8i+6||8i+7 of 64-bit x*/ -#define SWAP4(x) (x) = ((((x) & 0x0f0f0f0f0f0f0f0fULL) << 4) | (((x) & 0xf0f0f0f0f0f0f0f0ULL) >> 4)); -/*swapping bits 16i||16i+1||......||16i+7 with bits 16i+8||16i+9||......||16i+15 of 64-bit x*/ -#define SWAP8(x) (x) = ((((x) & 0x00ff00ff00ff00ffULL) << 8) | (((x) & 0xff00ff00ff00ff00ULL) >> 8)); -/*swapping bits 32i||32i+1||......||32i+15 with bits 32i+16||32i+17||......||32i+31 of 64-bit x*/ -#define SWAP16(x) (x) = ((((x) & 0x0000ffff0000ffffULL) << 16) | (((x) & 0xffff0000ffff0000ULL) >> 16)); -/*swapping bits 64i||64i+1||......||64i+31 with bits 64i+32||64i+33||......||64i+63 of 64-bit x*/ -#define SWAP32(x) (x) = (((x) << 32) | ((x) >> 32)); - -/*The MDS transform*/ -#define L(m0,m1,m2,m3,m4,m5,m6,m7) \ - (m4) ^= (m1); \ - (m5) ^= (m2); \ - (m6) ^= (m0) ^ (m3); \ - (m7) ^= (m0); \ - (m0) ^= (m5); \ - (m1) ^= (m6); \ - (m2) ^= (m4) ^ (m7); \ - (m3) ^= (m4); - -/*Two Sboxes are computed in parallel, each Sbox implements S0 and S1, selected by a constant bit*/ -/*The reason to compute two Sboxes in parallel is to try to fully utilize the parallel processing power*/ -#define SS(m0,m1,m2,m3,m4,m5,m6,m7,cc0,cc1) \ - m3 = ~(m3); \ - m7 = ~(m7); \ - m0 ^= ((~(m2)) & (cc0)); \ - m4 ^= ((~(m6)) & (cc1)); \ - temp0 = (cc0) ^ ((m0) & (m1));\ - temp1 = (cc1) ^ ((m4) & (m5));\ - m0 ^= ((m2) & (m3)); \ - m4 ^= ((m6) & (m7)); \ - m3 ^= ((~(m1)) & (m2)); \ - m7 ^= ((~(m5)) & (m6)); \ - m1 ^= ((m0) & (m2)); \ - m5 ^= ((m4) & (m6)); \ - m2 ^= ((m0) & (~(m3))); \ - m6 ^= ((m4) & (~(m7))); \ - m0 ^= ((m1) | (m3)); \ - m4 ^= ((m5) | (m7)); \ - m3 ^= ((m1) & (m2)); \ - m7 ^= ((m5) & (m6)); \ - m1 ^= (temp0 & (m0)); \ - m5 ^= (temp1 & (m4)); \ - m2 ^= temp0; \ - m6 ^= temp1; - -/*The bijective function E8, in bitslice form*/ -static void E8(hashState *state) -{ - uint64 i,roundnumber,temp0,temp1; - - for (roundnumber = 0; roundnumber < 42; roundnumber = roundnumber+7) { - /*round 7*roundnumber+0: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP1(state->x[1][i]); SWAP1(state->x[3][i]); SWAP1(state->x[5][i]); SWAP1(state->x[7][i]); - } - - /*round 7*roundnumber+1: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP2(state->x[1][i]); SWAP2(state->x[3][i]); SWAP2(state->x[5][i]); SWAP2(state->x[7][i]); - } - - /*round 7*roundnumber+2: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP4(state->x[1][i]); SWAP4(state->x[3][i]); SWAP4(state->x[5][i]); SWAP4(state->x[7][i]); - } - - /*round 7*roundnumber+3: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP8(state->x[1][i]); SWAP8(state->x[3][i]); SWAP8(state->x[5][i]); SWAP8(state->x[7][i]); - } - - /*round 7*roundnumber+4: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP16(state->x[1][i]); SWAP16(state->x[3][i]); SWAP16(state->x[5][i]); SWAP16(state->x[7][i]); - } - - /*round 7*roundnumber+5: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP32(state->x[1][i]); SWAP32(state->x[3][i]); SWAP32(state->x[5][i]); SWAP32(state->x[7][i]); - } - - /*round 7*roundnumber+6: Sbox and MDS layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - } - /*round 7*roundnumber+6: swapping layer*/ - for (i = 1; i < 8; i = i+2) { - temp0 = state->x[i][0]; state->x[i][0] = state->x[i][1]; state->x[i][1] = temp0; - } - } - -} - -/*The compression function F8 */ -static void F8(hashState *state) -{ - uint64 i; - - /*xor the 512-bit message with the fist half of the 1024-bit hash state*/ - for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i]; - - /*the bijective function E8 */ - E8(state); - - /*xor the 512-bit message with the second half of the 1024-bit hash state*/ - for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i]; -} - -/*before hashing a message, initialize the hash state as H0 */ -static HashReturn Init(hashState *state, int hashbitlen) -{ - state->databitlen = 0; - state->datasize_in_buffer = 0; - - /*initialize the initial hash value of JH*/ - state->hashbitlen = hashbitlen; - - /*load the intital hash value into state*/ - switch (hashbitlen) - { - case 224: memcpy(state->x,JH224_H0,128); break; - case 256: memcpy(state->x,JH256_H0,128); break; - case 384: memcpy(state->x,JH384_H0,128); break; - case 512: memcpy(state->x,JH512_H0,128); break; - } - - return(SUCCESS); -} - - -/*hash each 512-bit message block, except the last partial block*/ -static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) -{ - DataLength index; /*the starting address of the data to be compressed*/ - - state->databitlen += databitlen; - index = 0; - - /*if there is remaining data in the buffer, fill it to a full message block first*/ - /*we assume that the size of the data in the buffer is the multiple of 8 bits if it is not at the end of a message*/ - - /*There is data in the buffer, but the incoming data is insufficient for a full block*/ - if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) < 512) ) { - if ( (databitlen & 7) == 0 ) { - memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)) ; - } - else memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)+1) ; - state->datasize_in_buffer += databitlen; - databitlen = 0; - } - - /*There is data in the buffer, and the incoming data is sufficient for a full block*/ - if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) >= 512) ) { - memcpy( state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3) ) ; - index = 64-(state->datasize_in_buffer >> 3); - databitlen = databitlen - (512 - state->datasize_in_buffer); - F8(state); - state->datasize_in_buffer = 0; - } - - /*hash the remaining full message blocks*/ - for ( ; databitlen >= 512; index = index+64, databitlen = databitlen - 512) { - memcpy(state->buffer, data+index, 64); - F8(state); - } - - /*store the partial block into buffer, assume that -- if part of the last byte is not part of the message, then that part consists of 0 bits*/ - if ( databitlen > 0) { - if ((databitlen & 7) == 0) - memcpy(state->buffer, data+index, (databitlen & 0x1ff) >> 3); - else - memcpy(state->buffer, data+index, ((databitlen & 0x1ff) >> 3)+1); - state->datasize_in_buffer = databitlen; - } - - return(SUCCESS); -} - -/*pad the message, process the padded block(s), truncate the hash value H to obtain the message digest*/ -static HashReturn Final(hashState *state, BitSequence *hashval) -{ - unsigned int i; - - if ( (state->databitlen & 0x1ff) == 0 ) { - /*pad the message when databitlen is multiple of 512 bits, then process the padded block*/ - memset(state->buffer, 0, 64); - state->buffer[0] = 0x80; - state->buffer[63] = state->databitlen & 0xff; - state->buffer[62] = (state->databitlen >> 8) & 0xff; - state->buffer[61] = (state->databitlen >> 16) & 0xff; - state->buffer[60] = (state->databitlen >> 24) & 0xff; - state->buffer[59] = (state->databitlen >> 32) & 0xff; - state->buffer[58] = (state->databitlen >> 40) & 0xff; - state->buffer[57] = (state->databitlen >> 48) & 0xff; - state->buffer[56] = (state->databitlen >> 56) & 0xff; - F8(state); - } - else { - /*set the rest of the bytes in the buffer to 0*/ - if ( (state->datasize_in_buffer & 7) == 0) - for (i = (state->databitlen & 0x1ff) >> 3; i < 64; i++) state->buffer[i] = 0; - else - for (i = ((state->databitlen & 0x1ff) >> 3)+1; i < 64; i++) state->buffer[i] = 0; - - /*pad and process the partial block when databitlen is not multiple of 512 bits, then hash the padded blocks*/ - state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7- (state->databitlen & 7)); - - F8(state); - memset(state->buffer, 0, 64); - state->buffer[63] = state->databitlen & 0xff; - state->buffer[62] = (state->databitlen >> 8) & 0xff; - state->buffer[61] = (state->databitlen >> 16) & 0xff; - state->buffer[60] = (state->databitlen >> 24) & 0xff; - state->buffer[59] = (state->databitlen >> 32) & 0xff; - state->buffer[58] = (state->databitlen >> 40) & 0xff; - state->buffer[57] = (state->databitlen >> 48) & 0xff; - state->buffer[56] = (state->databitlen >> 56) & 0xff; - F8(state); - } - - /*truncating the final hash value to generate the message digest*/ - switch(state->hashbitlen) { - case 224: memcpy(hashval,(unsigned char*)state->x+64+36,28); break; - case 256: memcpy(hashval,(unsigned char*)state->x+64+32,32); break; - case 384: memcpy(hashval,(unsigned char*)state->x+64+16,48); break; - case 512: memcpy(hashval,(unsigned char*)state->x+64,64); break; - } - - return(SUCCESS); -} - -/* hash a message, - three inputs: message digest size in bits (hashbitlen); message (data); message length in bits (databitlen) - one output: message digest (hashval) -*/ -HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval) -{ - hashState state; - - if ( hashbitlen == 224 || hashbitlen == 256 || hashbitlen == 384 || hashbitlen == 512 ) { - Init(&state, hashbitlen); - Update(&state, data, databitlen); - Final(&state, hashval); - return SUCCESS; - } - else - return(BAD_HASHLEN); -} diff --git a/src/Native/libcryptonote/crypto/jh.h b/src/Native/libcryptonote/crypto/jh.h deleted file mode 100644 index 627a9ff05..000000000 --- a/src/Native/libcryptonote/crypto/jh.h +++ /dev/null @@ -1,21 +0,0 @@ -/*This program gives the 64-bit optimized bitslice implementation of JH using ANSI C - - -------------------------------- - Performance - - Microprocessor: Intel CORE 2 processor (Core 2 Duo Mobile T6600 2.2GHz) - Operating System: 64-bit Ubuntu 10.04 (Linux kernel 2.6.32-22-generic) - Speed for long message: - 1) 45.8 cycles/byte compiler: Intel C++ Compiler 11.1 compilation option: icc -O2 - 2) 56.8 cycles/byte compiler: gcc 4.4.3 compilation option: gcc -O3 - - -------------------------------- - Last Modified: January 16, 2011 -*/ -#pragma once - -typedef unsigned char BitSequence; -typedef unsigned long long DataLength; -typedef enum {SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2} HashReturn; - -HashReturn jh_hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval); diff --git a/src/Native/libcryptonote/crypto/keccak.c b/src/Native/libcryptonote/crypto/keccak.c index 95fb3d33d..3ee2a887c 100644 --- a/src/Native/libcryptonote/crypto/keccak.c +++ b/src/Native/libcryptonote/crypto/keccak.c @@ -2,25 +2,9 @@ // 19-Nov-11 Markku-Juhani O. Saarinen // A baseline Keccak (3rd round) implementation. -#include -#include #include "hash-ops.h" #include "keccak.h" -#ifndef _WIN32 -#include -#endif - -static void local_abort(const char *msg) -{ - fprintf(stderr, "%s\n", msg); -#ifdef NDEBUG - _exit(1); -#else - abort(); -#endif -} - const uint64_t keccakf_rndc[24] = { 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, @@ -89,17 +73,11 @@ void keccakf(uint64_t st[25], int rounds) // compute a keccak hash (md) of given byte length from "in" typedef uint64_t state_t[25]; -void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen) +int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen) { state_t st; uint8_t temp[144]; - size_t i, rsiz, rsizw; - - static_assert(HASH_DATA_AREA <= sizeof(temp), "Bad keccak preconditions"); - if (mdlen <= 0 || (mdlen > 100 && sizeof(st) != (size_t)mdlen)) - { - local_abort("Bad keccak use"); - } + int i, rsiz, rsizw; rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen; rsizw = rsiz / 8; @@ -113,11 +91,6 @@ void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen) } // last block and padding - if (inlen + 1 >= sizeof(temp) || inlen > rsiz || rsiz - inlen + inlen + 1 >= sizeof(temp) || rsiz == 0 || rsiz - 1 >= sizeof(temp) || rsizw * 8 > sizeof(temp)) - { - local_abort("Bad keccak use"); - } - memcpy(temp, in, inlen); temp[inlen++] = 1; memset(temp + inlen, 0, rsiz - inlen); @@ -129,9 +102,11 @@ void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen) keccakf(st, KECCAK_ROUNDS); memcpy(md, st, mdlen); + + return 0; } -void keccak1600(const uint8_t *in, size_t inlen, uint8_t *md) +void keccak1600(const uint8_t *in, int inlen, uint8_t *md) { keccak(in, inlen, md, sizeof(state_t)); } diff --git a/src/Native/libcryptonote/crypto/keccak.h b/src/Native/libcryptonote/crypto/keccak.h index fb9d8bd04..4f7f85729 100644 --- a/src/Native/libcryptonote/crypto/keccak.h +++ b/src/Native/libcryptonote/crypto/keccak.h @@ -16,11 +16,11 @@ #endif // compute a keccak hash (md) of given byte length from "in" -void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen); +int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen); // update the state void keccakf(uint64_t st[25], int norounds); -void keccak1600(const uint8_t *in, size_t inlen, uint8_t *md); +void keccak1600(const uint8_t *in, int inlen, uint8_t *md); #endif diff --git a/src/Native/libcryptonote/crypto/oaes_config.h b/src/Native/libcryptonote/crypto/oaes_config.h deleted file mode 100644 index 3fc0e1be5..000000000 --- a/src/Native/libcryptonote/crypto/oaes_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _OAES_CONFIG_H -#define _OAES_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -//#ifndef OAES_HAVE_ISAAC -//#define OAES_HAVE_ISAAC 1 -//#endif // OAES_HAVE_ISAAC - -//#ifndef OAES_DEBUG -//#define OAES_DEBUG 0 -//#endif // OAES_DEBUG - -#ifdef __cplusplus -} -#endif - -#endif // _OAES_CONFIG_H diff --git a/src/Native/libcryptonote/crypto/oaes_lib.c b/src/Native/libcryptonote/crypto/oaes_lib.c deleted file mode 100644 index aa7c3ee4b..000000000 --- a/src/Native/libcryptonote/crypto/oaes_lib.c +++ /dev/null @@ -1,1506 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ -#include -#include -#include -#include -#include - -// OS X, FreeBSD, and OpenBSD don't need malloc.h -#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) \ - && !defined(__DragonFly__) - #include -#endif - -// ANDROID, FreeBSD, and OpenBSD also don't need timeb.h -#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__ANDROID__) - #include -#else - #include -#endif - -#ifdef _WIN32 -#include -#else -#include -#include -#endif - -#ifdef _MSC_VER -#define GETPID() _getpid() -#else -#define GETPID() getpid() -#endif - -#include "oaes_config.h" -#include "oaes_lib.h" - -#ifdef OAES_HAVE_ISAAC -#include "rand.h" -#endif // OAES_HAVE_ISAAC - -#define OAES_RKEY_LEN 4 -#define OAES_COL_LEN 4 -#define OAES_ROUND_BASE 7 - -// the block is padded -#define OAES_FLAG_PAD 0x01 - -#ifndef min -# define min(a,b) (((a)<(b)) ? (a) : (b)) -#endif /* min */ - -// "OAES<8-bit header version><8-bit type><16-bit options><8-bit flags><56-bit reserved>" -static uint8_t oaes_header[OAES_BLOCK_SIZE] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x4f, 0x41, 0x45, 0x53, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t oaes_gf_8[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; - -static uint8_t oaes_sub_byte_value[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 }, - /*1*/ { 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 }, - /*2*/ { 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 }, - /*3*/ { 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 }, - /*4*/ { 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 }, - /*5*/ { 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf }, - /*6*/ { 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 }, - /*7*/ { 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 }, - /*8*/ { 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 }, - /*9*/ { 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb }, - /*a*/ { 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 }, - /*b*/ { 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 }, - /*c*/ { 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a }, - /*d*/ { 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e }, - /*e*/ { 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf }, - /*f*/ { 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }, -}; - -static uint8_t oaes_inv_sub_byte_value[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb }, - /*1*/ { 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb }, - /*2*/ { 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e }, - /*3*/ { 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 }, - /*4*/ { 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 }, - /*5*/ { 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 }, - /*6*/ { 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 }, - /*7*/ { 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b }, - /*8*/ { 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 }, - /*9*/ { 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e }, - /*a*/ { 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b }, - /*b*/ { 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 }, - /*c*/ { 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f }, - /*d*/ { 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef }, - /*e*/ { 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 }, - /*f*/ { 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }, -}; - -static uint8_t oaes_gf_mul_2[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, - /*1*/ { 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e }, - /*2*/ { 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e }, - /*3*/ { 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e }, - /*4*/ { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e }, - /*5*/ { 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe }, - /*6*/ { 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde }, - /*7*/ { 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe }, - /*8*/ { 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05 }, - /*9*/ { 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25 }, - /*a*/ { 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45 }, - /*b*/ { 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65 }, - /*c*/ { 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85 }, - /*d*/ { 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5 }, - /*e*/ { 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5 }, - /*f*/ { 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 }, -}; - -static uint8_t oaes_gf_mul_3[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, - /*1*/ { 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21 }, - /*2*/ { 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71 }, - /*3*/ { 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41 }, - /*4*/ { 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1 }, - /*5*/ { 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1 }, - /*6*/ { 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1 }, - /*7*/ { 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81 }, - /*8*/ { 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a }, - /*9*/ { 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba }, - /*a*/ { 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea }, - /*b*/ { 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda }, - /*c*/ { 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a }, - /*d*/ { 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a }, - /*e*/ { 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a }, - /*f*/ { 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a }, -}; - -static uint8_t oaes_gf_mul_9[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, - /*1*/ { 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7 }, - /*2*/ { 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c }, - /*3*/ { 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc }, - /*4*/ { 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01 }, - /*5*/ { 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91 }, - /*6*/ { 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a }, - /*7*/ { 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa }, - /*8*/ { 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b }, - /*9*/ { 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b }, - /*a*/ { 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0 }, - /*b*/ { 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30 }, - /*c*/ { 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed }, - /*d*/ { 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d }, - /*e*/ { 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6 }, - /*f*/ { 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46 }, -}; - -static uint8_t oaes_gf_mul_b[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, - /*1*/ { 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9 }, - /*2*/ { 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12 }, - /*3*/ { 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2 }, - /*4*/ { 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f }, - /*5*/ { 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f }, - /*6*/ { 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4 }, - /*7*/ { 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54 }, - /*8*/ { 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e }, - /*9*/ { 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e }, - /*a*/ { 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5 }, - /*b*/ { 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55 }, - /*c*/ { 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68 }, - /*d*/ { 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8 }, - /*e*/ { 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13 }, - /*f*/ { 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3 }, -}; - -static uint8_t oaes_gf_mul_d[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, - /*1*/ { 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b }, - /*2*/ { 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0 }, - /*3*/ { 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20 }, - /*4*/ { 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26 }, - /*5*/ { 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6 }, - /*6*/ { 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d }, - /*7*/ { 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d }, - /*8*/ { 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91 }, - /*9*/ { 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41 }, - /*a*/ { 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a }, - /*b*/ { 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa }, - /*c*/ { 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc }, - /*d*/ { 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c }, - /*e*/ { 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47 }, - /*f*/ { 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97 }, -}; - -static uint8_t oaes_gf_mul_e[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, - /*1*/ { 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba }, - /*2*/ { 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81 }, - /*3*/ { 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61 }, - /*4*/ { 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7 }, - /*5*/ { 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17 }, - /*6*/ { 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c }, - /*7*/ { 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc }, - /*8*/ { 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b }, - /*9*/ { 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb }, - /*a*/ { 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0 }, - /*b*/ { 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20 }, - /*c*/ { 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6 }, - /*d*/ { 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56 }, - /*e*/ { 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d }, - /*f*/ { 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d }, -}; - -static OAES_RET oaes_sub_byte( uint8_t * byte ) -{ - size_t _x, _y; - - if( NULL == byte ) - return OAES_RET_ARG1; - - _x = _y = *byte; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - *byte = oaes_sub_byte_value[_y][_x]; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_sub_byte( uint8_t * byte ) -{ - size_t _x, _y; - - if( NULL == byte ) - return OAES_RET_ARG1; - - _x = _y = *byte; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - *byte = oaes_inv_sub_byte_value[_y][_x]; - - return OAES_RET_SUCCESS; -} -/* -static OAES_RET oaes_word_rot_right( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - memcpy( _temp + 1, word, OAES_COL_LEN - 1 ); - _temp[0] = word[OAES_COL_LEN - 1]; - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} -*/ -static OAES_RET oaes_word_rot_left( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - memcpy( _temp, word + 1, OAES_COL_LEN - 1 ); - _temp[OAES_COL_LEN - 1] = word[0]; - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_shift_rows( uint8_t block[OAES_BLOCK_SIZE] ) -{ - uint8_t _temp[OAES_BLOCK_SIZE]; - - if( NULL == block ) - return OAES_RET_ARG1; - - _temp[0x00] = block[0x00]; - _temp[0x01] = block[0x05]; - _temp[0x02] = block[0x0a]; - _temp[0x03] = block[0x0f]; - _temp[0x04] = block[0x04]; - _temp[0x05] = block[0x09]; - _temp[0x06] = block[0x0e]; - _temp[0x07] = block[0x03]; - _temp[0x08] = block[0x08]; - _temp[0x09] = block[0x0d]; - _temp[0x0a] = block[0x02]; - _temp[0x0b] = block[0x07]; - _temp[0x0c] = block[0x0c]; - _temp[0x0d] = block[0x01]; - _temp[0x0e] = block[0x06]; - _temp[0x0f] = block[0x0b]; - memcpy( block, _temp, OAES_BLOCK_SIZE ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_shift_rows( uint8_t block[OAES_BLOCK_SIZE] ) -{ - uint8_t _temp[OAES_BLOCK_SIZE]; - - if( NULL == block ) - return OAES_RET_ARG1; - - _temp[0x00] = block[0x00]; - _temp[0x01] = block[0x0d]; - _temp[0x02] = block[0x0a]; - _temp[0x03] = block[0x07]; - _temp[0x04] = block[0x04]; - _temp[0x05] = block[0x01]; - _temp[0x06] = block[0x0e]; - _temp[0x07] = block[0x0b]; - _temp[0x08] = block[0x08]; - _temp[0x09] = block[0x05]; - _temp[0x0a] = block[0x02]; - _temp[0x0b] = block[0x0f]; - _temp[0x0c] = block[0x0c]; - _temp[0x0d] = block[0x09]; - _temp[0x0e] = block[0x06]; - _temp[0x0f] = block[0x03]; - memcpy( block, _temp, OAES_BLOCK_SIZE ); - - return OAES_RET_SUCCESS; -} - -static uint8_t oaes_gf_mul(uint8_t left, uint8_t right) -{ - size_t _x, _y; - - _x = _y = left; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - - switch( right ) - { - case 0x02: - return oaes_gf_mul_2[_y][_x]; - break; - case 0x03: - return oaes_gf_mul_3[_y][_x]; - break; - case 0x09: - return oaes_gf_mul_9[_y][_x]; - break; - case 0x0b: - return oaes_gf_mul_b[_y][_x]; - break; - case 0x0d: - return oaes_gf_mul_d[_y][_x]; - break; - case 0x0e: - return oaes_gf_mul_e[_y][_x]; - break; - default: - return left; - break; - } -} - -static OAES_RET oaes_mix_cols( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - _temp[0] = oaes_gf_mul(word[0], 0x02) ^ oaes_gf_mul( word[1], 0x03 ) ^ - word[2] ^ word[3]; - _temp[1] = word[0] ^ oaes_gf_mul( word[1], 0x02 ) ^ - oaes_gf_mul( word[2], 0x03 ) ^ word[3]; - _temp[2] = word[0] ^ word[1] ^ - oaes_gf_mul( word[2], 0x02 ) ^ oaes_gf_mul( word[3], 0x03 ); - _temp[3] = oaes_gf_mul( word[0], 0x03 ) ^ word[1] ^ - word[2] ^ oaes_gf_mul( word[3], 0x02 ); - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_mix_cols( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - _temp[0] = oaes_gf_mul( word[0], 0x0e ) ^ oaes_gf_mul( word[1], 0x0b ) ^ - oaes_gf_mul( word[2], 0x0d ) ^ oaes_gf_mul( word[3], 0x09 ); - _temp[1] = oaes_gf_mul( word[0], 0x09 ) ^ oaes_gf_mul( word[1], 0x0e ) ^ - oaes_gf_mul( word[2], 0x0b ) ^ oaes_gf_mul( word[3], 0x0d ); - _temp[2] = oaes_gf_mul( word[0], 0x0d ) ^ oaes_gf_mul( word[1], 0x09 ) ^ - oaes_gf_mul( word[2], 0x0e ) ^ oaes_gf_mul( word[3], 0x0b ); - _temp[3] = oaes_gf_mul( word[0], 0x0b ) ^ oaes_gf_mul( word[1], 0x0d ) ^ - oaes_gf_mul( word[2], 0x09 ) ^ oaes_gf_mul( word[3], 0x0e ); - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_sprintf( - char * buf, size_t * buf_len, const uint8_t * data, size_t data_len ) -{ - size_t _i, _buf_len_in; - char _temp[4]; - - if( NULL == buf_len ) - return OAES_RET_ARG2; - - _buf_len_in = *buf_len; - *buf_len = data_len * 3 + data_len / OAES_BLOCK_SIZE + 1; - - if( NULL == buf ) - return OAES_RET_SUCCESS; - - if( *buf_len > _buf_len_in ) - return OAES_RET_BUF; - - if( NULL == data ) - return OAES_RET_ARG3; - - strcpy( buf, "" ); - - for( _i = 0; _i < data_len; _i++ ) - { - sprintf( _temp, "%02x ", data[_i] ); - strcat( buf, _temp ); - if( _i && 0 == ( _i + 1 ) % OAES_BLOCK_SIZE ) - strcat( buf, "\n" ); - } - - return OAES_RET_SUCCESS; -} - -#ifdef OAES_HAVE_ISAAC -static void oaes_get_seed( char buf[RANDSIZ + 1] ) -{ - #if !defined(__FreeBSD__) && !defined(__OpenBSD__) - struct timeb timer; - struct tm *gmTimer; - char * _test = NULL; - - ftime (&timer); - gmTimer = gmtime( &timer.time ); - _test = (char *) calloc( sizeof( char ), timer.millitm ); - sprintf( buf, "%04d%02d%02d%02d%02d%02d%03d%p%d", - gmTimer->tm_year + 1900, gmTimer->tm_mon + 1, gmTimer->tm_mday, - gmTimer->tm_hour, gmTimer->tm_min, gmTimer->tm_sec, timer.millitm, - _test + timer.millitm, GETPID() ); - #else - struct timeval timer; - struct tm *gmTimer; - char * _test = NULL; - - gettimeofday(&timer, NULL); - gmTimer = gmtime( &timer.tv_sec ); - _test = (char *) calloc( sizeof( char ), timer.tv_usec/1000 ); - sprintf( buf, "%04d%02d%02d%02d%02d%02d%03d%p%d", - gmTimer->tm_year + 1900, gmTimer->tm_mon + 1, gmTimer->tm_mday, - gmTimer->tm_hour, gmTimer->tm_min, gmTimer->tm_sec, timer.tv_usec/1000, - _test + timer.tv_usec/1000, GETPID() ); - #endif - - if( _test ) - free( _test ); -} -#else -static uint32_t oaes_get_seed(void) -{ - #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__ANDROID__) - struct timeb timer; - struct tm *gmTimer; - char * _test = NULL; - uint32_t _ret = 0; - - ftime (&timer); - gmTimer = gmtime( &timer.time ); - _test = (char *) calloc( sizeof( char ), timer.millitm ); - _ret = gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday + - gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.millitm + - (uintptr_t) ( _test + timer.millitm ) + GETPID(); - #else - struct timeval timer; - struct tm *gmTimer; - char * _test = NULL; - uint32_t _ret = 0; - - gettimeofday(&timer, NULL); - gmTimer = gmtime( &timer.tv_sec ); - _test = (char *) calloc( sizeof( char ), timer.tv_usec/1000 ); - _ret = gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday + - gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.tv_usec/1000 + - (uintptr_t) ( _test + timer.tv_usec/1000 ) + GETPID(); - #endif - - if( _test ) - free( _test ); - - return _ret; -} -#endif // OAES_HAVE_ISAAC - -static OAES_RET oaes_key_destroy( oaes_key ** key ) -{ - if( NULL == *key ) - return OAES_RET_SUCCESS; - - if( (*key)->data ) - { - free( (*key)->data ); - (*key)->data = NULL; - } - - if( (*key)->exp_data ) - { - free( (*key)->exp_data ); - (*key)->exp_data = NULL; - } - - (*key)->data_len = 0; - (*key)->exp_data_len = 0; - (*key)->num_keys = 0; - (*key)->key_base = 0; - free( *key ); - *key = NULL; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_key_expand( OAES_CTX * ctx ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - _ctx->key->key_base = _ctx->key->data_len / OAES_RKEY_LEN; - _ctx->key->num_keys = _ctx->key->key_base + OAES_ROUND_BASE; - - _ctx->key->exp_data_len = _ctx->key->num_keys * OAES_RKEY_LEN * OAES_COL_LEN; - _ctx->key->exp_data = (uint8_t *) - calloc( _ctx->key->exp_data_len, sizeof( uint8_t )); - - if( NULL == _ctx->key->exp_data ) - return OAES_RET_MEM; - - // the first _ctx->key->data_len are a direct copy - memcpy( _ctx->key->exp_data, _ctx->key->data, _ctx->key->data_len ); - - // apply ExpandKey algorithm for remainder - for( _i = _ctx->key->key_base; _i < _ctx->key->num_keys * OAES_RKEY_LEN; _i++ ) - { - uint8_t _temp[OAES_COL_LEN]; - - memcpy( _temp, - _ctx->key->exp_data + ( _i - 1 ) * OAES_RKEY_LEN, OAES_COL_LEN ); - - // transform key column - if( 0 == _i % _ctx->key->key_base ) - { - oaes_word_rot_left( _temp ); - - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - oaes_sub_byte( _temp + _j ); - - _temp[0] = _temp[0] ^ oaes_gf_8[ _i / _ctx->key->key_base - 1 ]; - } - else if( _ctx->key->key_base > 6 && 4 == _i % _ctx->key->key_base ) - { - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - oaes_sub_byte( _temp + _j ); - } - - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - { - _ctx->key->exp_data[ _i * OAES_RKEY_LEN + _j ] = - _ctx->key->exp_data[ ( _i - _ctx->key->key_base ) * - OAES_RKEY_LEN + _j ] ^ _temp[_j]; - } - } - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_key_gen( OAES_CTX * ctx, size_t key_size ) -{ - size_t _i; - oaes_key * _key = NULL; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - _key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _key ) - return OAES_RET_MEM; - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _key->data_len = key_size; - _key->data = (uint8_t *) calloc( key_size, sizeof( uint8_t )); - - if( NULL == _key->data ) - { - free( _key ); - return OAES_RET_MEM; - } - - for( _i = 0; _i < key_size; _i++ ) -#ifdef OAES_HAVE_ISAAC - _key->data[_i] = (uint8_t) rand( _ctx->rctx ); -#else - _key->data[_i] = (uint8_t) rand(); -#endif // OAES_HAVE_ISAAC - - _ctx->key = _key; - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_gen_128( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 16 ); -} - -OAES_RET oaes_key_gen_192( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 24 ); -} - -OAES_RET oaes_key_gen_256( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 32 ); -} - -OAES_RET oaes_key_export( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ) -{ - size_t _data_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - if( NULL == data_len ) - return OAES_RET_ARG3; - - _data_len_in = *data_len; - // data + header - *data_len = _ctx->key->data_len + OAES_BLOCK_SIZE; - - if( NULL == data ) - return OAES_RET_SUCCESS; - - if( _data_len_in < *data_len ) - return OAES_RET_BUF; - - // header - memcpy( data, oaes_header, OAES_BLOCK_SIZE ); - data[5] = 0x01; - data[7] = _ctx->key->data_len; - memcpy( data + OAES_BLOCK_SIZE, _ctx->key->data, _ctx->key->data_len ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_export_data( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ) -{ - size_t _data_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - if( NULL == data_len ) - return OAES_RET_ARG3; - - _data_len_in = *data_len; - *data_len = _ctx->key->data_len; - - if( NULL == data ) - return OAES_RET_SUCCESS; - - if( _data_len_in < *data_len ) - return OAES_RET_BUF; - - memcpy( data, _ctx->key->data, *data_len ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_import( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ) -{ - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - int _key_length; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == data ) - return OAES_RET_ARG2; - - switch( data_len ) - { - case 16 + OAES_BLOCK_SIZE: - case 24 + OAES_BLOCK_SIZE: - case 32 + OAES_BLOCK_SIZE: - break; - default: - return OAES_RET_ARG3; - } - - // header - if( 0 != memcmp( data, oaes_header, 4 ) ) - return OAES_RET_HEADER; - - // header version - switch( data[4] ) - { - case 0x01: - break; - default: - return OAES_RET_HEADER; - } - - // header type - switch( data[5] ) - { - case 0x01: - break; - default: - return OAES_RET_HEADER; - } - - // options - _key_length = data[7]; - switch( _key_length ) - { - case 16: - case 24: - case 32: - break; - default: - return OAES_RET_HEADER; - } - - if( (int)data_len != _key_length + OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _ctx->key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _ctx->key ) - return OAES_RET_MEM; - - _ctx->key->data_len = _key_length; - _ctx->key->data = (uint8_t *) - calloc( _key_length, sizeof( uint8_t )); - - if( NULL == _ctx->key->data ) - { - oaes_key_destroy( &(_ctx->key) ); - return OAES_RET_MEM; - } - - memcpy( _ctx->key->data, data + OAES_BLOCK_SIZE, _key_length ); - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_import_data( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ) -{ - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == data ) - return OAES_RET_ARG2; - - switch( data_len ) - { - case 16: - case 24: - case 32: - break; - default: - return OAES_RET_ARG3; - } - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _ctx->key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _ctx->key ) - return OAES_RET_MEM; - - _ctx->key->data_len = data_len; - _ctx->key->data = (uint8_t *) - calloc( data_len, sizeof( uint8_t )); - - if( NULL == _ctx->key->data ) - { - oaes_key_destroy( &(_ctx->key) ); - return OAES_RET_MEM; - } - - memcpy( _ctx->key->data, data, data_len ); - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_CTX * oaes_alloc(void) -{ - oaes_ctx * _ctx = (oaes_ctx *) calloc( sizeof( oaes_ctx ), 1 ); - - if( NULL == _ctx ) - return NULL; - -#ifdef OAES_HAVE_ISAAC - { - ub4 _i = 0; - char _seed[RANDSIZ + 1]; - - _ctx->rctx = (randctx *) calloc( sizeof( randctx ), 1 ); - - if( NULL == _ctx->rctx ) - { - free( _ctx ); - return NULL; - } - - oaes_get_seed( _seed ); - memset( _ctx->rctx->randrsl, 0, RANDSIZ ); - memcpy( _ctx->rctx->randrsl, _seed, RANDSIZ ); - randinit( _ctx->rctx, TRUE); - } -#else - srand( oaes_get_seed() ); -#endif // OAES_HAVE_ISAAC - - _ctx->key = NULL; - oaes_set_option( _ctx, OAES_OPTION_CBC, NULL ); - -#ifdef OAES_DEBUG - _ctx->step_cb = NULL; - oaes_set_option( _ctx, OAES_OPTION_STEP_OFF, NULL ); -#endif // OAES_DEBUG - - return (OAES_CTX *) _ctx; -} - -OAES_RET oaes_free( OAES_CTX ** ctx ) -{ - oaes_ctx ** _ctx = (oaes_ctx **) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == *_ctx ) - return OAES_RET_SUCCESS; - - if( (*_ctx)->key ) - oaes_key_destroy( &((*_ctx)->key) ); - -#ifdef OAES_HAVE_ISAAC - if( (*_ctx)->rctx ) - { - free( (*_ctx)->rctx ); - (*_ctx)->rctx = NULL; - } -#endif // OAES_HAVE_ISAAC - - free( *_ctx ); - *_ctx = NULL; - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_set_option( OAES_CTX * ctx, - OAES_OPTION option, const void * value ) -{ - size_t _i; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - switch( option ) - { - case OAES_OPTION_ECB: - _ctx->options &= ~OAES_OPTION_CBC; - memset( _ctx->iv, 0, OAES_BLOCK_SIZE ); - break; - - case OAES_OPTION_CBC: - _ctx->options &= ~OAES_OPTION_ECB; - if( value ) - memcpy( _ctx->iv, value, OAES_BLOCK_SIZE ); - else - { - for( _i = 0; _i < OAES_BLOCK_SIZE; _i++ ) -#ifdef OAES_HAVE_ISAAC - _ctx->iv[_i] = (uint8_t) rand( _ctx->rctx ); -#else - _ctx->iv[_i] = (uint8_t) rand(); -#endif // OAES_HAVE_ISAAC - } - break; - -#ifdef OAES_DEBUG - - case OAES_OPTION_STEP_ON: - if( value ) - { - _ctx->options &= ~OAES_OPTION_STEP_OFF; - _ctx->step_cb = value; - } - else - { - _ctx->options &= ~OAES_OPTION_STEP_ON; - _ctx->options |= OAES_OPTION_STEP_OFF; - _ctx->step_cb = NULL; - return OAES_RET_ARG3; - } - break; - - case OAES_OPTION_STEP_OFF: - _ctx->options &= ~OAES_OPTION_STEP_ON; - _ctx->step_cb = NULL; - break; - -#endif // OAES_DEBUG - - default: - return OAES_RET_ARG2; - } - - _ctx->options |= option; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_encrypt_block( - OAES_CTX * ctx, uint8_t * c, size_t c_len ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len != OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "input", 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(State, K0) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[_i]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data, "k_sch", 1, NULL ); - _ctx->step_cb( c, "k_add", 1, NULL ); - } -#endif // OAES_DEBUG - - // for round = 1 step 1 to Nr–1 - for( _i = 1; _i < _ctx->key->num_keys - 1; _i++ ) - { - // SubBytes(state) - for( _j = 0; _j < c_len; _j++ ) - oaes_sub_byte( c + _j ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_box", _i, NULL ); -#endif // OAES_DEBUG - - // ShiftRows(state) - oaes_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_row", _i, NULL ); -#endif // OAES_DEBUG - - // MixColumns(state) - oaes_mix_cols( c ); - oaes_mix_cols( c + 4 ); - oaes_mix_cols( c + 8 ); - oaes_mix_cols( c + 12 ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "m_col", _i, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) - for( _j = 0; _j < c_len; _j++ ) - c[_j] = c[_j] ^ - _ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN + _j]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + _i * OAES_RKEY_LEN * OAES_COL_LEN, - "k_sch", _i, NULL ); - _ctx->step_cb( c, "k_add", _i, NULL ); - } -#endif // OAES_DEBUG - - } - - // SubBytes(state) - for( _i = 0; _i < c_len; _i++ ) - oaes_sub_byte( c + _i ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_box", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // ShiftRows(state) - oaes_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_row", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[ - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN + _i ]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN, - "k_sch", _ctx->key->num_keys - 1, NULL ); - _ctx->step_cb( c, "output", _ctx->key->num_keys - 1, NULL ); - } -#endif // OAES_DEBUG - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_decrypt_block( - OAES_CTX * ctx, uint8_t * c, size_t c_len ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len != OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "iinput", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[ - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN + _i ]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN, - "ik_sch", _ctx->key->num_keys - 1, NULL ); - _ctx->step_cb( c, "ik_add", _ctx->key->num_keys - 1, NULL ); - } -#endif // OAES_DEBUG - - for( _i = _ctx->key->num_keys - 2; _i > 0; _i-- ) - { - // InvShiftRows(state) - oaes_inv_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_row", _i, NULL ); -#endif // OAES_DEBUG - - // InvSubBytes(state) - for( _j = 0; _j < c_len; _j++ ) - oaes_inv_sub_byte( c + _j ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_box", _i, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) - for( _j = 0; _j < c_len; _j++ ) - c[_j] = c[_j] ^ - _ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN + _j]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + _i * OAES_RKEY_LEN * OAES_COL_LEN, - "ik_sch", _i, NULL ); - _ctx->step_cb( c, "ik_add", _i, NULL ); - } -#endif // OAES_DEBUG - - // InvMixColums(state) - oaes_inv_mix_cols( c ); - oaes_inv_mix_cols( c + 4 ); - oaes_inv_mix_cols( c + 8 ); - oaes_inv_mix_cols( c + 12 ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "im_col", _i, NULL ); -#endif // OAES_DEBUG - - } - - // InvShiftRows(state) - oaes_inv_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_row", 1, NULL ); -#endif // OAES_DEBUG - - // InvSubBytes(state) - for( _i = 0; _i < c_len; _i++ ) - oaes_inv_sub_byte( c + _i ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_box", 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[0, Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[_i]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data, "ik_sch", 1, NULL ); - _ctx->step_cb( c, "ioutput", 1, NULL ); - } -#endif // OAES_DEBUG - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_encrypt( OAES_CTX * ctx, - const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len ) -{ - size_t _i, _j, _c_len_in, _c_data_len; - size_t _pad_len = m_len % OAES_BLOCK_SIZE == 0 ? - 0 : OAES_BLOCK_SIZE - m_len % OAES_BLOCK_SIZE; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - uint8_t _flags = _pad_len ? OAES_FLAG_PAD : 0; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == m ) - return OAES_RET_ARG2; - - if( NULL == c_len ) - return OAES_RET_ARG5; - - _c_len_in = *c_len; - // data + pad - _c_data_len = m_len + _pad_len; - // header + iv + data + pad - *c_len = 2 * OAES_BLOCK_SIZE + m_len + _pad_len; - - if( NULL == c ) - return OAES_RET_SUCCESS; - - if( _c_len_in < *c_len ) - return OAES_RET_BUF; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - // header - memcpy(c, oaes_header, OAES_BLOCK_SIZE ); - memcpy(c + 6, &_ctx->options, sizeof(_ctx->options)); - memcpy(c + 8, &_flags, sizeof(_flags)); - // iv - memcpy(c + OAES_BLOCK_SIZE, _ctx->iv, OAES_BLOCK_SIZE ); - // data - memcpy(c + 2 * OAES_BLOCK_SIZE, m, m_len ); - - for( _i = 0; _i < _c_data_len; _i += OAES_BLOCK_SIZE ) - { - uint8_t _block[OAES_BLOCK_SIZE]; - size_t _block_size = min( m_len - _i, OAES_BLOCK_SIZE ); - - memcpy( _block, c + 2 * OAES_BLOCK_SIZE + _i, _block_size ); - - // insert pad - for( _j = 0; _j < OAES_BLOCK_SIZE - _block_size; _j++ ) - _block[ _block_size + _j ] = _j + 1; - - // CBC - if( _ctx->options & OAES_OPTION_CBC ) - { - for( _j = 0; _j < OAES_BLOCK_SIZE; _j++ ) - _block[_j] = _block[_j] ^ _ctx->iv[_j]; - } - - _rc = _rc || - oaes_encrypt_block( ctx, _block, OAES_BLOCK_SIZE ); - memcpy( c + 2 * OAES_BLOCK_SIZE + _i, _block, OAES_BLOCK_SIZE ); - - if( _ctx->options & OAES_OPTION_CBC ) - memcpy( _ctx->iv, _block, OAES_BLOCK_SIZE ); - } - - return _rc; -} - -OAES_RET oaes_decrypt( OAES_CTX * ctx, - const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len ) -{ - size_t _i, _j, _m_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - uint8_t _iv[OAES_BLOCK_SIZE]; - uint8_t _flags; - OAES_OPTION _options; - - if( NULL == ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len % OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == m_len ) - return OAES_RET_ARG5; - - _m_len_in = *m_len; - *m_len = c_len - 2 * OAES_BLOCK_SIZE; - - if( NULL == m ) - return OAES_RET_SUCCESS; - - if( _m_len_in < *m_len ) - return OAES_RET_BUF; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - // header - if( 0 != memcmp( c, oaes_header, 4 ) ) - return OAES_RET_HEADER; - - // header version - switch( c[4] ) - { - case 0x01: - break; - default: - return OAES_RET_HEADER; - } - - // header type - switch( c[5] ) - { - case 0x02: - break; - default: - return OAES_RET_HEADER; - } - - // options - memcpy(&_options, c + 6, sizeof(_options)); - // validate that all options are valid - if( _options & ~( - OAES_OPTION_ECB - | OAES_OPTION_CBC -#ifdef OAES_DEBUG - | OAES_OPTION_STEP_ON - | OAES_OPTION_STEP_OFF -#endif // OAES_DEBUG - ) ) - return OAES_RET_HEADER; - if( ( _options & OAES_OPTION_ECB ) && - ( _options & OAES_OPTION_CBC ) ) - return OAES_RET_HEADER; - if( _options == OAES_OPTION_NONE ) - return OAES_RET_HEADER; - - // flags - memcpy(&_flags, c + 8, sizeof(_flags)); - // validate that all flags are valid - if( _flags & ~( - OAES_FLAG_PAD - ) ) - return OAES_RET_HEADER; - - // iv - memcpy( _iv, c + OAES_BLOCK_SIZE, OAES_BLOCK_SIZE); - // data + pad - memcpy( m, c + 2 * OAES_BLOCK_SIZE, *m_len ); - - for( _i = 0; _i < *m_len; _i += OAES_BLOCK_SIZE ) - { - if( ( _options & OAES_OPTION_CBC ) && _i > 0 ) - memcpy( _iv, c + OAES_BLOCK_SIZE + _i, OAES_BLOCK_SIZE ); - - _rc = _rc || - oaes_decrypt_block( ctx, m + _i, min( *m_len - _i, OAES_BLOCK_SIZE ) ); - - // CBC - if( _options & OAES_OPTION_CBC ) - { - for( _j = 0; _j < OAES_BLOCK_SIZE; _j++ ) - m[ _i + _j ] = m[ _i + _j ] ^ _iv[_j]; - } - } - - // remove pad - if( _flags & OAES_FLAG_PAD ) - { - int _is_pad = 1; - size_t _temp = (size_t) m[*m_len - 1]; - - if( _temp <= 0x00 || _temp > 0x0f ) - return OAES_RET_HEADER; - for( _i = 0; _i < _temp; _i++ ) - if( m[*m_len - 1 - _i] != _temp - _i ) - _is_pad = 0; - if( _is_pad ) - { - memset( m + *m_len - _temp, 0, _temp ); - *m_len -= _temp; - } - else - return OAES_RET_HEADER; - } - - return OAES_RET_SUCCESS; -} - - -OAES_API OAES_RET oaes_encryption_round( const uint8_t * key, uint8_t * c ) -{ - size_t _i; - - if( NULL == key ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - // SubBytes(state) - for( _i = 0; _i < OAES_BLOCK_SIZE; _i++ ) - oaes_sub_byte( c + _i ); - - // ShiftRows(state) - oaes_shift_rows( c ); - - // MixColumns(state) - oaes_mix_cols( c ); - oaes_mix_cols( c + 4 ); - oaes_mix_cols( c + 8 ); - oaes_mix_cols( c + 12 ); - - // AddRoundKey(State, key) - for( _i = 0; _i < OAES_BLOCK_SIZE; _i++ ) - c[_i] ^= key[_i]; - - return OAES_RET_SUCCESS; -} - -OAES_API OAES_RET oaes_pseudo_encrypt_ecb( OAES_CTX * ctx, uint8_t * c ) -{ - size_t _i; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - for ( _i = 0; _i < 10; ++_i ) - { - oaes_encryption_round( &_ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN], c ); - } - - return OAES_RET_SUCCESS; -} diff --git a/src/Native/libcryptonote/crypto/oaes_lib.h b/src/Native/libcryptonote/crypto/oaes_lib.h deleted file mode 100644 index fd1942822..000000000 --- a/src/Native/libcryptonote/crypto/oaes_lib.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _OAES_LIB_H -#define _OAES_LIB_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -# ifdef OAES_SHARED -# ifdef oaes_lib_EXPORTS -# define OAES_API __declspec(dllexport) -# else -# define OAES_API __declspec(dllimport) -# endif -# else -# define OAES_API -# endif -#else -# define OAES_API -#endif // WIN32 - -#define OAES_VERSION "0.8.1" -#define OAES_BLOCK_SIZE 16 - -typedef void OAES_CTX; - -typedef enum -{ - OAES_RET_FIRST = 0, - OAES_RET_SUCCESS = 0, - OAES_RET_UNKNOWN, - OAES_RET_ARG1, - OAES_RET_ARG2, - OAES_RET_ARG3, - OAES_RET_ARG4, - OAES_RET_ARG5, - OAES_RET_NOKEY, - OAES_RET_MEM, - OAES_RET_BUF, - OAES_RET_HEADER, - OAES_RET_COUNT -} OAES_RET; - -/* - * oaes_set_option() takes one of these values for its [option] parameter - * some options accept either an optional or a required [value] parameter - */ -// no option -#define OAES_OPTION_NONE 0 -// enable ECB mode, disable CBC mode -#define OAES_OPTION_ECB 1 -// enable CBC mode, disable ECB mode -// value is optional, may pass uint8_t iv[OAES_BLOCK_SIZE] to specify -// the value of the initialization vector, iv -#define OAES_OPTION_CBC 2 - -#ifdef OAES_DEBUG -typedef int ( * oaes_step_cb ) ( - const uint8_t state[OAES_BLOCK_SIZE], - const char * step_name, - int step_count, - void * user_data ); -// enable state stepping mode -// value is required, must pass oaes_step_cb to receive the state at each step -#define OAES_OPTION_STEP_ON 4 -// disable state stepping mode -#define OAES_OPTION_STEP_OFF 8 -#endif // OAES_DEBUG - -typedef uint16_t OAES_OPTION; - -typedef struct _oaes_key -{ - size_t data_len; - uint8_t *data; - size_t exp_data_len; - uint8_t *exp_data; - size_t num_keys; - size_t key_base; -} oaes_key; - -typedef struct _oaes_ctx -{ -#ifdef OAES_HAVE_ISAAC - randctx * rctx; -#endif // OAES_HAVE_ISAAC - -#ifdef OAES_DEBUG - oaes_step_cb step_cb; -#endif // OAES_DEBUG - - oaes_key * key; - OAES_OPTION options; - uint8_t iv[OAES_BLOCK_SIZE]; -} oaes_ctx; -/* - * // usage: - * - * OAES_CTX * ctx = oaes_alloc(); - * . - * . - * . - * { - * oaes_gen_key_xxx( ctx ); - * { - * oaes_key_export( ctx, _buf, &_buf_len ); - * // or - * oaes_key_export_data( ctx, _buf, &_buf_len );\ - * } - * } - * // or - * { - * oaes_key_import( ctx, _buf, _buf_len ); - * // or - * oaes_key_import_data( ctx, _buf, _buf_len ); - * } - * . - * . - * . - * oaes_encrypt( ctx, m, m_len, c, &c_len ); - * . - * . - * . - * oaes_decrypt( ctx, c, c_len, m, &m_len ); - * . - * . - * . - * oaes_free( &ctx ); - */ - -OAES_API OAES_CTX * oaes_alloc(void); - -OAES_API OAES_RET oaes_free( OAES_CTX ** ctx ); - -OAES_API OAES_RET oaes_set_option( OAES_CTX * ctx, - OAES_OPTION option, const void * value ); - -OAES_API OAES_RET oaes_key_gen_128( OAES_CTX * ctx ); - -OAES_API OAES_RET oaes_key_gen_192( OAES_CTX * ctx ); - -OAES_API OAES_RET oaes_key_gen_256( OAES_CTX * ctx ); - -// export key with header information -// set data == NULL to get the required data_len -OAES_API OAES_RET oaes_key_export( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ); - -// directly export the data from key -// set data == NULL to get the required data_len -OAES_API OAES_RET oaes_key_export_data( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ); - -// import key with header information -OAES_API OAES_RET oaes_key_import( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ); - -// directly import data into key -OAES_API OAES_RET oaes_key_import_data( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ); - -// set c == NULL to get the required c_len -OAES_API OAES_RET oaes_encrypt( OAES_CTX * ctx, - const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len ); - -// set m == NULL to get the required m_len -OAES_API OAES_RET oaes_decrypt( OAES_CTX * ctx, - const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len ); - -// set buf == NULL to get the required buf_len -OAES_API OAES_RET oaes_sprintf( - char * buf, size_t * buf_len, const uint8_t * data, size_t data_len ); - -OAES_API OAES_RET oaes_encryption_round( const uint8_t * key, uint8_t * c ); - -OAES_API OAES_RET oaes_pseudo_encrypt_ecb( OAES_CTX * ctx, uint8_t * c ); - -#ifdef __cplusplus -} -#endif - -#endif // _OAES_LIB_H diff --git a/src/Native/libcryptonote/crypto/random.c b/src/Native/libcryptonote/crypto/random.c deleted file mode 100644 index 9e1a70a2d..000000000 --- a/src/Native/libcryptonote/crypto/random.c +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include -#include - -#include "hash-ops.h" -#include "initializer.h" -#include "random.h" - -static void generate_system_random_bytes(size_t n, void *result); - -#if defined(_WIN32) - -#include -#include -#include - -static void generate_system_random_bytes(size_t n, void *result) { - HCRYPTPROV prov; -#ifdef NDEBUG -#define must_succeed(x) do if (!(x)) { fprintf(stderr, "Failed: " #x); _exit(1); } while (0) -#else -#define must_succeed(x) do if (!(x)) abort(); while (0) -#endif - must_succeed(CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)); - must_succeed(CryptGenRandom(prov, (DWORD)n, result)); - must_succeed(CryptReleaseContext(prov, 0)); -#undef must_succeed -} - -#else - -#include -#include -#include -#include -#include -#include -#include - -static void generate_system_random_bytes(size_t n, void *result) { - int fd; - if ((fd = open("/dev/urandom", O_RDONLY | O_NOCTTY | O_CLOEXEC)) < 0) { - err(EXIT_FAILURE, "open /dev/urandom"); - } - for (;;) { - ssize_t res = read(fd, result, n); - if ((size_t) res == n) { - break; - } - if (res < 0) { - if (errno != EINTR) { - err(EXIT_FAILURE, "read /dev/urandom"); - } - } else if (res == 0) { - errx(EXIT_FAILURE, "read /dev/urandom: end of file"); - } else { - result = padd(result, (size_t) res); - n -= (size_t) res; - } - } - if (close(fd) < 0) { - err(EXIT_FAILURE, "close /dev/urandom"); - } -} - -#endif - -static union hash_state state; - -#if !defined(NDEBUG) -static volatile int curstate; /* To catch thread safety problems. */ -#endif - -FINALIZER(deinit_random) { -#if !defined(NDEBUG) - assert(curstate == 1); - curstate = 0; -#endif - memset(&state, 0, sizeof(union hash_state)); -} - -INITIALIZER(init_random) { - generate_system_random_bytes(32, &state); - REGISTER_FINALIZER(deinit_random); -#if !defined(NDEBUG) - assert(curstate == 0); - curstate = 1; -#endif -} - -void generate_random_bytes_not_thread_safe(size_t n, void *result) { -#if !defined(NDEBUG) - assert(curstate == 1); - curstate = 2; -#endif - if (n == 0) { -#if !defined(NDEBUG) - assert(curstate == 2); - curstate = 1; -#endif - return; - } - for (;;) { - hash_permutation(&state); - if (n <= HASH_DATA_AREA) { - memcpy(result, &state, n); -#if !defined(NDEBUG) - assert(curstate == 2); - curstate = 1; -#endif - return; - } else { - memcpy(result, &state, HASH_DATA_AREA); - result = padd(result, HASH_DATA_AREA); - n -= HASH_DATA_AREA; - } - } -} diff --git a/src/Native/libcryptonote/crypto/random.h b/src/Native/libcryptonote/crypto/random.h index 6468136cc..afc8f3b2d 100644 --- a/src/Native/libcryptonote/crypto/random.h +++ b/src/Native/libcryptonote/crypto/random.h @@ -1,35 +1,9 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once #include -void generate_random_bytes_not_thread_safe(size_t n, void *result); +void generate_random_bytes(size_t n, void *result); diff --git a/src/Native/libcryptonote/crypto/skein.c b/src/Native/libcryptonote/crypto/skein.c deleted file mode 100644 index 65e4525c3..000000000 --- a/src/Native/libcryptonote/crypto/skein.c +++ /dev/null @@ -1,2036 +0,0 @@ -/*********************************************************************** -** -** Implementation of the Skein hash function. -** -** Source code author: Doug Whiting, 2008. -** -** This algorithm and source code is released to the public domain. -** -************************************************************************/ - -#define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */ - -#include /* get size_t definition */ -#include /* get the memcpy/memset functions */ -#include "skein.h" /* get the Skein API definitions */ - -#define DISABLE_UNUSED 0 - -#ifndef SKEIN_256_NIST_MAX_HASHBITS -#define SKEIN_256_NIST_MAX_HASHBITS (0) -#endif - -#ifndef SKEIN_512_NIST_MAX_HASHBITS -#define SKEIN_512_NIST_MAX_HASHBITS (512) -#endif - -#define SKEIN_MODIFIER_WORDS ( 2) /* number of modifier (tweak) words */ - -#define SKEIN_256_STATE_WORDS ( 4) -#define SKEIN_512_STATE_WORDS ( 8) -#define SKEIN1024_STATE_WORDS (16) -#define SKEIN_MAX_STATE_WORDS (16) - -#define SKEIN_256_STATE_BYTES ( 8*SKEIN_256_STATE_WORDS) -#define SKEIN_512_STATE_BYTES ( 8*SKEIN_512_STATE_WORDS) -#define SKEIN1024_STATE_BYTES ( 8*SKEIN1024_STATE_WORDS) - -#define SKEIN_256_STATE_BITS (64*SKEIN_256_STATE_WORDS) -#define SKEIN_512_STATE_BITS (64*SKEIN_512_STATE_WORDS) -#define SKEIN1024_STATE_BITS (64*SKEIN1024_STATE_WORDS) - -#define SKEIN_256_BLOCK_BYTES ( 8*SKEIN_256_STATE_WORDS) -#define SKEIN_512_BLOCK_BYTES ( 8*SKEIN_512_STATE_WORDS) -#define SKEIN1024_BLOCK_BYTES ( 8*SKEIN1024_STATE_WORDS) - -#define SKEIN_RND_SPECIAL (1000u) -#define SKEIN_RND_KEY_INITIAL (SKEIN_RND_SPECIAL+0u) -#define SKEIN_RND_KEY_INJECT (SKEIN_RND_SPECIAL+1u) -#define SKEIN_RND_FEED_FWD (SKEIN_RND_SPECIAL+2u) - -typedef struct -{ - size_t hashBitLen; /* size of hash result, in bits */ - size_t bCnt; /* current byte count in buffer b[] */ - u64b_t T[SKEIN_MODIFIER_WORDS]; /* tweak words: T[0]=byte cnt, T[1]=flags */ -} Skein_Ctxt_Hdr_t; - -typedef struct /* 256-bit Skein hash context structure */ -{ - Skein_Ctxt_Hdr_t h; /* common header context variables */ - u64b_t X[SKEIN_256_STATE_WORDS]; /* chaining variables */ - u08b_t b[SKEIN_256_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */ -} Skein_256_Ctxt_t; - -typedef struct /* 512-bit Skein hash context structure */ -{ - Skein_Ctxt_Hdr_t h; /* common header context variables */ - u64b_t X[SKEIN_512_STATE_WORDS]; /* chaining variables */ - u08b_t b[SKEIN_512_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */ -} Skein_512_Ctxt_t; - -typedef struct /* 1024-bit Skein hash context structure */ -{ - Skein_Ctxt_Hdr_t h; /* common header context variables */ - u64b_t X[SKEIN1024_STATE_WORDS]; /* chaining variables */ - u08b_t b[SKEIN1024_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */ -} Skein1024_Ctxt_t; - -/* Skein APIs for (incremental) "straight hashing" */ -#if SKEIN_256_NIST_MAX_HASHBITS -static int Skein_256_Init (Skein_256_Ctxt_t *ctx, size_t hashBitLen); -#endif -static int Skein_512_Init (Skein_512_Ctxt_t *ctx, size_t hashBitLen); -static int Skein1024_Init (Skein1024_Ctxt_t *ctx, size_t hashBitLen); - -static int Skein_256_Update(Skein_256_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt); -static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt); -static int Skein1024_Update(Skein1024_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt); - -static int Skein_256_Final (Skein_256_Ctxt_t *ctx, u08b_t * hashVal); -static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); -static int Skein1024_Final (Skein1024_Ctxt_t *ctx, u08b_t * hashVal); - -/* -** Skein APIs for "extended" initialization: MAC keys, tree hashing. -** After an InitExt() call, just use Update/Final calls as with Init(). -** -** Notes: Same parameters as _Init() calls, plus treeInfo/key/keyBytes. -** When keyBytes == 0 and treeInfo == SKEIN_SEQUENTIAL, -** the results of InitExt() are identical to calling Init(). -** The function Init() may be called once to "precompute" the IV for -** a given hashBitLen value, then by saving a copy of the context -** the IV computation may be avoided in later calls. -** Similarly, the function InitExt() may be called once per MAC key -** to precompute the MAC IV, then a copy of the context saved and -** reused for each new MAC computation. -**/ -#if 0 -static int Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, u64b_t treeInfo, const u08b_t *key, size_t keyBytes); -static int Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, u64b_t treeInfo, const u08b_t *key, size_t keyBytes); -static int Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, u64b_t treeInfo, const u08b_t *key, size_t keyBytes); -#endif - -/* -** Skein APIs for MAC and tree hash: -** Final_Pad: pad, do final block, but no OUTPUT type -** Output: do just the output stage -*/ -#if 0 -static int Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, u08b_t * hashVal); -static int Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, u08b_t * hashVal); -static int Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, u08b_t * hashVal); -#endif - -#ifndef SKEIN_TREE_HASH -#define SKEIN_TREE_HASH (1) -#endif -#if 0 -#if SKEIN_TREE_HASH -static int Skein_256_Output (Skein_256_Ctxt_t *ctx, u08b_t * hashVal); -static int Skein_512_Output (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); -static int Skein1024_Output (Skein1024_Ctxt_t *ctx, u08b_t * hashVal); -#endif -#endif - -/***************************************************************** -** "Internal" Skein definitions -** -- not needed for sequential hashing API, but will be -** helpful for other uses of Skein (e.g., tree hash mode). -** -- included here so that they can be shared between -** reference and optimized code. -******************************************************************/ - -/* tweak word T[1]: bit field starting positions */ -#define SKEIN_T1_BIT(BIT) ((BIT) - 64) /* offset 64 because it's the second word */ - -#define SKEIN_T1_POS_TREE_LVL SKEIN_T1_BIT(112) /* bits 112..118: level in hash tree */ -#define SKEIN_T1_POS_BIT_PAD SKEIN_T1_BIT(119) /* bit 119 : partial final input byte */ -#define SKEIN_T1_POS_BLK_TYPE SKEIN_T1_BIT(120) /* bits 120..125: type field */ -#define SKEIN_T1_POS_FIRST SKEIN_T1_BIT(126) /* bits 126 : first block flag */ -#define SKEIN_T1_POS_FINAL SKEIN_T1_BIT(127) /* bit 127 : final block flag */ - -/* tweak word T[1]: flag bit definition(s) */ -#define SKEIN_T1_FLAG_FIRST (((u64b_t) 1 ) << SKEIN_T1_POS_FIRST) -#define SKEIN_T1_FLAG_FINAL (((u64b_t) 1 ) << SKEIN_T1_POS_FINAL) -#define SKEIN_T1_FLAG_BIT_PAD (((u64b_t) 1 ) << SKEIN_T1_POS_BIT_PAD) - -/* tweak word T[1]: tree level bit field mask */ -#define SKEIN_T1_TREE_LVL_MASK (((u64b_t)0x7F) << SKEIN_T1_POS_TREE_LVL) -#define SKEIN_T1_TREE_LEVEL(n) (((u64b_t) (n)) << SKEIN_T1_POS_TREE_LVL) - -/* tweak word T[1]: block type field */ -#define SKEIN_BLK_TYPE_KEY ( 0) /* key, for MAC and KDF */ -#define SKEIN_BLK_TYPE_CFG ( 4) /* configuration block */ -#define SKEIN_BLK_TYPE_PERS ( 8) /* personalization string */ -#define SKEIN_BLK_TYPE_PK (12) /* public key (for digital signature hashing) */ -#define SKEIN_BLK_TYPE_KDF (16) /* key identifier for KDF */ -#define SKEIN_BLK_TYPE_NONCE (20) /* nonce for PRNG */ -#define SKEIN_BLK_TYPE_MSG (48) /* message processing */ -#define SKEIN_BLK_TYPE_OUT (63) /* output stage */ -#define SKEIN_BLK_TYPE_MASK (63) /* bit field mask */ - -#define SKEIN_T1_BLK_TYPE(T) (((u64b_t) (SKEIN_BLK_TYPE_##T)) << SKEIN_T1_POS_BLK_TYPE) -#define SKEIN_T1_BLK_TYPE_KEY SKEIN_T1_BLK_TYPE(KEY) /* key, for MAC and KDF */ -#define SKEIN_T1_BLK_TYPE_CFG SKEIN_T1_BLK_TYPE(CFG) /* configuration block */ -#define SKEIN_T1_BLK_TYPE_PERS SKEIN_T1_BLK_TYPE(PERS) /* personalization string */ -#define SKEIN_T1_BLK_TYPE_PK SKEIN_T1_BLK_TYPE(PK) /* public key (for digital signature hashing) */ -#define SKEIN_T1_BLK_TYPE_KDF SKEIN_T1_BLK_TYPE(KDF) /* key identifier for KDF */ -#define SKEIN_T1_BLK_TYPE_NONCE SKEIN_T1_BLK_TYPE(NONCE)/* nonce for PRNG */ -#define SKEIN_T1_BLK_TYPE_MSG SKEIN_T1_BLK_TYPE(MSG) /* message processing */ -#define SKEIN_T1_BLK_TYPE_OUT SKEIN_T1_BLK_TYPE(OUT) /* output stage */ -#define SKEIN_T1_BLK_TYPE_MASK SKEIN_T1_BLK_TYPE(MASK) /* field bit mask */ - -#define SKEIN_T1_BLK_TYPE_CFG_FINAL (SKEIN_T1_BLK_TYPE_CFG | SKEIN_T1_FLAG_FINAL) -#define SKEIN_T1_BLK_TYPE_OUT_FINAL (SKEIN_T1_BLK_TYPE_OUT | SKEIN_T1_FLAG_FINAL) - -#define SKEIN_VERSION (1) - -#ifndef SKEIN_ID_STRING_LE /* allow compile-time personalization */ -#define SKEIN_ID_STRING_LE (0x33414853) /* "SHA3" (little-endian)*/ -#endif - -#define SKEIN_MK_64(hi32,lo32) ((lo32) + (((u64b_t) (hi32)) << 32)) -#define SKEIN_SCHEMA_VER SKEIN_MK_64(SKEIN_VERSION,SKEIN_ID_STRING_LE) -#define SKEIN_KS_PARITY SKEIN_MK_64(0x1BD11BDA,0xA9FC1A22) - -#define SKEIN_CFG_STR_LEN (4*8) - -/* bit field definitions in config block treeInfo word */ -#define SKEIN_CFG_TREE_LEAF_SIZE_POS ( 0) -#define SKEIN_CFG_TREE_NODE_SIZE_POS ( 8) -#define SKEIN_CFG_TREE_MAX_LEVEL_POS (16) - -#define SKEIN_CFG_TREE_LEAF_SIZE_MSK (((u64b_t) 0xFF) << SKEIN_CFG_TREE_LEAF_SIZE_POS) -#define SKEIN_CFG_TREE_NODE_SIZE_MSK (((u64b_t) 0xFF) << SKEIN_CFG_TREE_NODE_SIZE_POS) -#define SKEIN_CFG_TREE_MAX_LEVEL_MSK (((u64b_t) 0xFF) << SKEIN_CFG_TREE_MAX_LEVEL_POS) - -#define SKEIN_CFG_TREE_INFO(leaf,node,maxLvl) \ - ( (((u64b_t)(leaf )) << SKEIN_CFG_TREE_LEAF_SIZE_POS) | \ - (((u64b_t)(node )) << SKEIN_CFG_TREE_NODE_SIZE_POS) | \ - (((u64b_t)(maxLvl)) << SKEIN_CFG_TREE_MAX_LEVEL_POS) ) - -#define SKEIN_CFG_TREE_INFO_SEQUENTIAL SKEIN_CFG_TREE_INFO(0,0,0) /* use as treeInfo in InitExt() call for sequential processing */ - -/* -** Skein macros for getting/setting tweak words, etc. -** These are useful for partial input bytes, hash tree init/update, etc. -**/ -#define Skein_Get_Tweak(ctxPtr,TWK_NUM) ((ctxPtr)->h.T[TWK_NUM]) -#define Skein_Set_Tweak(ctxPtr,TWK_NUM,tVal) {(ctxPtr)->h.T[TWK_NUM] = (tVal);} - -#define Skein_Get_T0(ctxPtr) Skein_Get_Tweak(ctxPtr,0) -#define Skein_Get_T1(ctxPtr) Skein_Get_Tweak(ctxPtr,1) -#define Skein_Set_T0(ctxPtr,T0) Skein_Set_Tweak(ctxPtr,0,T0) -#define Skein_Set_T1(ctxPtr,T1) Skein_Set_Tweak(ctxPtr,1,T1) - -/* set both tweak words at once */ -#define Skein_Set_T0_T1(ctxPtr,T0,T1) \ -{ \ - Skein_Set_T0(ctxPtr,(T0)); \ - Skein_Set_T1(ctxPtr,(T1)); \ -} - -#define Skein_Set_Type(ctxPtr,BLK_TYPE) \ - Skein_Set_T1(ctxPtr,SKEIN_T1_BLK_TYPE_##BLK_TYPE) - -/* set up for starting with a new type: h.T[0]=0; h.T[1] = NEW_TYPE; h.bCnt=0; */ -#define Skein_Start_New_Type(ctxPtr,BLK_TYPE) \ -{ Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; } - -#define Skein_Clear_First_Flag(hdr) { (hdr).T[1] &= ~SKEIN_T1_FLAG_FIRST; } -#define Skein_Set_Bit_Pad_Flag(hdr) { (hdr).T[1] |= SKEIN_T1_FLAG_BIT_PAD; } - -#define Skein_Set_Tree_Level(hdr,height) { (hdr).T[1] |= SKEIN_T1_TREE_LEVEL(height);} - -/***************************************************************** -** "Internal" Skein definitions for debugging and error checking -******************************************************************/ -#define Skein_Show_Block(bits,ctx,X,blkPtr,wPtr,ksEvenPtr,ksOddPtr) -#define Skein_Show_Round(bits,ctx,r,X) -#define Skein_Show_R_Ptr(bits,ctx,r,X_ptr) -#define Skein_Show_Final(bits,ctx,cnt,outPtr) -#define Skein_Show_Key(bits,ctx,key,keyBytes) - - -#ifndef SKEIN_ERR_CHECK /* run-time checks (e.g., bad params, uninitialized context)? */ -#define Skein_Assert(x,retCode)/* default: ignore all Asserts, for performance */ -#define Skein_assert(x) -#elif defined(SKEIN_ASSERT) -#include -#define Skein_Assert(x,retCode) assert(x) -#define Skein_assert(x) assert(x) -#else -#include -#define Skein_Assert(x,retCode) { if (!(x)) return retCode; } /* caller error */ -#define Skein_assert(x) assert(x) /* internal error */ -#endif - -/***************************************************************** -** Skein block function constants (shared across Ref and Opt code) -******************************************************************/ -enum -{ - /* Skein_256 round rotation constants */ - R_256_0_0=14, R_256_0_1=16, - R_256_1_0=52, R_256_1_1=57, - R_256_2_0=23, R_256_2_1=40, - R_256_3_0= 5, R_256_3_1=37, - R_256_4_0=25, R_256_4_1=33, - R_256_5_0=46, R_256_5_1=12, - R_256_6_0=58, R_256_6_1=22, - R_256_7_0=32, R_256_7_1=32, - - /* Skein_512 round rotation constants */ - R_512_0_0=46, R_512_0_1=36, R_512_0_2=19, R_512_0_3=37, - R_512_1_0=33, R_512_1_1=27, R_512_1_2=14, R_512_1_3=42, - R_512_2_0=17, R_512_2_1=49, R_512_2_2=36, R_512_2_3=39, - R_512_3_0=44, R_512_3_1= 9, R_512_3_2=54, R_512_3_3=56, - R_512_4_0=39, R_512_4_1=30, R_512_4_2=34, R_512_4_3=24, - R_512_5_0=13, R_512_5_1=50, R_512_5_2=10, R_512_5_3=17, - R_512_6_0=25, R_512_6_1=29, R_512_6_2=39, R_512_6_3=43, - R_512_7_0= 8, R_512_7_1=35, R_512_7_2=56, R_512_7_3=22, - - /* Skein1024 round rotation constants */ - R1024_0_0=24, R1024_0_1=13, R1024_0_2= 8, R1024_0_3=47, R1024_0_4= 8, R1024_0_5=17, R1024_0_6=22, R1024_0_7=37, - R1024_1_0=38, R1024_1_1=19, R1024_1_2=10, R1024_1_3=55, R1024_1_4=49, R1024_1_5=18, R1024_1_6=23, R1024_1_7=52, - R1024_2_0=33, R1024_2_1= 4, R1024_2_2=51, R1024_2_3=13, R1024_2_4=34, R1024_2_5=41, R1024_2_6=59, R1024_2_7=17, - R1024_3_0= 5, R1024_3_1=20, R1024_3_2=48, R1024_3_3=41, R1024_3_4=47, R1024_3_5=28, R1024_3_6=16, R1024_3_7=25, - R1024_4_0=41, R1024_4_1= 9, R1024_4_2=37, R1024_4_3=31, R1024_4_4=12, R1024_4_5=47, R1024_4_6=44, R1024_4_7=30, - R1024_5_0=16, R1024_5_1=34, R1024_5_2=56, R1024_5_3=51, R1024_5_4= 4, R1024_5_5=53, R1024_5_6=42, R1024_5_7=41, - R1024_6_0=31, R1024_6_1=44, R1024_6_2=47, R1024_6_3=46, R1024_6_4=19, R1024_6_5=42, R1024_6_6=44, R1024_6_7=25, - R1024_7_0= 9, R1024_7_1=48, R1024_7_2=35, R1024_7_3=52, R1024_7_4=23, R1024_7_5=31, R1024_7_6=37, R1024_7_7=20 -}; - -#ifndef SKEIN_ROUNDS -#define SKEIN_256_ROUNDS_TOTAL (72) /* number of rounds for the different block sizes */ -#define SKEIN_512_ROUNDS_TOTAL (72) -#define SKEIN1024_ROUNDS_TOTAL (80) -#else /* allow command-line define in range 8*(5..14) */ -#define SKEIN_256_ROUNDS_TOTAL (8*((((SKEIN_ROUNDS/100) + 5) % 10) + 5)) -#define SKEIN_512_ROUNDS_TOTAL (8*((((SKEIN_ROUNDS/ 10) + 5) % 10) + 5)) -#define SKEIN1024_ROUNDS_TOTAL (8*((((SKEIN_ROUNDS ) + 5) % 10) + 5)) -#endif - - -/* -***************** Pre-computed Skein IVs ******************* -** -** NOTE: these values are not "magic" constants, but -** are generated using the Threefish block function. -** They are pre-computed here only for speed; i.e., to -** avoid the need for a Threefish call during Init(). -** -** The IV for any fixed hash length may be pre-computed. -** Only the most common values are included here. -** -************************************************************ -**/ - -#define MK_64 SKEIN_MK_64 - -/* blkSize = 256 bits. hashSize = 128 bits */ -const u64b_t SKEIN_256_IV_128[] = - { - MK_64(0xE1111906,0x964D7260), - MK_64(0x883DAAA7,0x7C8D811C), - MK_64(0x10080DF4,0x91960F7A), - MK_64(0xCCF7DDE5,0xB45BC1C2) - }; - -/* blkSize = 256 bits. hashSize = 160 bits */ -const u64b_t SKEIN_256_IV_160[] = - { - MK_64(0x14202314,0x72825E98), - MK_64(0x2AC4E9A2,0x5A77E590), - MK_64(0xD47A5856,0x8838D63E), - MK_64(0x2DD2E496,0x8586AB7D) - }; - -/* blkSize = 256 bits. hashSize = 224 bits */ -const u64b_t SKEIN_256_IV_224[] = - { - MK_64(0xC6098A8C,0x9AE5EA0B), - MK_64(0x876D5686,0x08C5191C), - MK_64(0x99CB88D7,0xD7F53884), - MK_64(0x384BDDB1,0xAEDDB5DE) - }; - -/* blkSize = 256 bits. hashSize = 256 bits */ -const u64b_t SKEIN_256_IV_256[] = - { - MK_64(0xFC9DA860,0xD048B449), - MK_64(0x2FCA6647,0x9FA7D833), - MK_64(0xB33BC389,0x6656840F), - MK_64(0x6A54E920,0xFDE8DA69) - }; - -/* blkSize = 512 bits. hashSize = 128 bits */ -const u64b_t SKEIN_512_IV_128[] = - { - MK_64(0xA8BC7BF3,0x6FBF9F52), - MK_64(0x1E9872CE,0xBD1AF0AA), - MK_64(0x309B1790,0xB32190D3), - MK_64(0xBCFBB854,0x3F94805C), - MK_64(0x0DA61BCD,0x6E31B11B), - MK_64(0x1A18EBEA,0xD46A32E3), - MK_64(0xA2CC5B18,0xCE84AA82), - MK_64(0x6982AB28,0x9D46982D) - }; - -/* blkSize = 512 bits. hashSize = 160 bits */ -const u64b_t SKEIN_512_IV_160[] = - { - MK_64(0x28B81A2A,0xE013BD91), - MK_64(0xC2F11668,0xB5BDF78F), - MK_64(0x1760D8F3,0xF6A56F12), - MK_64(0x4FB74758,0x8239904F), - MK_64(0x21EDE07F,0x7EAF5056), - MK_64(0xD908922E,0x63ED70B8), - MK_64(0xB8EC76FF,0xECCB52FA), - MK_64(0x01A47BB8,0xA3F27A6E) - }; - -/* blkSize = 512 bits. hashSize = 224 bits */ -const u64b_t SKEIN_512_IV_224[] = - { - MK_64(0xCCD06162,0x48677224), - MK_64(0xCBA65CF3,0xA92339EF), - MK_64(0x8CCD69D6,0x52FF4B64), - MK_64(0x398AED7B,0x3AB890B4), - MK_64(0x0F59D1B1,0x457D2BD0), - MK_64(0x6776FE65,0x75D4EB3D), - MK_64(0x99FBC70E,0x997413E9), - MK_64(0x9E2CFCCF,0xE1C41EF7) - }; - -/* blkSize = 512 bits. hashSize = 256 bits */ -const u64b_t SKEIN_512_IV_256[] = - { - MK_64(0xCCD044A1,0x2FDB3E13), - MK_64(0xE8359030,0x1A79A9EB), - MK_64(0x55AEA061,0x4F816E6F), - MK_64(0x2A2767A4,0xAE9B94DB), - MK_64(0xEC06025E,0x74DD7683), - MK_64(0xE7A436CD,0xC4746251), - MK_64(0xC36FBAF9,0x393AD185), - MK_64(0x3EEDBA18,0x33EDFC13) - }; - -/* blkSize = 512 bits. hashSize = 384 bits */ -const u64b_t SKEIN_512_IV_384[] = - { - MK_64(0xA3F6C6BF,0x3A75EF5F), - MK_64(0xB0FEF9CC,0xFD84FAA4), - MK_64(0x9D77DD66,0x3D770CFE), - MK_64(0xD798CBF3,0xB468FDDA), - MK_64(0x1BC4A666,0x8A0E4465), - MK_64(0x7ED7D434,0xE5807407), - MK_64(0x548FC1AC,0xD4EC44D6), - MK_64(0x266E1754,0x6AA18FF8) - }; - -/* blkSize = 512 bits. hashSize = 512 bits */ -const u64b_t SKEIN_512_IV_512[] = - { - MK_64(0x4903ADFF,0x749C51CE), - MK_64(0x0D95DE39,0x9746DF03), - MK_64(0x8FD19341,0x27C79BCE), - MK_64(0x9A255629,0xFF352CB1), - MK_64(0x5DB62599,0xDF6CA7B0), - MK_64(0xEABE394C,0xA9D5C3F4), - MK_64(0x991112C7,0x1A75B523), - MK_64(0xAE18A40B,0x660FCC33) - }; - -/* blkSize = 1024 bits. hashSize = 384 bits */ -const u64b_t SKEIN1024_IV_384[] = - { - MK_64(0x5102B6B8,0xC1894A35), - MK_64(0xFEEBC9E3,0xFE8AF11A), - MK_64(0x0C807F06,0xE32BED71), - MK_64(0x60C13A52,0xB41A91F6), - MK_64(0x9716D35D,0xD4917C38), - MK_64(0xE780DF12,0x6FD31D3A), - MK_64(0x797846B6,0xC898303A), - MK_64(0xB172C2A8,0xB3572A3B), - MK_64(0xC9BC8203,0xA6104A6C), - MK_64(0x65909338,0xD75624F4), - MK_64(0x94BCC568,0x4B3F81A0), - MK_64(0x3EBBF51E,0x10ECFD46), - MK_64(0x2DF50F0B,0xEEB08542), - MK_64(0x3B5A6530,0x0DBC6516), - MK_64(0x484B9CD2,0x167BBCE1), - MK_64(0x2D136947,0xD4CBAFEA) - }; - -/* blkSize = 1024 bits. hashSize = 512 bits */ -const u64b_t SKEIN1024_IV_512[] = - { - MK_64(0xCAEC0E5D,0x7C1B1B18), - MK_64(0xA01B0E04,0x5F03E802), - MK_64(0x33840451,0xED912885), - MK_64(0x374AFB04,0xEAEC2E1C), - MK_64(0xDF25A0E2,0x813581F7), - MK_64(0xE4004093,0x8B12F9D2), - MK_64(0xA662D539,0xC2ED39B6), - MK_64(0xFA8B85CF,0x45D8C75A), - MK_64(0x8316ED8E,0x29EDE796), - MK_64(0x053289C0,0x2E9F91B8), - MK_64(0xC3F8EF1D,0x6D518B73), - MK_64(0xBDCEC3C4,0xD5EF332E), - MK_64(0x549A7E52,0x22974487), - MK_64(0x67070872,0x5B749816), - MK_64(0xB9CD28FB,0xF0581BD1), - MK_64(0x0E2940B8,0x15804974) - }; - -/* blkSize = 1024 bits. hashSize = 1024 bits */ -const u64b_t SKEIN1024_IV_1024[] = - { - MK_64(0xD593DA07,0x41E72355), - MK_64(0x15B5E511,0xAC73E00C), - MK_64(0x5180E5AE,0xBAF2C4F0), - MK_64(0x03BD41D3,0xFCBCAFAF), - MK_64(0x1CAEC6FD,0x1983A898), - MK_64(0x6E510B8B,0xCDD0589F), - MK_64(0x77E2BDFD,0xC6394ADA), - MK_64(0xC11E1DB5,0x24DCB0A3), - MK_64(0xD6D14AF9,0xC6329AB5), - MK_64(0x6A9B0BFC,0x6EB67E0D), - MK_64(0x9243C60D,0xCCFF1332), - MK_64(0x1A1F1DDE,0x743F02D4), - MK_64(0x0996753C,0x10ED0BB8), - MK_64(0x6572DD22,0xF2B4969A), - MK_64(0x61FD3062,0xD00A579A), - MK_64(0x1DE0536E,0x8682E539) - }; - - -#ifndef SKEIN_USE_ASM -#define SKEIN_USE_ASM (0) /* default is all C code (no ASM) */ -#endif - -#ifndef SKEIN_LOOP -#define SKEIN_LOOP 001 /* default: unroll 256 and 512, but not 1024 */ -#endif - -#define BLK_BITS (WCNT*64) /* some useful definitions for code here */ -#define KW_TWK_BASE (0) -#define KW_KEY_BASE (3) -#define ks (kw + KW_KEY_BASE) -#define ts (kw + KW_TWK_BASE) - -#ifdef SKEIN_DEBUG -#define DebugSaveTweak(ctx) { ctx->h.T[0] = ts[0]; ctx->h.T[1] = ts[1]; } -#else -#define DebugSaveTweak(ctx) -#endif - -/***************************** Skein_256 ******************************/ -#if !(SKEIN_USE_ASM & 256) -static void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd) - { /* do it in C */ - enum - { - WCNT = SKEIN_256_STATE_WORDS - }; -#undef RCNT -#define RCNT (SKEIN_256_ROUNDS_TOTAL/8) - -#ifdef SKEIN_LOOP /* configure how much to unroll the loop */ -#define SKEIN_UNROLL_256 (((SKEIN_LOOP)/100)%10) -#else -#define SKEIN_UNROLL_256 (0) -#endif - -#if SKEIN_UNROLL_256 -#if (RCNT % SKEIN_UNROLL_256) -#error "Invalid SKEIN_UNROLL_256" /* sanity check on unroll count */ -#endif - size_t r; - u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/ -#else - u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */ -#endif - u64b_t X0,X1,X2,X3; /* local copy of context vars, for speed */ - u64b_t w [WCNT]; /* local copy of input block */ -#ifdef SKEIN_DEBUG - const u64b_t *Xptr[4]; /* use for debugging (help compiler put Xn in registers) */ - Xptr[0] = &X0; Xptr[1] = &X1; Xptr[2] = &X2; Xptr[3] = &X3; -#endif - Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ - ts[0] = ctx->h.T[0]; - ts[1] = ctx->h.T[1]; - do { - /* this implementation only supports 2**64 input bytes (no carry out here) */ - ts[0] += byteCntAdd; /* update processed length */ - - /* precompute the key schedule for this block */ - ks[0] = ctx->X[0]; - ks[1] = ctx->X[1]; - ks[2] = ctx->X[2]; - ks[3] = ctx->X[3]; - ks[4] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ SKEIN_KS_PARITY; - - ts[2] = ts[0] ^ ts[1]; - - Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */ - DebugSaveTweak(ctx); - Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts); - - X0 = w[0] + ks[0]; /* do the first full key injection */ - X1 = w[1] + ks[1] + ts[0]; - X2 = w[2] + ks[2] + ts[1]; - X3 = w[3] + ks[3]; - - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr); /* show starting state values */ - - blkPtr += SKEIN_256_BLOCK_BYTES; - - /* run the rounds */ - -#define Round256(p0,p1,p2,p3,ROT,rNum) \ - X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \ - X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \ - -#if SKEIN_UNROLL_256 == 0 -#define R256(p0,p1,p2,p3,ROT,rNum) /* fully unrolled */ \ - Round256(p0,p1,p2,p3,ROT,rNum) \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rNum,Xptr); - -#define I256(R) \ - X0 += ks[((R)+1) % 5]; /* inject the key schedule value */ \ - X1 += ks[((R)+2) % 5] + ts[((R)+1) % 3]; \ - X2 += ks[((R)+3) % 5] + ts[((R)+2) % 3]; \ - X3 += ks[((R)+4) % 5] + (R)+1; \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); -#else /* looping version */ -#define R256(p0,p1,p2,p3,ROT,rNum) \ - Round256(p0,p1,p2,p3,ROT,rNum) \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rNum,Xptr); - -#define I256(R) \ - X0 += ks[r+(R)+0]; /* inject the key schedule value */ \ - X1 += ks[r+(R)+1] + ts[r+(R)+0]; \ - X2 += ks[r+(R)+2] + ts[r+(R)+1]; \ - X3 += ks[r+(R)+3] + r+(R) ; \ - ks[r + (R)+4 ] = ks[r+(R)-1]; /* rotate key schedule */\ - ts[r + (R)+2 ] = ts[r+(R)-1]; \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); - - for (r=1;r < 2*RCNT;r+=2*SKEIN_UNROLL_256) /* loop thru it */ -#endif - { -#define R256_8_rounds(R) \ - R256(0,1,2,3,R_256_0,8*(R) + 1); \ - R256(0,3,2,1,R_256_1,8*(R) + 2); \ - R256(0,1,2,3,R_256_2,8*(R) + 3); \ - R256(0,3,2,1,R_256_3,8*(R) + 4); \ - I256(2*(R)); \ - R256(0,1,2,3,R_256_4,8*(R) + 5); \ - R256(0,3,2,1,R_256_5,8*(R) + 6); \ - R256(0,1,2,3,R_256_6,8*(R) + 7); \ - R256(0,3,2,1,R_256_7,8*(R) + 8); \ - I256(2*(R)+1); - - R256_8_rounds( 0); - -#define R256_Unroll_R(NN) ((SKEIN_UNROLL_256 == 0 && SKEIN_256_ROUNDS_TOTAL/8 > (NN)) || (SKEIN_UNROLL_256 > (NN))) - - #if R256_Unroll_R( 1) - R256_8_rounds( 1); - #endif - #if R256_Unroll_R( 2) - R256_8_rounds( 2); - #endif - #if R256_Unroll_R( 3) - R256_8_rounds( 3); - #endif - #if R256_Unroll_R( 4) - R256_8_rounds( 4); - #endif - #if R256_Unroll_R( 5) - R256_8_rounds( 5); - #endif - #if R256_Unroll_R( 6) - R256_8_rounds( 6); - #endif - #if R256_Unroll_R( 7) - R256_8_rounds( 7); - #endif - #if R256_Unroll_R( 8) - R256_8_rounds( 8); - #endif - #if R256_Unroll_R( 9) - R256_8_rounds( 9); - #endif - #if R256_Unroll_R(10) - R256_8_rounds(10); - #endif - #if R256_Unroll_R(11) - R256_8_rounds(11); - #endif - #if R256_Unroll_R(12) - R256_8_rounds(12); - #endif - #if R256_Unroll_R(13) - R256_8_rounds(13); - #endif - #if R256_Unroll_R(14) - R256_8_rounds(14); - #endif - #if (SKEIN_UNROLL_256 > 14) -#error "need more unrolling in Skein_256_Process_Block" - #endif - } - /* do the final "feedforward" xor, update context chaining vars */ - ctx->X[0] = X0 ^ w[0]; - ctx->X[1] = X1 ^ w[1]; - ctx->X[2] = X2 ^ w[2]; - ctx->X[3] = X3 ^ w[3]; - - Skein_Show_Round(BLK_BITS,&ctx->h,SKEIN_RND_FEED_FWD,ctx->X); - - ts[1] &= ~SKEIN_T1_FLAG_FIRST; - } - while (--blkCnt); - ctx->h.T[0] = ts[0]; - ctx->h.T[1] = ts[1]; - } - -#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) -static size_t Skein_256_Process_Block_CodeSize(void) - { - return ((u08b_t *) Skein_256_Process_Block_CodeSize) - - ((u08b_t *) Skein_256_Process_Block); - } -static uint_t Skein_256_Unroll_Cnt(void) - { - return SKEIN_UNROLL_256; - } -#endif -#endif - -/***************************** Skein_512 ******************************/ -#if !(SKEIN_USE_ASM & 512) -static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd) - { /* do it in C */ - enum - { - WCNT = SKEIN_512_STATE_WORDS - }; -#undef RCNT -#define RCNT (SKEIN_512_ROUNDS_TOTAL/8) - -#ifdef SKEIN_LOOP /* configure how much to unroll the loop */ -#define SKEIN_UNROLL_512 (((SKEIN_LOOP)/10)%10) -#else -#define SKEIN_UNROLL_512 (0) -#endif - -#if SKEIN_UNROLL_512 -#if (RCNT % SKEIN_UNROLL_512) -#error "Invalid SKEIN_UNROLL_512" /* sanity check on unroll count */ -#endif - size_t r; - u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/ -#else - u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */ -#endif - u64b_t X0,X1,X2,X3,X4,X5,X6,X7; /* local copy of vars, for speed */ - u64b_t w [WCNT]; /* local copy of input block */ -#ifdef SKEIN_DEBUG - const u64b_t *Xptr[8]; /* use for debugging (help compiler put Xn in registers) */ - Xptr[0] = &X0; Xptr[1] = &X1; Xptr[2] = &X2; Xptr[3] = &X3; - Xptr[4] = &X4; Xptr[5] = &X5; Xptr[6] = &X6; Xptr[7] = &X7; -#endif - - Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ - ts[0] = ctx->h.T[0]; - ts[1] = ctx->h.T[1]; - do { - /* this implementation only supports 2**64 input bytes (no carry out here) */ - ts[0] += byteCntAdd; /* update processed length */ - - /* precompute the key schedule for this block */ - ks[0] = ctx->X[0]; - ks[1] = ctx->X[1]; - ks[2] = ctx->X[2]; - ks[3] = ctx->X[3]; - ks[4] = ctx->X[4]; - ks[5] = ctx->X[5]; - ks[6] = ctx->X[6]; - ks[7] = ctx->X[7]; - ks[8] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ - ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^ SKEIN_KS_PARITY; - - ts[2] = ts[0] ^ ts[1]; - - Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */ - DebugSaveTweak(ctx); - Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts); - - X0 = w[0] + ks[0]; /* do the first full key injection */ - X1 = w[1] + ks[1]; - X2 = w[2] + ks[2]; - X3 = w[3] + ks[3]; - X4 = w[4] + ks[4]; - X5 = w[5] + ks[5] + ts[0]; - X6 = w[6] + ks[6] + ts[1]; - X7 = w[7] + ks[7]; - - blkPtr += SKEIN_512_BLOCK_BYTES; - - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr); - /* run the rounds */ -#define Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ - X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \ - X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \ - X##p4 += X##p5; X##p5 = RotL_64(X##p5,ROT##_2); X##p5 ^= X##p4; \ - X##p6 += X##p7; X##p7 = RotL_64(X##p7,ROT##_3); X##p7 ^= X##p6; \ - -#if SKEIN_UNROLL_512 == 0 -#define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) /* unrolled */ \ - Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rNum,Xptr); - -#define I512(R) \ - X0 += ks[((R)+1) % 9]; /* inject the key schedule value */ \ - X1 += ks[((R)+2) % 9]; \ - X2 += ks[((R)+3) % 9]; \ - X3 += ks[((R)+4) % 9]; \ - X4 += ks[((R)+5) % 9]; \ - X5 += ks[((R)+6) % 9] + ts[((R)+1) % 3]; \ - X6 += ks[((R)+7) % 9] + ts[((R)+2) % 3]; \ - X7 += ks[((R)+8) % 9] + (R)+1; \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); -#else /* looping version */ -#define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ - Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rNum,Xptr); - -#define I512(R) \ - X0 += ks[r+(R)+0]; /* inject the key schedule value */ \ - X1 += ks[r+(R)+1]; \ - X2 += ks[r+(R)+2]; \ - X3 += ks[r+(R)+3]; \ - X4 += ks[r+(R)+4]; \ - X5 += ks[r+(R)+5] + ts[r+(R)+0]; \ - X6 += ks[r+(R)+6] + ts[r+(R)+1]; \ - X7 += ks[r+(R)+7] + r+(R) ; \ - ks[r + (R)+8] = ks[r+(R)-1]; /* rotate key schedule */ \ - ts[r + (R)+2] = ts[r+(R)-1]; \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); - - for (r=1;r < 2*RCNT;r+=2*SKEIN_UNROLL_512) /* loop thru it */ -#endif /* end of looped code definitions */ - { -#define R512_8_rounds(R) /* do 8 full rounds */ \ - R512(0,1,2,3,4,5,6,7,R_512_0,8*(R)+ 1); \ - R512(2,1,4,7,6,5,0,3,R_512_1,8*(R)+ 2); \ - R512(4,1,6,3,0,5,2,7,R_512_2,8*(R)+ 3); \ - R512(6,1,0,7,2,5,4,3,R_512_3,8*(R)+ 4); \ - I512(2*(R)); \ - R512(0,1,2,3,4,5,6,7,R_512_4,8*(R)+ 5); \ - R512(2,1,4,7,6,5,0,3,R_512_5,8*(R)+ 6); \ - R512(4,1,6,3,0,5,2,7,R_512_6,8*(R)+ 7); \ - R512(6,1,0,7,2,5,4,3,R_512_7,8*(R)+ 8); \ - I512(2*(R)+1); /* and key injection */ - - R512_8_rounds( 0); - -#define R512_Unroll_R(NN) ((SKEIN_UNROLL_512 == 0 && SKEIN_512_ROUNDS_TOTAL/8 > (NN)) || (SKEIN_UNROLL_512 > (NN))) - - #if R512_Unroll_R( 1) - R512_8_rounds( 1); - #endif - #if R512_Unroll_R( 2) - R512_8_rounds( 2); - #endif - #if R512_Unroll_R( 3) - R512_8_rounds( 3); - #endif - #if R512_Unroll_R( 4) - R512_8_rounds( 4); - #endif - #if R512_Unroll_R( 5) - R512_8_rounds( 5); - #endif - #if R512_Unroll_R( 6) - R512_8_rounds( 6); - #endif - #if R512_Unroll_R( 7) - R512_8_rounds( 7); - #endif - #if R512_Unroll_R( 8) - R512_8_rounds( 8); - #endif - #if R512_Unroll_R( 9) - R512_8_rounds( 9); - #endif - #if R512_Unroll_R(10) - R512_8_rounds(10); - #endif - #if R512_Unroll_R(11) - R512_8_rounds(11); - #endif - #if R512_Unroll_R(12) - R512_8_rounds(12); - #endif - #if R512_Unroll_R(13) - R512_8_rounds(13); - #endif - #if R512_Unroll_R(14) - R512_8_rounds(14); - #endif - #if (SKEIN_UNROLL_512 > 14) -#error "need more unrolling in Skein_512_Process_Block" - #endif - } - - /* do the final "feedforward" xor, update context chaining vars */ - ctx->X[0] = X0 ^ w[0]; - ctx->X[1] = X1 ^ w[1]; - ctx->X[2] = X2 ^ w[2]; - ctx->X[3] = X3 ^ w[3]; - ctx->X[4] = X4 ^ w[4]; - ctx->X[5] = X5 ^ w[5]; - ctx->X[6] = X6 ^ w[6]; - ctx->X[7] = X7 ^ w[7]; - Skein_Show_Round(BLK_BITS,&ctx->h,SKEIN_RND_FEED_FWD,ctx->X); - - ts[1] &= ~SKEIN_T1_FLAG_FIRST; - } - while (--blkCnt); - ctx->h.T[0] = ts[0]; - ctx->h.T[1] = ts[1]; - } - -#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) -static size_t Skein_512_Process_Block_CodeSize(void) - { - return ((u08b_t *) Skein_512_Process_Block_CodeSize) - - ((u08b_t *) Skein_512_Process_Block); - } -static uint_t Skein_512_Unroll_Cnt(void) - { - return SKEIN_UNROLL_512; - } -#endif -#endif - -/***************************** Skein1024 ******************************/ -#if !(SKEIN_USE_ASM & 1024) -static void Skein1024_Process_Block(Skein1024_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd) - { /* do it in C, always looping (unrolled is bigger AND slower!) */ - enum - { - WCNT = SKEIN1024_STATE_WORDS - }; -#undef RCNT -#define RCNT (SKEIN1024_ROUNDS_TOTAL/8) - -#ifdef SKEIN_LOOP /* configure how much to unroll the loop */ -#define SKEIN_UNROLL_1024 ((SKEIN_LOOP)%10) -#else -#define SKEIN_UNROLL_1024 (0) -#endif - -#if (SKEIN_UNROLL_1024 != 0) -#if (RCNT % SKEIN_UNROLL_1024) -#error "Invalid SKEIN_UNROLL_1024" /* sanity check on unroll count */ -#endif - size_t r; - u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/ -#else - u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */ -#endif - - u64b_t X00,X01,X02,X03,X04,X05,X06,X07, /* local copy of vars, for speed */ - X08,X09,X10,X11,X12,X13,X14,X15; - u64b_t w [WCNT]; /* local copy of input block */ -#ifdef SKEIN_DEBUG - const u64b_t *Xptr[16]; /* use for debugging (help compiler put Xn in registers) */ - Xptr[ 0] = &X00; Xptr[ 1] = &X01; Xptr[ 2] = &X02; Xptr[ 3] = &X03; - Xptr[ 4] = &X04; Xptr[ 5] = &X05; Xptr[ 6] = &X06; Xptr[ 7] = &X07; - Xptr[ 8] = &X08; Xptr[ 9] = &X09; Xptr[10] = &X10; Xptr[11] = &X11; - Xptr[12] = &X12; Xptr[13] = &X13; Xptr[14] = &X14; Xptr[15] = &X15; -#endif - - Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ - ts[0] = ctx->h.T[0]; - ts[1] = ctx->h.T[1]; - do { - /* this implementation only supports 2**64 input bytes (no carry out here) */ - ts[0] += byteCntAdd; /* update processed length */ - - /* precompute the key schedule for this block */ - ks[ 0] = ctx->X[ 0]; - ks[ 1] = ctx->X[ 1]; - ks[ 2] = ctx->X[ 2]; - ks[ 3] = ctx->X[ 3]; - ks[ 4] = ctx->X[ 4]; - ks[ 5] = ctx->X[ 5]; - ks[ 6] = ctx->X[ 6]; - ks[ 7] = ctx->X[ 7]; - ks[ 8] = ctx->X[ 8]; - ks[ 9] = ctx->X[ 9]; - ks[10] = ctx->X[10]; - ks[11] = ctx->X[11]; - ks[12] = ctx->X[12]; - ks[13] = ctx->X[13]; - ks[14] = ctx->X[14]; - ks[15] = ctx->X[15]; - ks[16] = ks[ 0] ^ ks[ 1] ^ ks[ 2] ^ ks[ 3] ^ - ks[ 4] ^ ks[ 5] ^ ks[ 6] ^ ks[ 7] ^ - ks[ 8] ^ ks[ 9] ^ ks[10] ^ ks[11] ^ - ks[12] ^ ks[13] ^ ks[14] ^ ks[15] ^ SKEIN_KS_PARITY; - - ts[2] = ts[0] ^ ts[1]; - - Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */ - DebugSaveTweak(ctx); - Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts); - - X00 = w[ 0] + ks[ 0]; /* do the first full key injection */ - X01 = w[ 1] + ks[ 1]; - X02 = w[ 2] + ks[ 2]; - X03 = w[ 3] + ks[ 3]; - X04 = w[ 4] + ks[ 4]; - X05 = w[ 5] + ks[ 5]; - X06 = w[ 6] + ks[ 6]; - X07 = w[ 7] + ks[ 7]; - X08 = w[ 8] + ks[ 8]; - X09 = w[ 9] + ks[ 9]; - X10 = w[10] + ks[10]; - X11 = w[11] + ks[11]; - X12 = w[12] + ks[12]; - X13 = w[13] + ks[13] + ts[0]; - X14 = w[14] + ks[14] + ts[1]; - X15 = w[15] + ks[15]; - - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr); - -#define Round1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rNum) \ - X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \ - X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \ - X##p4 += X##p5; X##p5 = RotL_64(X##p5,ROT##_2); X##p5 ^= X##p4; \ - X##p6 += X##p7; X##p7 = RotL_64(X##p7,ROT##_3); X##p7 ^= X##p6; \ - X##p8 += X##p9; X##p9 = RotL_64(X##p9,ROT##_4); X##p9 ^= X##p8; \ - X##pA += X##pB; X##pB = RotL_64(X##pB,ROT##_5); X##pB ^= X##pA; \ - X##pC += X##pD; X##pD = RotL_64(X##pD,ROT##_6); X##pD ^= X##pC; \ - X##pE += X##pF; X##pF = RotL_64(X##pF,ROT##_7); X##pF ^= X##pE; \ - -#if SKEIN_UNROLL_1024 == 0 -#define R1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rn) \ - Round1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rn) \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rn,Xptr); - -#define I1024(R) \ - X00 += ks[((R)+ 1) % 17]; /* inject the key schedule value */ \ - X01 += ks[((R)+ 2) % 17]; \ - X02 += ks[((R)+ 3) % 17]; \ - X03 += ks[((R)+ 4) % 17]; \ - X04 += ks[((R)+ 5) % 17]; \ - X05 += ks[((R)+ 6) % 17]; \ - X06 += ks[((R)+ 7) % 17]; \ - X07 += ks[((R)+ 8) % 17]; \ - X08 += ks[((R)+ 9) % 17]; \ - X09 += ks[((R)+10) % 17]; \ - X10 += ks[((R)+11) % 17]; \ - X11 += ks[((R)+12) % 17]; \ - X12 += ks[((R)+13) % 17]; \ - X13 += ks[((R)+14) % 17] + ts[((R)+1) % 3]; \ - X14 += ks[((R)+15) % 17] + ts[((R)+2) % 3]; \ - X15 += ks[((R)+16) % 17] + (R)+1; \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); -#else /* looping version */ -#define R1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rn) \ - Round1024(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF,ROT,rn) \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rn,Xptr); - -#define I1024(R) \ - X00 += ks[r+(R)+ 0]; /* inject the key schedule value */ \ - X01 += ks[r+(R)+ 1]; \ - X02 += ks[r+(R)+ 2]; \ - X03 += ks[r+(R)+ 3]; \ - X04 += ks[r+(R)+ 4]; \ - X05 += ks[r+(R)+ 5]; \ - X06 += ks[r+(R)+ 6]; \ - X07 += ks[r+(R)+ 7]; \ - X08 += ks[r+(R)+ 8]; \ - X09 += ks[r+(R)+ 9]; \ - X10 += ks[r+(R)+10]; \ - X11 += ks[r+(R)+11]; \ - X12 += ks[r+(R)+12]; \ - X13 += ks[r+(R)+13] + ts[r+(R)+0]; \ - X14 += ks[r+(R)+14] + ts[r+(R)+1]; \ - X15 += ks[r+(R)+15] + r+(R) ; \ - ks[r + (R)+16] = ks[r+(R)-1]; /* rotate key schedule */ \ - ts[r + (R)+ 2] = ts[r+(R)-1]; \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); - - for (r=1;r <= 2*RCNT;r+=2*SKEIN_UNROLL_1024) /* loop thru it */ -#endif - { -#define R1024_8_rounds(R) /* do 8 full rounds */ \ - R1024(00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,R1024_0,8*(R) + 1); \ - R1024(00,09,02,13,06,11,04,15,10,07,12,03,14,05,08,01,R1024_1,8*(R) + 2); \ - R1024(00,07,02,05,04,03,06,01,12,15,14,13,08,11,10,09,R1024_2,8*(R) + 3); \ - R1024(00,15,02,11,06,13,04,09,14,01,08,05,10,03,12,07,R1024_3,8*(R) + 4); \ - I1024(2*(R)); \ - R1024(00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,R1024_4,8*(R) + 5); \ - R1024(00,09,02,13,06,11,04,15,10,07,12,03,14,05,08,01,R1024_5,8*(R) + 6); \ - R1024(00,07,02,05,04,03,06,01,12,15,14,13,08,11,10,09,R1024_6,8*(R) + 7); \ - R1024(00,15,02,11,06,13,04,09,14,01,08,05,10,03,12,07,R1024_7,8*(R) + 8); \ - I1024(2*(R)+1); - - R1024_8_rounds( 0); - -#define R1024_Unroll_R(NN) ((SKEIN_UNROLL_1024 == 0 && SKEIN1024_ROUNDS_TOTAL/8 > (NN)) || (SKEIN_UNROLL_1024 > (NN))) - - #if R1024_Unroll_R( 1) - R1024_8_rounds( 1); - #endif - #if R1024_Unroll_R( 2) - R1024_8_rounds( 2); - #endif - #if R1024_Unroll_R( 3) - R1024_8_rounds( 3); - #endif - #if R1024_Unroll_R( 4) - R1024_8_rounds( 4); - #endif - #if R1024_Unroll_R( 5) - R1024_8_rounds( 5); - #endif - #if R1024_Unroll_R( 6) - R1024_8_rounds( 6); - #endif - #if R1024_Unroll_R( 7) - R1024_8_rounds( 7); - #endif - #if R1024_Unroll_R( 8) - R1024_8_rounds( 8); - #endif - #if R1024_Unroll_R( 9) - R1024_8_rounds( 9); - #endif - #if R1024_Unroll_R(10) - R1024_8_rounds(10); - #endif - #if R1024_Unroll_R(11) - R1024_8_rounds(11); - #endif - #if R1024_Unroll_R(12) - R1024_8_rounds(12); - #endif - #if R1024_Unroll_R(13) - R1024_8_rounds(13); - #endif - #if R1024_Unroll_R(14) - R1024_8_rounds(14); - #endif - #if (SKEIN_UNROLL_1024 > 14) -#error "need more unrolling in Skein_1024_Process_Block" - #endif - } - /* do the final "feedforward" xor, update context chaining vars */ - - ctx->X[ 0] = X00 ^ w[ 0]; - ctx->X[ 1] = X01 ^ w[ 1]; - ctx->X[ 2] = X02 ^ w[ 2]; - ctx->X[ 3] = X03 ^ w[ 3]; - ctx->X[ 4] = X04 ^ w[ 4]; - ctx->X[ 5] = X05 ^ w[ 5]; - ctx->X[ 6] = X06 ^ w[ 6]; - ctx->X[ 7] = X07 ^ w[ 7]; - ctx->X[ 8] = X08 ^ w[ 8]; - ctx->X[ 9] = X09 ^ w[ 9]; - ctx->X[10] = X10 ^ w[10]; - ctx->X[11] = X11 ^ w[11]; - ctx->X[12] = X12 ^ w[12]; - ctx->X[13] = X13 ^ w[13]; - ctx->X[14] = X14 ^ w[14]; - ctx->X[15] = X15 ^ w[15]; - - Skein_Show_Round(BLK_BITS,&ctx->h,SKEIN_RND_FEED_FWD,ctx->X); - - ts[1] &= ~SKEIN_T1_FLAG_FIRST; - blkPtr += SKEIN1024_BLOCK_BYTES; - } - while (--blkCnt); - ctx->h.T[0] = ts[0]; - ctx->h.T[1] = ts[1]; - } - -#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) -static size_t Skein1024_Process_Block_CodeSize(void) - { - return ((u08b_t *) Skein1024_Process_Block_CodeSize) - - ((u08b_t *) Skein1024_Process_Block); - } -static uint_t Skein1024_Unroll_Cnt(void) - { - return SKEIN_UNROLL_1024; - } -#endif -#endif - - -#if 0 -/*****************************************************************/ -/* 256-bit Skein */ -/*****************************************************************/ - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* init the context for a straight hashing operation */ -static int Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen) - { - union - { - u08b_t b[SKEIN_256_STATE_BYTES]; - u64b_t w[SKEIN_256_STATE_WORDS]; - } cfg; /* config block */ - - Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); - ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ - - switch (hashBitLen) - { /* use pre-computed values, where available */ -#ifndef SKEIN_NO_PRECOMP - case 256: memcpy(ctx->X,SKEIN_256_IV_256,sizeof(ctx->X)); break; - case 224: memcpy(ctx->X,SKEIN_256_IV_224,sizeof(ctx->X)); break; - case 160: memcpy(ctx->X,SKEIN_256_IV_160,sizeof(ctx->X)); break; - case 128: memcpy(ctx->X,SKEIN_256_IV_128,sizeof(ctx->X)); break; -#endif - default: - /* here if there is no precomputed IV value available */ - /* build/process the config block, type == CONFIG (could be precomputed) */ - Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */ - - cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */ - cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ - cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); - memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */ - - /* compute the initial chaining values from config block */ - memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */ - Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); - break; - } - /* The chaining vars ctx->X are now initialized for the given hashBitLen. */ - /* Set up to process the data message portion of the hash (default) */ - Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */ - - return SKEIN_SUCCESS; - } - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* init the context for a MAC and/or tree hash operation */ -/* [identical to Skein_256_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */ -static int Skein_256_InitExt(Skein_256_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes) - { - union - { - u08b_t b[SKEIN_256_STATE_BYTES]; - u64b_t w[SKEIN_256_STATE_WORDS]; - } cfg; /* config block */ - - Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); - Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL); - - /* compute the initial chaining values ctx->X[], based on key */ - if (keyBytes == 0) /* is there a key? */ - { - memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */ - } - else /* here to pre-process a key */ - { - Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X)); - /* do a mini-Init right here */ - ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */ - Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */ - memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */ - Skein_256_Update(ctx,key,keyBytes); /* hash the key */ - Skein_256_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */ - memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */ -#if SKEIN_NEED_SWAP - { - uint_t i; - for (i=0;iX[i] = Skein_Swap64(ctx->X[i]); - } -#endif - } - /* build/process the config block, type == CONFIG (could be precomputed for each key) */ - ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ - Skein_Start_New_Type(ctx,CFG_FINAL); - - memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */ - cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); - cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ - cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ - - Skein_Show_Key(256,&ctx->h,key,keyBytes); - - /* compute the initial chaining values from config block */ - Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); - - /* The chaining vars ctx->X are now initialized */ - /* Set up to process the data message portion of the hash (default) */ - ctx->h.bCnt = 0; /* buffer b[] starts out empty */ - Skein_Start_New_Type(ctx,MSG); - - return SKEIN_SUCCESS; - } -#endif - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* process the input bytes */ -static int Skein_256_Update(Skein_256_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt) - { - size_t n; - - Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - /* process full blocks, if any */ - if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES) - { - if (ctx->h.bCnt) /* finish up any buffered message data */ - { - n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ - if (n) - { - Skein_assert(n < msgByteCnt); /* check on our logic here */ - memcpy(&ctx->b[ctx->h.bCnt],msg,n); - msgByteCnt -= n; - msg += n; - ctx->h.bCnt += n; - } - Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES); - Skein_256_Process_Block(ctx,ctx->b,1,SKEIN_256_BLOCK_BYTES); - ctx->h.bCnt = 0; - } - /* now process any remaining full blocks, directly from input message data */ - if (msgByteCnt > SKEIN_256_BLOCK_BYTES) - { - n = (msgByteCnt-1) / SKEIN_256_BLOCK_BYTES; /* number of full blocks to process */ - Skein_256_Process_Block(ctx,msg,n,SKEIN_256_BLOCK_BYTES); - msgByteCnt -= n * SKEIN_256_BLOCK_BYTES; - msg += n * SKEIN_256_BLOCK_BYTES; - } - Skein_assert(ctx->h.bCnt == 0); - } - - /* copy any remaining source message data bytes into b[] */ - if (msgByteCnt) - { - Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES); - memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt); - ctx->h.bCnt += msgByteCnt; - } - - return SKEIN_SUCCESS; - } - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* finalize the hash computation and output the result */ -static int Skein_256_Final(Skein_256_Ctxt_t *ctx, u08b_t *hashVal) - { - size_t i,n,byteCnt; - u64b_t X[SKEIN_256_STATE_WORDS]; - Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ - if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) /* zero pad b[] if necessary */ - memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt); - - Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ - - /* now output the result */ - byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ - - /* run Threefish in "counter mode" to generate output */ - memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ - memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ - for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++) - { - ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ - Skein_Start_New_Type(ctx,OUT_FINAL); - Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ - n = byteCnt - i*SKEIN_256_BLOCK_BYTES; /* number of output bytes left to go */ - if (n >= SKEIN_256_BLOCK_BYTES) - n = SKEIN_256_BLOCK_BYTES; - Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ - Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES); - memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ - } - return SKEIN_SUCCESS; - } - -#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) -static size_t Skein_256_API_CodeSize(void) - { - return ((u08b_t *) Skein_256_API_CodeSize) - - ((u08b_t *) Skein_256_Init); - } -#endif - -/*****************************************************************/ -/* 512-bit Skein */ -/*****************************************************************/ - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* init the context for a straight hashing operation */ -static int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen) - { - union - { - u08b_t b[SKEIN_512_STATE_BYTES]; - u64b_t w[SKEIN_512_STATE_WORDS]; - } cfg; /* config block */ - - Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); - ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ - - switch (hashBitLen) - { /* use pre-computed values, where available */ -#ifndef SKEIN_NO_PRECOMP - case 512: memcpy(ctx->X,SKEIN_512_IV_512,sizeof(ctx->X)); break; - case 384: memcpy(ctx->X,SKEIN_512_IV_384,sizeof(ctx->X)); break; - case 256: memcpy(ctx->X,SKEIN_512_IV_256,sizeof(ctx->X)); break; - case 224: memcpy(ctx->X,SKEIN_512_IV_224,sizeof(ctx->X)); break; -#endif - default: - /* here if there is no precomputed IV value available */ - /* build/process the config block, type == CONFIG (could be precomputed) */ - Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */ - - cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */ - cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ - cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); - memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */ - - /* compute the initial chaining values from config block */ - memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */ - Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); - break; - } - - /* The chaining vars ctx->X are now initialized for the given hashBitLen. */ - /* Set up to process the data message portion of the hash (default) */ - Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */ - - return SKEIN_SUCCESS; - } - -#if 0 -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* init the context for a MAC and/or tree hash operation */ -/* [identical to Skein_512_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */ -static int Skein_512_InitExt(Skein_512_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes) - { - union - { - u08b_t b[SKEIN_512_STATE_BYTES]; - u64b_t w[SKEIN_512_STATE_WORDS]; - } cfg; /* config block */ - - Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); - Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL); - - /* compute the initial chaining values ctx->X[], based on key */ - if (keyBytes == 0) /* is there a key? */ - { - memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */ - } - else /* here to pre-process a key */ - { - Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X)); - /* do a mini-Init right here */ - ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */ - Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */ - memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */ - Skein_512_Update(ctx,key,keyBytes); /* hash the key */ - Skein_512_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */ - memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */ -#if SKEIN_NEED_SWAP - { - uint_t i; - for (i=0;iX[i] = Skein_Swap64(ctx->X[i]); - } -#endif - } - /* build/process the config block, type == CONFIG (could be precomputed for each key) */ - ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ - Skein_Start_New_Type(ctx,CFG_FINAL); - - memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */ - cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); - cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ - cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ - - Skein_Show_Key(512,&ctx->h,key,keyBytes); - - /* compute the initial chaining values from config block */ - Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); - - /* The chaining vars ctx->X are now initialized */ - /* Set up to process the data message portion of the hash (default) */ - ctx->h.bCnt = 0; /* buffer b[] starts out empty */ - Skein_Start_New_Type(ctx,MSG); - - return SKEIN_SUCCESS; - } -#endif - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* process the input bytes */ -static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt) - { - size_t n; - - Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - /* process full blocks, if any */ - if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) - { - if (ctx->h.bCnt) /* finish up any buffered message data */ - { - n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ - if (n) - { - Skein_assert(n < msgByteCnt); /* check on our logic here */ - memcpy(&ctx->b[ctx->h.bCnt],msg,n); - msgByteCnt -= n; - msg += n; - ctx->h.bCnt += n; - } - Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES); - Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES); - ctx->h.bCnt = 0; - } - /* now process any remaining full blocks, directly from input message data */ - if (msgByteCnt > SKEIN_512_BLOCK_BYTES) - { - n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */ - Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES); - msgByteCnt -= n * SKEIN_512_BLOCK_BYTES; - msg += n * SKEIN_512_BLOCK_BYTES; - } - Skein_assert(ctx->h.bCnt == 0); - } - - /* copy any remaining source message data bytes into b[] */ - if (msgByteCnt) - { - Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES); - memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt); - ctx->h.bCnt += msgByteCnt; - } - - return SKEIN_SUCCESS; - } - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* finalize the hash computation and output the result */ -static int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal) - { - size_t i,n,byteCnt; - u64b_t X[SKEIN_512_STATE_WORDS]; - Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ - if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */ - memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); - - Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ - - /* now output the result */ - byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ - - /* run Threefish in "counter mode" to generate output */ - memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ - memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ - for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++) - { - ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ - Skein_Start_New_Type(ctx,OUT_FINAL); - Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ - n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */ - if (n >= SKEIN_512_BLOCK_BYTES) - n = SKEIN_512_BLOCK_BYTES; - Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ - Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES); - memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ - } - return SKEIN_SUCCESS; - } - -#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) -static size_t Skein_512_API_CodeSize(void) - { - return ((u08b_t *) Skein_512_API_CodeSize) - - ((u08b_t *) Skein_512_Init); - } -#endif - -/*****************************************************************/ -/* 1024-bit Skein */ -/*****************************************************************/ -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* init the context for a straight hashing operation */ -static int Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen) - { - union - { - u08b_t b[SKEIN1024_STATE_BYTES]; - u64b_t w[SKEIN1024_STATE_WORDS]; - } cfg; /* config block */ - - Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); - ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ - - switch (hashBitLen) - { /* use pre-computed values, where available */ -#ifndef SKEIN_NO_PRECOMP - case 512: memcpy(ctx->X,SKEIN1024_IV_512 ,sizeof(ctx->X)); break; - case 384: memcpy(ctx->X,SKEIN1024_IV_384 ,sizeof(ctx->X)); break; - case 1024: memcpy(ctx->X,SKEIN1024_IV_1024,sizeof(ctx->X)); break; -#endif - default: - /* here if there is no precomputed IV value available */ - /* build/process the config block, type == CONFIG (could be precomputed) */ - Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */ - - cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */ - cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ - cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); - memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */ - - /* compute the initial chaining values from config block */ - memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */ - Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); - break; - } - - /* The chaining vars ctx->X are now initialized for the given hashBitLen. */ - /* Set up to process the data message portion of the hash (default) */ - Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */ - - return SKEIN_SUCCESS; - } - -#if 0 -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* init the context for a MAC and/or tree hash operation */ -/* [identical to Skein1024_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */ -static int Skein1024_InitExt(Skein1024_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes) - { - union - { - u08b_t b[SKEIN1024_STATE_BYTES]; - u64b_t w[SKEIN1024_STATE_WORDS]; - } cfg; /* config block */ - - Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); - Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL); - - /* compute the initial chaining values ctx->X[], based on key */ - if (keyBytes == 0) /* is there a key? */ - { - memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */ - } - else /* here to pre-process a key */ - { - Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X)); - /* do a mini-Init right here */ - ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */ - Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */ - memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */ - Skein1024_Update(ctx,key,keyBytes); /* hash the key */ - Skein1024_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */ - memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */ -#if SKEIN_NEED_SWAP - { - uint_t i; - for (i=0;iX[i] = Skein_Swap64(ctx->X[i]); - } -#endif - } - /* build/process the config block, type == CONFIG (could be precomputed for each key) */ - ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ - Skein_Start_New_Type(ctx,CFG_FINAL); - - memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */ - cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); - cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ - cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ - - Skein_Show_Key(1024,&ctx->h,key,keyBytes); - - /* compute the initial chaining values from config block */ - Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); - - /* The chaining vars ctx->X are now initialized */ - /* Set up to process the data message portion of the hash (default) */ - ctx->h.bCnt = 0; /* buffer b[] starts out empty */ - Skein_Start_New_Type(ctx,MSG); - - return SKEIN_SUCCESS; - } -#endif - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* process the input bytes */ -static int Skein1024_Update(Skein1024_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt) - { - size_t n; - - Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - /* process full blocks, if any */ - if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES) - { - if (ctx->h.bCnt) /* finish up any buffered message data */ - { - n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ - if (n) - { - Skein_assert(n < msgByteCnt); /* check on our logic here */ - memcpy(&ctx->b[ctx->h.bCnt],msg,n); - msgByteCnt -= n; - msg += n; - ctx->h.bCnt += n; - } - Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES); - Skein1024_Process_Block(ctx,ctx->b,1,SKEIN1024_BLOCK_BYTES); - ctx->h.bCnt = 0; - } - /* now process any remaining full blocks, directly from input message data */ - if (msgByteCnt > SKEIN1024_BLOCK_BYTES) - { - n = (msgByteCnt-1) / SKEIN1024_BLOCK_BYTES; /* number of full blocks to process */ - Skein1024_Process_Block(ctx,msg,n,SKEIN1024_BLOCK_BYTES); - msgByteCnt -= n * SKEIN1024_BLOCK_BYTES; - msg += n * SKEIN1024_BLOCK_BYTES; - } - Skein_assert(ctx->h.bCnt == 0); - } - - /* copy any remaining source message data bytes into b[] */ - if (msgByteCnt) - { - Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES); - memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt); - ctx->h.bCnt += msgByteCnt; - } - - return SKEIN_SUCCESS; - } - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* finalize the hash computation and output the result */ -static int Skein1024_Final(Skein1024_Ctxt_t *ctx, u08b_t *hashVal) - { - size_t i,n,byteCnt; - u64b_t X[SKEIN1024_STATE_WORDS]; - Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ - if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) /* zero pad b[] if necessary */ - memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt); - - Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ - - /* now output the result */ - byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ - - /* run Threefish in "counter mode" to generate output */ - memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ - memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ - for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++) - { - ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ - Skein_Start_New_Type(ctx,OUT_FINAL); - Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ - n = byteCnt - i*SKEIN1024_BLOCK_BYTES; /* number of output bytes left to go */ - if (n >= SKEIN1024_BLOCK_BYTES) - n = SKEIN1024_BLOCK_BYTES; - Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ - Skein_Show_Final(1024,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES); - memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ - } - return SKEIN_SUCCESS; - } - -#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) -static size_t Skein1024_API_CodeSize(void) - { - return ((u08b_t *) Skein1024_API_CodeSize) - - ((u08b_t *) Skein1024_Init); - } -#endif - -/**************** Functions to support MAC/tree hashing ***************/ -/* (this code is identical for Optimized and Reference versions) */ - -#if 0 -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* finalize the hash computation and output the block, no OUTPUT stage */ -static int Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, u08b_t *hashVal) - { - Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ - if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) /* zero pad b[] if necessary */ - memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt); - Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ - - Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_256_BLOCK_BYTES); /* "output" the state bytes */ - - return SKEIN_SUCCESS; - } - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* finalize the hash computation and output the block, no OUTPUT stage */ -static int Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, u08b_t *hashVal) - { - Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ - if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */ - memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); - Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ - - Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_512_BLOCK_BYTES); /* "output" the state bytes */ - - return SKEIN_SUCCESS; - } - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* finalize the hash computation and output the block, no OUTPUT stage */ -static int Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, u08b_t *hashVal) - { - Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ - if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) /* zero pad b[] if necessary */ - memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt); - Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ - - Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN1024_BLOCK_BYTES); /* "output" the state bytes */ - - return SKEIN_SUCCESS; - } - - -#if SKEIN_TREE_HASH -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* just do the OUTPUT stage */ -static int Skein_256_Output(Skein_256_Ctxt_t *ctx, u08b_t *hashVal) - { - size_t i,n,byteCnt; - u64b_t X[SKEIN_256_STATE_WORDS]; - Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - /* now output the result */ - byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ - - /* run Threefish in "counter mode" to generate output */ - memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ - memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ - for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++) - { - ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ - Skein_Start_New_Type(ctx,OUT_FINAL); - Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ - n = byteCnt - i*SKEIN_256_BLOCK_BYTES; /* number of output bytes left to go */ - if (n >= SKEIN_256_BLOCK_BYTES) - n = SKEIN_256_BLOCK_BYTES; - Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ - Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES); - memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ - } - return SKEIN_SUCCESS; - } - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* just do the OUTPUT stage */ -static int Skein_512_Output(Skein_512_Ctxt_t *ctx, u08b_t *hashVal) - { - size_t i,n,byteCnt; - u64b_t X[SKEIN_512_STATE_WORDS]; - Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - /* now output the result */ - byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ - - /* run Threefish in "counter mode" to generate output */ - memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ - memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ - for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++) - { - ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ - Skein_Start_New_Type(ctx,OUT_FINAL); - Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ - n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */ - if (n >= SKEIN_512_BLOCK_BYTES) - n = SKEIN_512_BLOCK_BYTES; - Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ - Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES); - memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ - } - return SKEIN_SUCCESS; - } - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* just do the OUTPUT stage */ -static int Skein1024_Output(Skein1024_Ctxt_t *ctx, u08b_t *hashVal) - { - size_t i,n,byteCnt; - u64b_t X[SKEIN1024_STATE_WORDS]; - Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ - - /* now output the result */ - byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ - - /* run Threefish in "counter mode" to generate output */ - memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ - memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ - for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++) - { - ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ - Skein_Start_New_Type(ctx,OUT_FINAL); - Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ - n = byteCnt - i*SKEIN1024_BLOCK_BYTES; /* number of output bytes left to go */ - if (n >= SKEIN1024_BLOCK_BYTES) - n = SKEIN1024_BLOCK_BYTES; - Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ - Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES); - memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ - } - return SKEIN_SUCCESS; - } -#endif -#endif - -typedef struct -{ - uint_t statebits; /* 256, 512, or 1024 */ - union - { - Skein_Ctxt_Hdr_t h; /* common header "overlay" */ - Skein_256_Ctxt_t ctx_256; - Skein_512_Ctxt_t ctx_512; - Skein1024_Ctxt_t ctx1024; - } u; -} -hashState; - -/* "incremental" hashing API */ -static HashReturn Init (hashState *state, int hashbitlen); -static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); -static HashReturn Final (hashState *state, BitSequence *hashval); - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* select the context size and init the context */ -static HashReturn Init(hashState *state, int hashbitlen) -{ -#if SKEIN_256_NIST_MAX_HASHBITS - if (hashbitlen <= SKEIN_256_NIST_MAX_HASHBITS) - { - Skein_Assert(hashbitlen > 0,BAD_HASHLEN); - state->statebits = 64*SKEIN_256_STATE_WORDS; - return Skein_256_Init(&state->u.ctx_256,(size_t) hashbitlen); - } -#endif - if (hashbitlen <= SKEIN_512_NIST_MAX_HASHBITS) - { - state->statebits = 64*SKEIN_512_STATE_WORDS; - return Skein_512_Init(&state->u.ctx_512,(size_t) hashbitlen); - } - else - { - state->statebits = 64*SKEIN1024_STATE_WORDS; - return Skein1024_Init(&state->u.ctx1024,(size_t) hashbitlen); - } -} - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* process data to be hashed */ -static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) -{ - /* only the final Update() call is allowed do partial bytes, else assert an error */ - Skein_Assert((state->u.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || databitlen == 0, SKEIN_FAIL); - - Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,SKEIN_FAIL); - if ((databitlen & 7) == 0) /* partial bytes? */ - { - switch ((state->statebits >> 8) & 3) - { - case 2: return Skein_512_Update(&state->u.ctx_512,data,databitlen >> 3); - case 1: return Skein_256_Update(&state->u.ctx_256,data,databitlen >> 3); - case 0: return Skein1024_Update(&state->u.ctx1024,data,databitlen >> 3); - default: return SKEIN_FAIL; - } - } - else - { /* handle partial final byte */ - size_t bCnt = (databitlen >> 3) + 1; /* number of bytes to handle (nonzero here!) */ - u08b_t b,mask; - - mask = (u08b_t) (1u << (7 - (databitlen & 7))); /* partial byte bit mask */ - b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask); /* apply bit padding on final byte */ - - switch ((state->statebits >> 8) & 3) - { - case 2: Skein_512_Update(&state->u.ctx_512,data,bCnt-1); /* process all but the final byte */ - Skein_512_Update(&state->u.ctx_512,&b , 1 ); /* process the (masked) partial byte */ - break; - case 1: Skein_256_Update(&state->u.ctx_256,data,bCnt-1); /* process all but the final byte */ - Skein_256_Update(&state->u.ctx_256,&b , 1 ); /* process the (masked) partial byte */ - break; - case 0: Skein1024_Update(&state->u.ctx1024,data,bCnt-1); /* process all but the final byte */ - Skein1024_Update(&state->u.ctx1024,&b , 1 ); /* process the (masked) partial byte */ - break; - default: return SKEIN_FAIL; - } - Skein_Set_Bit_Pad_Flag(state->u.h); /* set tweak flag for the final call */ - - return SKEIN_SUCCESS; - } -} - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* finalize hash computation and output the result (hashbitlen bits) */ -static HashReturn Final(hashState *state, BitSequence *hashval) -{ - Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,FAIL); - switch ((state->statebits >> 8) & 3) - { - case 2: return Skein_512_Final(&state->u.ctx_512,hashval); - case 1: return Skein_256_Final(&state->u.ctx_256,hashval); - case 0: return Skein1024_Final(&state->u.ctx1024,hashval); - default: return SKEIN_FAIL; - } -} - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* all-in-one hash function */ -HashReturn skein_hash(int hashbitlen, const BitSequence *data, /* all-in-one call */ - DataLength databitlen,BitSequence *hashval) -{ - hashState state; - HashReturn r = Init(&state,hashbitlen); - if (r == SKEIN_SUCCESS) - { /* these calls do not fail when called properly */ - r = Update(&state,data,databitlen); - Final(&state,hashval); - } - return r; -} diff --git a/src/Native/libcryptonote/crypto/skein.h b/src/Native/libcryptonote/crypto/skein.h deleted file mode 100644 index 5c9cc5518..000000000 --- a/src/Native/libcryptonote/crypto/skein.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _SKEIN_H_ -#define _SKEIN_H_ 1 -/************************************************************************** -** -** Interface declarations and internal definitions for Skein hashing. -** -** Source code author: Doug Whiting, 2008. -** -** This algorithm and source code is released to the public domain. -** -*************************************************************************** -** -** The following compile-time switches may be defined to control some -** tradeoffs between speed, code size, error checking, and security. -** -** The "default" note explains what happens when the switch is not defined. -** -** SKEIN_DEBUG -- make callouts from inside Skein code -** to examine/display intermediate values. -** [default: no callouts (no overhead)] -** -** SKEIN_ERR_CHECK -- how error checking is handled inside Skein -** code. If not defined, most error checking -** is disabled (for performance). Otherwise, -** the switch value is interpreted as: -** 0: use assert() to flag errors -** 1: return SKEIN_FAIL to flag errors -** -***************************************************************************/ -#include "skein_port.h" /* get platform-specific definitions */ - -typedef enum -{ - SKEIN_SUCCESS = 0, /* return codes from Skein calls */ - SKEIN_FAIL = 1, - SKEIN_BAD_HASHLEN = 2 -} -HashReturn; - -typedef size_t DataLength; /* bit count type */ -typedef u08b_t BitSequence; /* bit stream type */ - -/* "all-in-one" call */ -HashReturn skein_hash(int hashbitlen, const BitSequence *data, - DataLength databitlen, BitSequence *hashval); - -#endif /* ifndef _SKEIN_H_ */ diff --git a/src/Native/libcryptonote/crypto/skein_port.h b/src/Native/libcryptonote/crypto/skein_port.h deleted file mode 100644 index a50a28e6b..000000000 --- a/src/Native/libcryptonote/crypto/skein_port.h +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef _SKEIN_PORT_H_ -#define _SKEIN_PORT_H_ - -#include -#include - -#ifndef RETURN_VALUES -# define RETURN_VALUES -# if defined( DLL_EXPORT ) -# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) -# define VOID_RETURN __declspec( dllexport ) void __stdcall -# define INT_RETURN __declspec( dllexport ) int __stdcall -# elif defined( __GNUC__ ) -# define VOID_RETURN __declspec( __dllexport__ ) void -# define INT_RETURN __declspec( __dllexport__ ) int -# else -# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers -# endif -# elif defined( DLL_IMPORT ) -# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) -# define VOID_RETURN __declspec( dllimport ) void __stdcall -# define INT_RETURN __declspec( dllimport ) int __stdcall -# elif defined( __GNUC__ ) -# define VOID_RETURN __declspec( __dllimport__ ) void -# define INT_RETURN __declspec( __dllimport__ ) int -# else -# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers -# endif -# elif defined( __WATCOMC__ ) -# define VOID_RETURN void __cdecl -# define INT_RETURN int __cdecl -# else -# define VOID_RETURN void -# define INT_RETURN int -# endif -#endif - -/* These defines are used to declare buffers in a way that allows - faster operations on longer variables to be used. In all these - defines 'size' must be a power of 2 and >= 8 - - dec_unit_type(size,x) declares a variable 'x' of length - 'size' bits - - dec_bufr_type(size,bsize,x) declares a buffer 'x' of length 'bsize' - bytes defined as an array of variables - each of 'size' bits (bsize must be a - multiple of size / 8) - - ptr_cast(x,size) casts a pointer to a pointer to a - varaiable of length 'size' bits -*/ - -#define ui_type(size) uint##size##_t -#define dec_unit_type(size,x) typedef ui_type(size) x -#define dec_bufr_type(size,bsize,x) typedef ui_type(size) x[bsize / (size >> 3)] -#define ptr_cast(x,size) ((ui_type(size)*)(x)) - -typedef unsigned int uint_t; /* native unsigned integer */ -typedef uint8_t u08b_t; /* 8-bit unsigned integer */ -typedef uint64_t u64b_t; /* 64-bit unsigned integer */ - -#ifndef RotL_64 -#define RotL_64(x,N) (((x) << (N)) | ((x) >> (64-(N)))) -#endif - -/* - * Skein is "natively" little-endian (unlike SHA-xxx), for optimal - * performance on x86 CPUs. The Skein code requires the following - * definitions for dealing with endianness: - * - * SKEIN_NEED_SWAP: 0 for little-endian, 1 for big-endian - * Skein_Put64_LSB_First - * Skein_Get64_LSB_First - * Skein_Swap64 - * - * If SKEIN_NEED_SWAP is defined at compile time, it is used here - * along with the portable versions of Put64/Get64/Swap64, which - * are slow in general. - * - * Otherwise, an "auto-detect" of endianness is attempted below. - * If the default handling doesn't work well, the user may insert - * platform-specific code instead (e.g., for big-endian CPUs). - * - */ -#ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */ - - -#include "common/int-util.h" - -#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ -#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ - -#if BYTE_ORDER == LITTLE_ENDIAN -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -#endif - -#if BYTE_ORDER == BIG_ENDIAN -# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN -#endif - -/* special handler for IA64, which may be either endianness (?) */ -/* here we assume little-endian, but this may need to be changed */ -#if defined(__ia64) || defined(__ia64__) || defined(_M_IA64) -# define PLATFORM_MUST_ALIGN (1) -#ifndef PLATFORM_BYTE_ORDER -# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN -#endif -#endif - -#ifndef PLATFORM_MUST_ALIGN -# define PLATFORM_MUST_ALIGN (0) -#endif - - -#if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN - /* here for big-endian CPUs */ -#define SKEIN_NEED_SWAP (1) -#elif PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN - /* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */ -#define SKEIN_NEED_SWAP (0) -#if PLATFORM_MUST_ALIGN == 0 /* ok to use "fast" versions? */ -#define Skein_Put64_LSB_First(dst08,src64,bCnt) memcpy(dst08,src64,bCnt) -#define Skein_Get64_LSB_First(dst64,src08,wCnt) memcpy(dst64,src08,8*(wCnt)) -#endif -#else -#error "Skein needs endianness setting!" -#endif - -#endif /* ifndef SKEIN_NEED_SWAP */ - -/* - ****************************************************************** - * Provide any definitions still needed. - ****************************************************************** - */ -#ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */ -#if SKEIN_NEED_SWAP -#define Skein_Swap64(w64) \ - ( (( ((u64b_t)(w64)) & 0xFF) << 56) | \ - (((((u64b_t)(w64)) >> 8) & 0xFF) << 48) | \ - (((((u64b_t)(w64)) >>16) & 0xFF) << 40) | \ - (((((u64b_t)(w64)) >>24) & 0xFF) << 32) | \ - (((((u64b_t)(w64)) >>32) & 0xFF) << 24) | \ - (((((u64b_t)(w64)) >>40) & 0xFF) << 16) | \ - (((((u64b_t)(w64)) >>48) & 0xFF) << 8) | \ - (((((u64b_t)(w64)) >>56) & 0xFF) ) ) -#else -#define Skein_Swap64(w64) (w64) -#endif -#endif /* ifndef Skein_Swap64 */ - - -#ifndef Skein_Put64_LSB_First -void Skein_Put64_LSB_First(u08b_t *dst,const u64b_t *src,size_t bCnt) -#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */ - { /* this version is fully portable (big-endian or little-endian), but slow */ - size_t n; - - for (n=0;n>3] >> (8*(n&7))); - } -#else - ; /* output only the function prototype */ -#endif -#endif /* ifndef Skein_Put64_LSB_First */ - - -#ifndef Skein_Get64_LSB_First -void Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt) -#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */ - { /* this version is fully portable (big-endian or little-endian), but slow */ - size_t n; - - for (n=0;n<8*wCnt;n+=8) - dst[n/8] = (((u64b_t) src[n ]) ) + - (((u64b_t) src[n+1]) << 8) + - (((u64b_t) src[n+2]) << 16) + - (((u64b_t) src[n+3]) << 24) + - (((u64b_t) src[n+4]) << 32) + - (((u64b_t) src[n+5]) << 40) + - (((u64b_t) src[n+6]) << 48) + - (((u64b_t) src[n+7]) << 56) ; - } -#else - ; /* output only the function prototype */ -#endif -#endif /* ifndef Skein_Get64_LSB_First */ - -#endif /* ifndef _SKEIN_PORT_H_ */ diff --git a/src/Native/libcryptonote/crypto/slow-hash-lite.c b/src/Native/libcryptonote/crypto/slow-hash-lite.c deleted file mode 100644 index f47e7c9ef..000000000 --- a/src/Native/libcryptonote/crypto/slow-hash-lite.c +++ /dev/null @@ -1,1245 +0,0 @@ -// Copyright (c) 2014-2017, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include -#include -#include - -#include "common/int-util.h" -#include "hash-ops.h" -#include "oaes_lib.h" - -#define MEMORY (1 << 20) // 1MB scratchpad -#define ITER (1 << 19) -#define AES_BLOCK_SIZE 16 -#define AES_KEY_SIZE 32 -#define INIT_SIZE_BLK 8 -#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE) - -extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey); -extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); - -#if defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64)) -// Optimised code below, uses x86-specific intrinsics, SSE2, AES-NI -// Fall back to more portable code is down at the bottom - -#include - -#if defined(_MSC_VER) -#include -#include -#define STATIC -#define INLINE __inline -#if !defined(RDATA_ALIGN16) -#define RDATA_ALIGN16 __declspec(align(16)) -#endif -#elif defined(__MINGW32__) -#include -#include -#define STATIC static -#define INLINE inline -#if !defined(RDATA_ALIGN16) -#define RDATA_ALIGN16 __attribute__ ((aligned(16))) -#endif -#else -#include -#include -#define STATIC static -#define INLINE inline -#if !defined(RDATA_ALIGN16) -#define RDATA_ALIGN16 __attribute__ ((aligned(16))) -#endif -#endif - -#if defined(__INTEL_COMPILER) -#define ASM __asm__ -#elif !defined(_MSC_VER) -#define ASM __asm__ -#else -#define ASM __asm -#endif - -#define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE) - -#define U64(x) ((uint64_t *) (x)) -#define R128(x) ((__m128i *) (x)) - -#define state_index(x) (((*((uint64_t *)x) >> 4) & (TOTALBLOCKS - 1)) << 4) -#if defined(_MSC_VER) -#if !defined(_WIN64) -#define __mul() lo = mul128(c[0], b[0], &hi); -#else -#define __mul() lo = _umul128(c[0], b[0], &hi); -#endif -#else -#if defined(__x86_64__) -#define __mul() ASM("mulq %3\n\t" : "=d"(hi), "=a"(lo) : "%a" (c[0]), "rm" (b[0]) : "cc"); -#else -#define __mul() lo = mul128(c[0], b[0], &hi); -#endif -#endif - -#define pre_aes() \ - j = state_index(a); \ - _c = _mm_load_si128(R128(&hp_state_lite[j])); \ - _a = _mm_load_si128(R128(a)); \ - -/* - * An SSE-optimized implementation of the second half of CryptoNight step 3. - * After using AES to mix a scratchpad value into _c (done by the caller), - * this macro xors it with _b and stores the result back to the same index (j) that it - * loaded the scratchpad value from. It then performs a second random memory - * read/write from the scratchpad, but this time mixes the values using a 64 - * bit multiply. - * This code is based upon an optimized implementation by dga. - */ -#define post_aes() \ - _mm_store_si128(R128(c), _c); \ - _b = _mm_xor_si128(_b, _c); \ - _mm_store_si128(R128(&hp_state_lite[j]), _b); \ - j = state_index(c); \ - p = U64(&hp_state_lite[j]); \ - b[0] = p[0]; b[1] = p[1]; \ - __mul(); \ - a[0] += hi; a[1] += lo; \ - p = U64(&hp_state_lite[j]); \ - p[0] = a[0]; p[1] = a[1]; \ - a[0] ^= b[0]; a[1] ^= b[1]; \ - _b = _c; \ - -#if defined(_MSC_VER) -#define THREADV __declspec(thread) -#else -#define THREADV __thread -#endif - -#pragma pack(push, 1) -union cn_slow_hash_state -{ - union hash_state hs; - struct - { - uint8_t k[64]; - uint8_t init[INIT_SIZE_BYTE]; - }; -}; -#pragma pack(pop) - -THREADV uint8_t *hp_state_lite = NULL; -THREADV int hp_allocated_lite = 0; - -#if defined(_MSC_VER) -#define cpuid(info,x) __cpuidex(info,x,0) -#else -extern void cpuid(int CPUInfo[4], int InfoType); -#endif - -/** - * @brief a = (a xor b), where a and b point to 128 bit values - */ - -STATIC INLINE void xor_blocks(uint8_t *a, const uint8_t *b) -{ - U64(a)[0] ^= U64(b)[0]; - U64(a)[1] ^= U64(b)[1]; -} - -/** - * @brief uses cpuid to determine if the CPU supports the AES instructions - * @return true if the CPU supports AES, false otherwise - */ - -STATIC INLINE int force_software_aes(void) -{ - static int use = -1; - - if (use != -1) - return use; - - const char *env = getenv("MONERO_USE_SOFTWARE_AES"); - if (!env) { - use = 0; - } - else if (!strcmp(env, "0") || !strcmp(env, "no")) { - use = 0; - } - else { - use = 1; - } - return use; -} - -STATIC INLINE int check_aes_hw(void) -{ - int cpuid_results[4]; - static int supported = -1; - - if(supported >= 0) - return supported; - - cpuid(cpuid_results,1); - return supported = cpuid_results[2] & (1 << 25); -} - -STATIC INLINE void aes_256_assist1(__m128i* t1, __m128i * t2) -{ - __m128i t4; - *t2 = _mm_shuffle_epi32(*t2, 0xff); - t4 = _mm_slli_si128(*t1, 0x04); - *t1 = _mm_xor_si128(*t1, t4); - t4 = _mm_slli_si128(t4, 0x04); - *t1 = _mm_xor_si128(*t1, t4); - t4 = _mm_slli_si128(t4, 0x04); - *t1 = _mm_xor_si128(*t1, t4); - *t1 = _mm_xor_si128(*t1, *t2); -} - -STATIC INLINE void aes_256_assist2(__m128i* t1, __m128i * t3) -{ - __m128i t2, t4; - t4 = _mm_aeskeygenassist_si128(*t1, 0x00); - t2 = _mm_shuffle_epi32(t4, 0xaa); - t4 = _mm_slli_si128(*t3, 0x04); - *t3 = _mm_xor_si128(*t3, t4); - t4 = _mm_slli_si128(t4, 0x04); - *t3 = _mm_xor_si128(*t3, t4); - t4 = _mm_slli_si128(t4, 0x04); - *t3 = _mm_xor_si128(*t3, t4); - *t3 = _mm_xor_si128(*t3, t2); -} - -/** - * @brief expands 'key' into a form it can be used for AES encryption. - * - * This is an SSE-optimized implementation of AES key schedule generation. It - * expands the key into multiple round keys, each of which is used in one round - * of the AES encryption used to fill (and later, extract randomness from) - * the large 2MB buffer. Note that CryptoNight does not use a completely - * standard AES encryption for its buffer expansion, so do not copy this - * function outside of Monero without caution! This version uses the hardware - * AESKEYGENASSIST instruction to speed key generation, and thus requires - * CPU AES support. - * For more information about these functions, see page 19 of Intel's AES instructions - * white paper: - * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/aes-instructions-set-white-paper.pdf - * - * @param key the input 128 bit key - * @param expandedKey An output buffer to hold the generated key schedule - */ - -STATIC INLINE void aes_expand_key(const uint8_t *key, uint8_t *expandedKey) -{ - __m128i *ek = R128(expandedKey); - __m128i t1, t2, t3; - - t1 = _mm_loadu_si128(R128(key)); - t3 = _mm_loadu_si128(R128(key + 16)); - - ek[0] = t1; - ek[1] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x01); - aes_256_assist1(&t1, &t2); - ek[2] = t1; - aes_256_assist2(&t1, &t3); - ek[3] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x02); - aes_256_assist1(&t1, &t2); - ek[4] = t1; - aes_256_assist2(&t1, &t3); - ek[5] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x04); - aes_256_assist1(&t1, &t2); - ek[6] = t1; - aes_256_assist2(&t1, &t3); - ek[7] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x08); - aes_256_assist1(&t1, &t2); - ek[8] = t1; - aes_256_assist2(&t1, &t3); - ek[9] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x10); - aes_256_assist1(&t1, &t2); - ek[10] = t1; -} - -/** - * @brief a "pseudo" round of AES (similar to but slightly different from normal AES encryption) - * - * To fill its 2MB scratch buffer, CryptoNight uses a nonstandard implementation - * of AES encryption: It applies 10 rounds of the basic AES encryption operation - * to an input 128 bit chunk of data . Unlike normal AES, however, this is - * all it does; it does not perform the initial AddRoundKey step (this is done - * in subsequent steps by aesenc_si128), and it does not use the simpler final round. - * Hence, this is a "pseudo" round - though the function actually implements 10 rounds together. - * - * Note that unlike aesb_pseudo_round, this function works on multiple data chunks. - * - * @param in a pointer to nblocks * 128 bits of data to be encrypted - * @param out a pointer to an nblocks * 128 bit buffer where the output will be stored - * @param expandedKey the expanded AES key - * @param nblocks the number of 128 blocks of data to be encrypted - */ - -STATIC INLINE void aes_pseudo_round(const uint8_t *in, uint8_t *out, - const uint8_t *expandedKey, int nblocks) -{ - __m128i *k = R128(expandedKey); - __m128i d; - int i; - - for(i = 0; i < nblocks; i++) - { - d = _mm_loadu_si128(R128(in + i * AES_BLOCK_SIZE)); - d = _mm_aesenc_si128(d, *R128(&k[0])); - d = _mm_aesenc_si128(d, *R128(&k[1])); - d = _mm_aesenc_si128(d, *R128(&k[2])); - d = _mm_aesenc_si128(d, *R128(&k[3])); - d = _mm_aesenc_si128(d, *R128(&k[4])); - d = _mm_aesenc_si128(d, *R128(&k[5])); - d = _mm_aesenc_si128(d, *R128(&k[6])); - d = _mm_aesenc_si128(d, *R128(&k[7])); - d = _mm_aesenc_si128(d, *R128(&k[8])); - d = _mm_aesenc_si128(d, *R128(&k[9])); - _mm_storeu_si128((R128(out + i * AES_BLOCK_SIZE)), d); - } -} - -/** - * @brief aes_pseudo_round that loads data from *in and xors it with *xor first - * - * This function performs the same operations as aes_pseudo_round, but before - * performing the encryption of each 128 bit block from , it xors - * it with the corresponding block from . - * - * @param in a pointer to nblocks * 128 bits of data to be encrypted - * @param out a pointer to an nblocks * 128 bit buffer where the output will be stored - * @param expandedKey the expanded AES key - * @param xor a pointer to an nblocks * 128 bit buffer that is xored into in before encryption (in is left unmodified) - * @param nblocks the number of 128 blocks of data to be encrypted - */ - -STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, - const uint8_t *expandedKey, const uint8_t *xor, int nblocks) -{ - __m128i *k = R128(expandedKey); - __m128i *x = R128(xor); - __m128i d; - int i; - - for(i = 0; i < nblocks; i++) - { - d = _mm_loadu_si128(R128(in + i * AES_BLOCK_SIZE)); - d = _mm_xor_si128(d, *R128(x++)); - d = _mm_aesenc_si128(d, *R128(&k[0])); - d = _mm_aesenc_si128(d, *R128(&k[1])); - d = _mm_aesenc_si128(d, *R128(&k[2])); - d = _mm_aesenc_si128(d, *R128(&k[3])); - d = _mm_aesenc_si128(d, *R128(&k[4])); - d = _mm_aesenc_si128(d, *R128(&k[5])); - d = _mm_aesenc_si128(d, *R128(&k[6])); - d = _mm_aesenc_si128(d, *R128(&k[7])); - d = _mm_aesenc_si128(d, *R128(&k[8])); - d = _mm_aesenc_si128(d, *R128(&k[9])); - _mm_storeu_si128((R128(out + i * AES_BLOCK_SIZE)), d); - } -} - -#if defined(_MSC_VER) || defined(__MINGW32__) -extern BOOL SetLockPagesPrivilege(HANDLE hProcess, BOOL bEnable); -#endif - -/** - * @brief allocate the 2MB scratch buffer using OS support for huge pages, if available - * - * This function tries to allocate the 2MB scratch buffer using a single - * 2MB "huge page" (instead of the usual 4KB page sizes) to reduce TLB misses - * during the random accesses to the scratch buffer. This is one of the - * important speed optimizations needed to make CryptoNight faster. - * - * No parameters. Updates a thread-local pointer, hp_state_lite, to point to - * the allocated buffer. - */ - -void slow_hash_allocate_state_lite(void) -{ - if(hp_state_lite != NULL) - return; - -#if defined(_MSC_VER) || defined(__MINGW32__) - SetLockPagesPrivilege(GetCurrentProcess(), TRUE); - hp_state_lite = (uint8_t *) VirtualAlloc(hp_state_lite, MEMORY, MEM_LARGE_PAGES | - MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); -#else -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__DragonFly__) - hp_state_lite = mmap(0, MEMORY, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, 0, 0); -#else - hp_state_lite = mmap(0, MEMORY, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, 0, 0); -#endif - if(hp_state_lite == MAP_FAILED) - hp_state_lite = NULL; -#endif - hp_allocated_lite = 1; - if(hp_state_lite == NULL) - { - hp_allocated_lite = 0; - hp_state_lite = (uint8_t *) malloc(MEMORY); - } -} - -/** - *@brief frees the state allocated by slow_hash_allocate_state_lite - */ - -void slow_hash_free_state_lite(void) -{ - if(hp_state_lite == NULL) - return; - - if(!hp_allocated_lite) - free(hp_state_lite); - else - { -#if defined(_MSC_VER) || defined(__MINGW32__) - VirtualFree(hp_state_lite, MEMORY, MEM_RELEASE); -#else - munmap(hp_state_lite, MEMORY); -#endif - } - - hp_state_lite = NULL; - hp_allocated_lite = 0; -} - -/** - * @brief the hash function implementing CryptoNight, used for the Monero proof-of-work - * - * Computes the hash of (which consists of bytes), returning the - * hash in . The CryptoNight hash operates by first using Keccak 1600, - * the 1600 bit variant of the Keccak hash used in SHA-3, to create a 200 byte - * buffer of pseudorandom data by hashing the supplied data. It then uses this - * random data to fill a large 2MB buffer with pseudorandom data by iteratively - * encrypting it using 10 rounds of AES per entry. After this initialization, - * it executes 524,288 rounds of mixing through the random 2MB buffer using - * AES (typically provided in hardware on modern CPUs) and a 64 bit multiply. - * Finally, it re-mixes this large buffer back into - * the 200 byte "text" buffer, and then hashes this buffer using one of four - * pseudorandomly selected hash functions (Blake, Groestl, JH, or Skein) - * to populate the output. - * - * The 2MB buffer and choice of functions for mixing are designed to make the - * algorithm "CPU-friendly" (and thus, reduce the advantage of GPU, FPGA, - * or ASIC-based implementations): the functions used are fast on modern - * CPUs, and the 2MB size matches the typical amount of L3 cache available per - * core on 2013-era CPUs. When available, this implementation will use hardware - * AES support on x86 CPUs. - * - * A diagram of the inner loop of this function can be found at - * http://www.cs.cmu.edu/~dga/crypto/xmr/cryptonight.png - * - * @param data the data to hash - * @param length the length in bytes of the data - * @param hash a pointer to a buffer in which the final 256 bit hash will be stored - */ - -void cn_slow_hash_lite(const void *data, size_t length, char *hash) -{ - RDATA_ALIGN16 uint8_t expandedKey[240]; /* These buffers are aligned to use later with SSE functions */ - - uint8_t text[INIT_SIZE_BYTE]; - RDATA_ALIGN16 uint64_t a[2]; - RDATA_ALIGN16 uint64_t b[2]; - RDATA_ALIGN16 uint64_t c[2]; - union cn_slow_hash_state state; - __m128i _a, _b, _c; - uint64_t hi, lo; - - size_t i, j; - uint64_t *p = NULL; - oaes_ctx *aes_ctx = NULL; - int useAes = !force_software_aes() && check_aes_hw(); - - static void (*const extra_hashes[4])(const void *, size_t, char *) = - { - hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein - }; - - // this isn't supposed to happen, but guard against it for now. - if(hp_state_lite == NULL) - slow_hash_allocate_state_lite(); - - /* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */ - - hash_process(&state.hs, data, length); - memcpy(text, state.init, INIT_SIZE_BYTE); - - /* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill - * the 2MB large random access buffer. - */ - - if(useAes) - { - aes_expand_key(state.hs.b, expandedKey); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - aes_pseudo_round(text, text, expandedKey, INIT_SIZE_BLK); - memcpy(&hp_state_lite[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); - } - } - else - { - aes_ctx = (oaes_ctx *) oaes_alloc(); - oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - for(j = 0; j < INIT_SIZE_BLK; j++) - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); - - memcpy(&hp_state_lite[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); - } - } - - U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0]; - U64(a)[1] = U64(&state.k[0])[1] ^ U64(&state.k[32])[1]; - U64(b)[0] = U64(&state.k[16])[0] ^ U64(&state.k[48])[0]; - U64(b)[1] = U64(&state.k[16])[1] ^ U64(&state.k[48])[1]; - - /* CryptoNight Step 3: Bounce randomly 1,048,576 times (1<<20) through the mixing buffer, - * using 524,288 iterations of the following mixing function. Each execution - * performs two reads and writes from the mixing buffer. - */ - - _b = _mm_load_si128(R128(b)); - // Two independent versions, one with AES, one without, to ensure that - // the useAes test is only performed once, not every iteration. - if(useAes) - { - for(i = 0; i < ITER / 2; i++) - { - pre_aes(); - _c = _mm_aesenc_si128(_c, _a); - post_aes(); - } - } - else - { - for(i = 0; i < ITER / 2; i++) - { - pre_aes(); - aesb_single_round((uint8_t *) &_c, (uint8_t *) &_c, (uint8_t *) &_a); - post_aes(); - } - } - - /* CryptoNight Step 4: Sequentially pass through the mixing buffer and use 10 rounds - * of AES encryption to mix the random data back into the 'text' buffer. 'text' - * was originally created with the output of Keccak1600. */ - - memcpy(text, state.init, INIT_SIZE_BYTE); - if(useAes) - { - aes_expand_key(&state.hs.b[32], expandedKey); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - // add the xor to the pseudo round - aes_pseudo_round_xor(text, text, expandedKey, &hp_state_lite[i * INIT_SIZE_BYTE], INIT_SIZE_BLK); - } - } - else - { - oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - for(j = 0; j < INIT_SIZE_BLK; j++) - { - xor_blocks(&text[j * AES_BLOCK_SIZE], &hp_state_lite[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); - } - } - oaes_free((OAES_CTX **) &aes_ctx); - } - - /* CryptoNight Step 5: Apply Keccak to the state again, and then - * use the resulting data to select which of four finalizer - * hash functions to apply to the data (Blake, Groestl, JH, or Skein). - * Use this hash to squeeze the state array down - * to the final 256 bit hash output. - */ - - memcpy(state.init, text, INIT_SIZE_BYTE); - hash_permutation(&state.hs); - extra_hashes[state.hs.b[0] & 3](&state, 200, hash); -} - -#elif defined(__arm__) || defined(__aarch64__) -void slow_hash_allocate_state_lite(void) -{ - // Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c - return; -} - -void slow_hash_free_state_lite(void) -{ - // As above - return; -} - -#if defined(__GNUC__) -#define RDATA_ALIGN16 __attribute__ ((aligned(16))) -#define STATIC static -#define INLINE inline -#else -#define RDATA_ALIGN16 -#define STATIC static -#define INLINE -#endif - -#define U64(x) ((uint64_t *) (x)) - -#pragma pack(push, 1) -union cn_slow_hash_state -{ - union hash_state hs; - struct - { - uint8_t k[64]; - uint8_t init[INIT_SIZE_BYTE]; - }; -}; -#pragma pack(pop) - -#if defined(__aarch64__) && defined(__ARM_FEATURE_CRYPTO) - -/* ARMv8-A optimized with NEON and AES instructions. - * Copied from the x86-64 AES-NI implementation. It has much the same - * characteristics as x86-64: there's no 64x64=128 multiplier for vectors, - * and moving between vector and regular registers stalls the pipeline. - */ -#include - -#define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE) - -#define state_index(x) (((*((uint64_t *)x) >> 4) & (TOTALBLOCKS - 1)) << 4) -#define __mul() __asm__("mul %0, %1, %2\n\t" : "=r"(lo) : "r"(c[0]), "r"(b[0]) ); \ - __asm__("umulh %0, %1, %2\n\t" : "=r"(hi) : "r"(c[0]), "r"(b[0]) ); - -#define pre_aes() \ - j = state_index(a); \ - _c = vld1q_u8(&hp_state_lite[j]); \ - _a = vld1q_u8((const uint8_t *)a); \ - -#define post_aes() \ - vst1q_u8((uint8_t *)c, _c); \ - _b = veorq_u8(_b, _c); \ - vst1q_u8(&hp_state_lite[j], _b); \ - j = state_index(c); \ - p = U64(&hp_state_lite[j]); \ - b[0] = p[0]; b[1] = p[1]; \ - __mul(); \ - a[0] += hi; a[1] += lo; \ - p = U64(&hp_state_lite[j]); \ - p[0] = a[0]; p[1] = a[1]; \ - a[0] ^= b[0]; a[1] ^= b[1]; \ - _b = _c; \ - - -/* Note: this was based on a standard 256bit key schedule but - * it's been shortened since Cryptonight doesn't use the full - * key schedule. Don't try to use this for vanilla AES. -*/ -static void aes_expand_key(const uint8_t *key, uint8_t *expandedKey) { -static const int rcon[] = { - 0x01,0x01,0x01,0x01, - 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d, // rotate-n-splat - 0x1b,0x1b,0x1b,0x1b }; -__asm__( -" eor v0.16b,v0.16b,v0.16b\n" -" ld1 {v3.16b},[%0],#16\n" -" ld1 {v1.4s,v2.4s},[%2],#32\n" -" ld1 {v4.16b},[%0]\n" -" mov w2,#5\n" -" st1 {v3.4s},[%1],#16\n" -"\n" -"1:\n" -" tbl v6.16b,{v4.16b},v2.16b\n" -" ext v5.16b,v0.16b,v3.16b,#12\n" -" st1 {v4.4s},[%1],#16\n" -" aese v6.16b,v0.16b\n" -" subs w2,w2,#1\n" -"\n" -" eor v3.16b,v3.16b,v5.16b\n" -" ext v5.16b,v0.16b,v5.16b,#12\n" -" eor v3.16b,v3.16b,v5.16b\n" -" ext v5.16b,v0.16b,v5.16b,#12\n" -" eor v6.16b,v6.16b,v1.16b\n" -" eor v3.16b,v3.16b,v5.16b\n" -" shl v1.16b,v1.16b,#1\n" -" eor v3.16b,v3.16b,v6.16b\n" -" st1 {v3.4s},[%1],#16\n" -" b.eq 2f\n" -"\n" -" dup v6.4s,v3.s[3] // just splat\n" -" ext v5.16b,v0.16b,v4.16b,#12\n" -" aese v6.16b,v0.16b\n" -"\n" -" eor v4.16b,v4.16b,v5.16b\n" -" ext v5.16b,v0.16b,v5.16b,#12\n" -" eor v4.16b,v4.16b,v5.16b\n" -" ext v5.16b,v0.16b,v5.16b,#12\n" -" eor v4.16b,v4.16b,v5.16b\n" -"\n" -" eor v4.16b,v4.16b,v6.16b\n" -" b 1b\n" -"\n" -"2:\n" : : "r"(key), "r"(expandedKey), "r"(rcon)); -} - -/* An ordinary AES round is a sequence of SubBytes, ShiftRows, MixColumns, AddRoundKey. There - * is also an InitialRound which consists solely of AddRoundKey. The ARM instructions slice - * this sequence differently; the aese instruction performs AddRoundKey, SubBytes, ShiftRows. - * The aesmc instruction does the MixColumns. Since the aese instruction moves the AddRoundKey - * up front, and Cryptonight's hash skips the InitialRound step, we have to kludge it here by - * feeding in a vector of zeros for our first step. Also we have to do our own Xor explicitly - * at the last step, to provide the AddRoundKey that the ARM instructions omit. - */ -STATIC INLINE void aes_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey, int nblocks) -{ - const uint8x16_t *k = (const uint8x16_t *)expandedKey, zero = {0}; - uint8x16_t tmp; - int i; - - for (i=0; ikey->exp_data, aes_ctx->key->exp_data_len); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - for(j = 0; j < INIT_SIZE_BLK; j++) - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey); - memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); - } - - U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0]; - U64(a)[1] = U64(&state.k[0])[1] ^ U64(&state.k[32])[1]; - U64(b)[0] = U64(&state.k[16])[0] ^ U64(&state.k[48])[0]; - U64(b)[1] = U64(&state.k[16])[1] ^ U64(&state.k[48])[1]; - - for(i = 0; i < ITER / 2; i++) - { - #define MASK ((uint32_t)(((MEMORY / AES_BLOCK_SIZE) - 1) << 4)) - #define state_index(x) ((*(uint32_t *) x) & MASK) - - // Iteration 1 - p = &long_state[state_index(a)]; - aesb_single_round(p, p, a); - - xor_blocks(b, p); - swap_blocks(b, p); - swap_blocks(a, b); - - // Iteration 2 - p = &long_state[state_index(a)]; - - mul(a, p, d); - sum_half_blocks(b, d); - swap_blocks(b, p); - xor_blocks(b, p); - swap_blocks(a, b); - } - - memcpy(text, state.init, INIT_SIZE_BYTE); - oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); - memcpy(expandedKey, aes_ctx->key->exp_data, aes_ctx->key->exp_data_len); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - for(j = 0; j < INIT_SIZE_BLK; j++) - { - xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey); - } - } - - oaes_free((OAES_CTX **) &aes_ctx); - memcpy(state.init, text, INIT_SIZE_BYTE); - hash_permutation(&state.hs); - extra_hashes[state.hs.b[0] & 3](&state, 200, hash); -#ifdef FORCE_USE_HEAP - free(long_state); -#endif -} -#endif /* !aarch64 || !crypto */ - -#else -// Portable implementation as a fallback - -void slow_hash_allocate_state_lite(void) -{ - // Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c - return; -} - -void slow_hash_free_state_lite(void) -{ - // As above - return; -} - -static void (*const extra_hashes[4])(const void *, size_t, char *) = { - hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein -}; - -extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey); -extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); - -static size_t e2i(const uint8_t* a, size_t count) { return (*((uint64_t*)a) / AES_BLOCK_SIZE) & (count - 1); } - -static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) { - uint64_t a0, b0; - uint64_t hi, lo; - - a0 = SWAP64LE(((uint64_t*)a)[0]); - b0 = SWAP64LE(((uint64_t*)b)[0]); - lo = mul128(a0, b0, &hi); - ((uint64_t*)res)[0] = SWAP64LE(hi); - ((uint64_t*)res)[1] = SWAP64LE(lo); -} - -static void sum_half_blocks(uint8_t* a, const uint8_t* b) { - uint64_t a0, a1, b0, b1; - - a0 = SWAP64LE(((uint64_t*)a)[0]); - a1 = SWAP64LE(((uint64_t*)a)[1]); - b0 = SWAP64LE(((uint64_t*)b)[0]); - b1 = SWAP64LE(((uint64_t*)b)[1]); - a0 += b0; - a1 += b1; - ((uint64_t*)a)[0] = SWAP64LE(a0); - ((uint64_t*)a)[1] = SWAP64LE(a1); -} -#define U64(x) ((uint64_t *) (x)) - -static void copy_block(uint8_t* dst, const uint8_t* src) { - memcpy(dst, src, AES_BLOCK_SIZE); -} - -static void swap_blocks(uint8_t *a, uint8_t *b){ - uint64_t t[2]; - U64(t)[0] = U64(a)[0]; - U64(t)[1] = U64(a)[1]; - U64(a)[0] = U64(b)[0]; - U64(a)[1] = U64(b)[1]; - U64(b)[0] = U64(t)[0]; - U64(b)[1] = U64(t)[1]; -} - -static void xor_blocks(uint8_t* a, const uint8_t* b) { - size_t i; - for (i = 0; i < AES_BLOCK_SIZE; i++) { - a[i] ^= b[i]; - } -} - -#pragma pack(push, 1) -union cn_slow_hash_state { - union hash_state hs; - struct { - uint8_t k[64]; - uint8_t init[INIT_SIZE_BYTE]; - }; -}; -#pragma pack(pop) - -void cn_slow_hash_lite(const void *data, size_t length, char *hash) { - uint8_t long_state[MEMORY]; - union cn_slow_hash_state state; - uint8_t text[INIT_SIZE_BYTE]; - uint8_t a[AES_BLOCK_SIZE]; - uint8_t b[AES_BLOCK_SIZE]; - uint8_t c[AES_BLOCK_SIZE]; - uint8_t d[AES_BLOCK_SIZE]; - size_t i, j; - uint8_t aes_key[AES_KEY_SIZE]; - oaes_ctx *aes_ctx; - - hash_process(&state.hs, data, length); - memcpy(text, state.init, INIT_SIZE_BYTE); - memcpy(aes_key, state.hs.b, AES_KEY_SIZE); - aes_ctx = (oaes_ctx *) oaes_alloc(); - - oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE); - for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { - for (j = 0; j < INIT_SIZE_BLK; j++) { - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); - } - memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); - } - - for (i = 0; i < 16; i++) { - a[i] = state.k[ i] ^ state.k[32 + i]; - b[i] = state.k[16 + i] ^ state.k[48 + i]; - } - - for (i = 0; i < ITER / 2; i++) { - /* Dependency chain: address -> read value ------+ - * written value <-+ hard function (AES or MUL) <+ - * next address <-+ - */ - /* Iteration 1 */ - j = e2i(a, MEMORY / AES_BLOCK_SIZE); - copy_block(c, &long_state[j * AES_BLOCK_SIZE]); - aesb_single_round(c, c, a); - xor_blocks(b, c); - swap_blocks(b, c); - copy_block(&long_state[j * AES_BLOCK_SIZE], c); - assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); - swap_blocks(a, b); - /* Iteration 2 */ - j = e2i(a, MEMORY / AES_BLOCK_SIZE); - copy_block(c, &long_state[j * AES_BLOCK_SIZE]); - mul(a, c, d); - sum_half_blocks(b, d); - swap_blocks(b, c); - xor_blocks(b, c); - copy_block(&long_state[j * AES_BLOCK_SIZE], c); - assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); - swap_blocks(a, b); - } - - memcpy(text, state.init, INIT_SIZE_BYTE); - oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); - for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { - for (j = 0; j < INIT_SIZE_BLK; j++) { - xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); - } - } - memcpy(state.init, text, INIT_SIZE_BYTE); - hash_permutation(&state.hs); - /*memcpy(hash, &state, 32);*/ - extra_hashes[state.hs.b[0] & 3](&state, 200, hash); - oaes_free((OAES_CTX **) &aes_ctx); -} - -#endif diff --git a/src/Native/libcryptonote/crypto/slow-hash.c b/src/Native/libcryptonote/crypto/slow-hash.c deleted file mode 100644 index 4a8ebbf9d..000000000 --- a/src/Native/libcryptonote/crypto/slow-hash.c +++ /dev/null @@ -1,1378 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - -#include "common/int-util.h" -#include "hash-ops.h" -#include "oaes_lib.h" - -#define MEMORY (1 << 21) // 2MB scratchpad -#define ITER (1 << 20) -#define AES_BLOCK_SIZE 16 -#define AES_KEY_SIZE 32 -#define INIT_SIZE_BLK 8 -#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE) - -extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey); -extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); - -#define VARIANT1_1(p) \ - do if (variant > 0) \ - { \ - const uint8_t tmp = ((const uint8_t*)(p))[11]; \ - static const uint32_t table = 0x75310; \ - const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \ - ((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \ - } while(0) - -#define VARIANT1_2(p) \ - do if (variant > 0) \ - { \ - xor64(p, tweak1_2); \ - } while(0) - -#define VARIANT1_CHECK() \ - do if (length < 43) \ - { \ - fprintf(stderr, "Cryptonight variants need at least 43 bytes of data"); \ - _exit(1); \ - } while(0) - -#define NONCE_POINTER (((const uint8_t*)data)+35) - -#define VARIANT1_PORTABLE_INIT() \ - uint8_t tweak1_2[8]; \ - do if (variant > 0) \ - { \ - VARIANT1_CHECK(); \ - memcpy(&tweak1_2, &state.hs.b[192], sizeof(tweak1_2)); \ - xor64(tweak1_2, NONCE_POINTER); \ - } while(0) - -#define VARIANT1_INIT64() \ - if (variant > 0) \ - { \ - VARIANT1_CHECK(); \ - } \ - const uint64_t tweak1_2 = variant > 0 ? (state.hs.w[24] ^ (*((const uint64_t*)NONCE_POINTER))) : 0 - -#if !defined NO_AES && (defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64))) -// Optimised code below, uses x86-specific intrinsics, SSE2, AES-NI -// Fall back to more portable code is down at the bottom - -#include - -#if defined(_MSC_VER) -#include -#include -#define STATIC -#define INLINE __inline -#if !defined(RDATA_ALIGN16) -#define RDATA_ALIGN16 __declspec(align(16)) -#endif -#elif defined(__MINGW32__) -#include -#include -#define STATIC static -#define INLINE inline -#if !defined(RDATA_ALIGN16) -#define RDATA_ALIGN16 __attribute__ ((aligned(16))) -#endif -#else -#include -#include -#define STATIC static -#define INLINE inline -#if !defined(RDATA_ALIGN16) -#define RDATA_ALIGN16 __attribute__ ((aligned(16))) -#endif -#endif - -#if defined(__INTEL_COMPILER) -#define ASM __asm__ -#elif !defined(_MSC_VER) -#define ASM __asm__ -#else -#define ASM __asm -#endif - -#define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE) - -#define U64(x) ((uint64_t *) (x)) -#define R128(x) ((__m128i *) (x)) - -#define state_index(x) (((*((uint64_t *)x) >> 4) & (TOTALBLOCKS - 1)) << 4) -#if defined(_MSC_VER) -#if !defined(_WIN64) -#define __mul() lo = mul128(c[0], b[0], &hi); -#else -#define __mul() lo = _umul128(c[0], b[0], &hi); -#endif -#else -#if defined(__x86_64__) -#define __mul() ASM("mulq %3\n\t" : "=d"(hi), "=a"(lo) : "%a" (c[0]), "rm" (b[0]) : "cc"); -#else -#define __mul() lo = mul128(c[0], b[0], &hi); -#endif -#endif - -#define pre_aes() \ - j = state_index(a); \ - _c = _mm_load_si128(R128(&hp_state[j])); \ - _a = _mm_load_si128(R128(a)); \ - -/* - * An SSE-optimized implementation of the second half of CryptoNight step 3. - * After using AES to mix a scratchpad value into _c (done by the caller), - * this macro xors it with _b and stores the result back to the same index (j) that it - * loaded the scratchpad value from. It then performs a second random memory - * read/write from the scratchpad, but this time mixes the values using a 64 - * bit multiply. - * This code is based upon an optimized implementation by dga. - */ -#define post_aes() \ - _mm_store_si128(R128(c), _c); \ - _b = _mm_xor_si128(_b, _c); \ - _mm_store_si128(R128(&hp_state[j]), _b); \ - VARIANT1_1(&hp_state[j]); \ - j = state_index(c); \ - p = U64(&hp_state[j]); \ - b[0] = p[0]; b[1] = p[1]; \ - __mul(); \ - a[0] += hi; a[1] += lo; \ - p = U64(&hp_state[j]); \ - p[0] = a[0]; p[1] = a[1]; \ - a[0] ^= b[0]; a[1] ^= b[1]; \ - VARIANT1_2(p + 1); \ - _b = _c; \ - -#if defined(_MSC_VER) -#define THREADV __declspec(thread) -#else -#define THREADV __thread -#endif - -#pragma pack(push, 1) -union cn_slow_hash_state -{ - union hash_state hs; - struct - { - uint8_t k[64]; - uint8_t init[INIT_SIZE_BYTE]; - }; -}; -#pragma pack(pop) - -THREADV uint8_t *hp_state = NULL; -THREADV int hp_allocated = 0; - -#if defined(_MSC_VER) -#define cpuid(info,x) __cpuidex(info,x,0) -#else -void cpuid(int CPUInfo[4], int InfoType) -{ - ASM __volatile__ - ( - "cpuid": - "=a" (CPUInfo[0]), - "=b" (CPUInfo[1]), - "=c" (CPUInfo[2]), - "=d" (CPUInfo[3]) : - "a" (InfoType), "c" (0) - ); -} -#endif - -/** - * @brief a = (a xor b), where a and b point to 128 bit values - */ - -STATIC INLINE void xor_blocks(uint8_t *a, const uint8_t *b) -{ - U64(a)[0] ^= U64(b)[0]; - U64(a)[1] ^= U64(b)[1]; -} - -STATIC INLINE void xor64(uint64_t *a, const uint64_t b) -{ - *a ^= b; -} - -/** - * @brief uses cpuid to determine if the CPU supports the AES instructions - * @return true if the CPU supports AES, false otherwise - */ - -STATIC INLINE int force_software_aes(void) -{ - static int use = -1; - - if (use != -1) - return use; - - const char *env = getenv("MONERO_USE_SOFTWARE_AES"); - if (!env) { - use = 0; - } - else if (!strcmp(env, "0") || !strcmp(env, "no")) { - use = 0; - } - else { - use = 1; - } - return use; -} - -STATIC INLINE int check_aes_hw(void) -{ - int cpuid_results[4]; - static int supported = -1; - - if(supported >= 0) - return supported; - - cpuid(cpuid_results,1); - return supported = cpuid_results[2] & (1 << 25); -} - -STATIC INLINE void aes_256_assist1(__m128i* t1, __m128i * t2) -{ - __m128i t4; - *t2 = _mm_shuffle_epi32(*t2, 0xff); - t4 = _mm_slli_si128(*t1, 0x04); - *t1 = _mm_xor_si128(*t1, t4); - t4 = _mm_slli_si128(t4, 0x04); - *t1 = _mm_xor_si128(*t1, t4); - t4 = _mm_slli_si128(t4, 0x04); - *t1 = _mm_xor_si128(*t1, t4); - *t1 = _mm_xor_si128(*t1, *t2); -} - -STATIC INLINE void aes_256_assist2(__m128i* t1, __m128i * t3) -{ - __m128i t2, t4; - t4 = _mm_aeskeygenassist_si128(*t1, 0x00); - t2 = _mm_shuffle_epi32(t4, 0xaa); - t4 = _mm_slli_si128(*t3, 0x04); - *t3 = _mm_xor_si128(*t3, t4); - t4 = _mm_slli_si128(t4, 0x04); - *t3 = _mm_xor_si128(*t3, t4); - t4 = _mm_slli_si128(t4, 0x04); - *t3 = _mm_xor_si128(*t3, t4); - *t3 = _mm_xor_si128(*t3, t2); -} - -/** - * @brief expands 'key' into a form it can be used for AES encryption. - * - * This is an SSE-optimized implementation of AES key schedule generation. It - * expands the key into multiple round keys, each of which is used in one round - * of the AES encryption used to fill (and later, extract randomness from) - * the large 2MB buffer. Note that CryptoNight does not use a completely - * standard AES encryption for its buffer expansion, so do not copy this - * function outside of Monero without caution! This version uses the hardware - * AESKEYGENASSIST instruction to speed key generation, and thus requires - * CPU AES support. - * For more information about these functions, see page 19 of Intel's AES instructions - * white paper: - * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/aes-instructions-set-white-paper.pdf - * - * @param key the input 128 bit key - * @param expandedKey An output buffer to hold the generated key schedule - */ - -STATIC INLINE void aes_expand_key(const uint8_t *key, uint8_t *expandedKey) -{ - __m128i *ek = R128(expandedKey); - __m128i t1, t2, t3; - - t1 = _mm_loadu_si128(R128(key)); - t3 = _mm_loadu_si128(R128(key + 16)); - - ek[0] = t1; - ek[1] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x01); - aes_256_assist1(&t1, &t2); - ek[2] = t1; - aes_256_assist2(&t1, &t3); - ek[3] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x02); - aes_256_assist1(&t1, &t2); - ek[4] = t1; - aes_256_assist2(&t1, &t3); - ek[5] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x04); - aes_256_assist1(&t1, &t2); - ek[6] = t1; - aes_256_assist2(&t1, &t3); - ek[7] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x08); - aes_256_assist1(&t1, &t2); - ek[8] = t1; - aes_256_assist2(&t1, &t3); - ek[9] = t3; - - t2 = _mm_aeskeygenassist_si128(t3, 0x10); - aes_256_assist1(&t1, &t2); - ek[10] = t1; -} - -/** - * @brief a "pseudo" round of AES (similar to but slightly different from normal AES encryption) - * - * To fill its 2MB scratch buffer, CryptoNight uses a nonstandard implementation - * of AES encryption: It applies 10 rounds of the basic AES encryption operation - * to an input 128 bit chunk of data . Unlike normal AES, however, this is - * all it does; it does not perform the initial AddRoundKey step (this is done - * in subsequent steps by aesenc_si128), and it does not use the simpler final round. - * Hence, this is a "pseudo" round - though the function actually implements 10 rounds together. - * - * Note that unlike aesb_pseudo_round, this function works on multiple data chunks. - * - * @param in a pointer to nblocks * 128 bits of data to be encrypted - * @param out a pointer to an nblocks * 128 bit buffer where the output will be stored - * @param expandedKey the expanded AES key - * @param nblocks the number of 128 blocks of data to be encrypted - */ - -STATIC INLINE void aes_pseudo_round(const uint8_t *in, uint8_t *out, - const uint8_t *expandedKey, int nblocks) -{ - __m128i *k = R128(expandedKey); - __m128i d; - int i; - - for(i = 0; i < nblocks; i++) - { - d = _mm_loadu_si128(R128(in + i * AES_BLOCK_SIZE)); - d = _mm_aesenc_si128(d, *R128(&k[0])); - d = _mm_aesenc_si128(d, *R128(&k[1])); - d = _mm_aesenc_si128(d, *R128(&k[2])); - d = _mm_aesenc_si128(d, *R128(&k[3])); - d = _mm_aesenc_si128(d, *R128(&k[4])); - d = _mm_aesenc_si128(d, *R128(&k[5])); - d = _mm_aesenc_si128(d, *R128(&k[6])); - d = _mm_aesenc_si128(d, *R128(&k[7])); - d = _mm_aesenc_si128(d, *R128(&k[8])); - d = _mm_aesenc_si128(d, *R128(&k[9])); - _mm_storeu_si128((R128(out + i * AES_BLOCK_SIZE)), d); - } -} - -/** - * @brief aes_pseudo_round that loads data from *in and xors it with *xor first - * - * This function performs the same operations as aes_pseudo_round, but before - * performing the encryption of each 128 bit block from , it xors - * it with the corresponding block from . - * - * @param in a pointer to nblocks * 128 bits of data to be encrypted - * @param out a pointer to an nblocks * 128 bit buffer where the output will be stored - * @param expandedKey the expanded AES key - * @param xor a pointer to an nblocks * 128 bit buffer that is xored into in before encryption (in is left unmodified) - * @param nblocks the number of 128 blocks of data to be encrypted - */ - -STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, - const uint8_t *expandedKey, const uint8_t *xor, int nblocks) -{ - __m128i *k = R128(expandedKey); - __m128i *x = R128(xor); - __m128i d; - int i; - - for(i = 0; i < nblocks; i++) - { - d = _mm_loadu_si128(R128(in + i * AES_BLOCK_SIZE)); - d = _mm_xor_si128(d, *R128(x++)); - d = _mm_aesenc_si128(d, *R128(&k[0])); - d = _mm_aesenc_si128(d, *R128(&k[1])); - d = _mm_aesenc_si128(d, *R128(&k[2])); - d = _mm_aesenc_si128(d, *R128(&k[3])); - d = _mm_aesenc_si128(d, *R128(&k[4])); - d = _mm_aesenc_si128(d, *R128(&k[5])); - d = _mm_aesenc_si128(d, *R128(&k[6])); - d = _mm_aesenc_si128(d, *R128(&k[7])); - d = _mm_aesenc_si128(d, *R128(&k[8])); - d = _mm_aesenc_si128(d, *R128(&k[9])); - _mm_storeu_si128((R128(out + i * AES_BLOCK_SIZE)), d); - } -} - -#if defined(_MSC_VER) || defined(__MINGW32__) -BOOL SetLockPagesPrivilege(HANDLE hProcess, BOOL bEnable) -{ - struct - { - DWORD count; - LUID_AND_ATTRIBUTES privilege[1]; - } info; - - HANDLE token; - if(!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &token)) - return FALSE; - - info.count = 1; - info.privilege[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; - - if(!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(info.privilege[0].Luid))) - return FALSE; - - if(!AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &info, 0, NULL, NULL)) - return FALSE; - - if (GetLastError() != ERROR_SUCCESS) - return FALSE; - - CloseHandle(token); - - return TRUE; - -} -#endif - -/** - * @brief allocate the 2MB scratch buffer using OS support for huge pages, if available - * - * This function tries to allocate the 2MB scratch buffer using a single - * 2MB "huge page" (instead of the usual 4KB page sizes) to reduce TLB misses - * during the random accesses to the scratch buffer. This is one of the - * important speed optimizations needed to make CryptoNight faster. - * - * No parameters. Updates a thread-local pointer, hp_state, to point to - * the allocated buffer. - */ - -void slow_hash_allocate_state(void) -{ - if(hp_state != NULL) - return; - -#if defined(_MSC_VER) || defined(__MINGW32__) - SetLockPagesPrivilege(GetCurrentProcess(), TRUE); - hp_state = (uint8_t *) VirtualAlloc(hp_state, MEMORY, MEM_LARGE_PAGES | - MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); -#else -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__DragonFly__) - hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, 0, 0); -#else - hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, 0, 0); -#endif - if(hp_state == MAP_FAILED) - hp_state = NULL; -#endif - hp_allocated = 1; - if(hp_state == NULL) - { - hp_allocated = 0; - hp_state = (uint8_t *) malloc(MEMORY); - } -} - -/** - *@brief frees the state allocated by slow_hash_allocate_state - */ - -void slow_hash_free_state(void) -{ - if(hp_state == NULL) - return; - - if(!hp_allocated) - free(hp_state); - else - { -#if defined(_MSC_VER) || defined(__MINGW32__) - VirtualFree(hp_state, MEMORY, MEM_RELEASE); -#else - munmap(hp_state, MEMORY); -#endif - } - - hp_state = NULL; - hp_allocated = 0; -} - -/** - * @brief the hash function implementing CryptoNight, used for the Monero proof-of-work - * - * Computes the hash of (which consists of bytes), returning the - * hash in . The CryptoNight hash operates by first using Keccak 1600, - * the 1600 bit variant of the Keccak hash used in SHA-3, to create a 200 byte - * buffer of pseudorandom data by hashing the supplied data. It then uses this - * random data to fill a large 2MB buffer with pseudorandom data by iteratively - * encrypting it using 10 rounds of AES per entry. After this initialization, - * it executes 524,288 rounds of mixing through the random 2MB buffer using - * AES (typically provided in hardware on modern CPUs) and a 64 bit multiply. - * Finally, it re-mixes this large buffer back into - * the 200 byte "text" buffer, and then hashes this buffer using one of four - * pseudorandomly selected hash functions (Blake, Groestl, JH, or Skein) - * to populate the output. - * - * The 2MB buffer and choice of functions for mixing are designed to make the - * algorithm "CPU-friendly" (and thus, reduce the advantage of GPU, FPGA, - * or ASIC-based implementations): the functions used are fast on modern - * CPUs, and the 2MB size matches the typical amount of L3 cache available per - * core on 2013-era CPUs. When available, this implementation will use hardware - * AES support on x86 CPUs. - * - * A diagram of the inner loop of this function can be found at - * http://www.cs.cmu.edu/~dga/crypto/xmr/cryptonight.png - * - * @param data the data to hash - * @param length the length in bytes of the data - * @param hash a pointer to a buffer in which the final 256 bit hash will be stored - */ -void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) -{ - RDATA_ALIGN16 uint8_t expandedKey[240]; /* These buffers are aligned to use later with SSE functions */ - - uint8_t text[INIT_SIZE_BYTE]; - RDATA_ALIGN16 uint64_t a[2]; - RDATA_ALIGN16 uint64_t b[2]; - RDATA_ALIGN16 uint64_t c[2]; - union cn_slow_hash_state state; - __m128i _a, _b, _c; - uint64_t hi, lo; - - size_t i, j; - uint64_t *p = NULL; - oaes_ctx *aes_ctx = NULL; - int useAes = !force_software_aes() && check_aes_hw(); - - static void (*const extra_hashes[4])(const void *, size_t, char *) = - { - hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein - }; - - // this isn't supposed to happen, but guard against it for now. - if(hp_state == NULL) - slow_hash_allocate_state(); - - /* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */ - if (prehashed) { - memcpy(&state.hs, data, length); - } else { - hash_process(&state.hs, data, length); - } - memcpy(text, state.init, INIT_SIZE_BYTE); - - VARIANT1_INIT64(); - - /* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill - * the 2MB large random access buffer. - */ - - if(useAes) - { - aes_expand_key(state.hs.b, expandedKey); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - aes_pseudo_round(text, text, expandedKey, INIT_SIZE_BLK); - memcpy(&hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); - } - } - else - { - aes_ctx = (oaes_ctx *) oaes_alloc(); - oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - for(j = 0; j < INIT_SIZE_BLK; j++) - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); - - memcpy(&hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); - } - } - - U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0]; - U64(a)[1] = U64(&state.k[0])[1] ^ U64(&state.k[32])[1]; - U64(b)[0] = U64(&state.k[16])[0] ^ U64(&state.k[48])[0]; - U64(b)[1] = U64(&state.k[16])[1] ^ U64(&state.k[48])[1]; - - /* CryptoNight Step 3: Bounce randomly 1,048,576 times (1<<20) through the mixing buffer, - * using 524,288 iterations of the following mixing function. Each execution - * performs two reads and writes from the mixing buffer. - */ - - _b = _mm_load_si128(R128(b)); - // Two independent versions, one with AES, one without, to ensure that - // the useAes test is only performed once, not every iteration. - if(useAes) - { - for(i = 0; i < ITER / 2; i++) - { - pre_aes(); - _c = _mm_aesenc_si128(_c, _a); - post_aes(); - } - } - else - { - for(i = 0; i < ITER / 2; i++) - { - pre_aes(); - aesb_single_round((uint8_t *) &_c, (uint8_t *) &_c, (uint8_t *) &_a); - post_aes(); - } - } - - /* CryptoNight Step 4: Sequentially pass through the mixing buffer and use 10 rounds - * of AES encryption to mix the random data back into the 'text' buffer. 'text' - * was originally created with the output of Keccak1600. */ - - memcpy(text, state.init, INIT_SIZE_BYTE); - if(useAes) - { - aes_expand_key(&state.hs.b[32], expandedKey); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - // add the xor to the pseudo round - aes_pseudo_round_xor(text, text, expandedKey, &hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK); - } - } - else - { - oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - for(j = 0; j < INIT_SIZE_BLK; j++) - { - xor_blocks(&text[j * AES_BLOCK_SIZE], &hp_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); - } - } - oaes_free((OAES_CTX **) &aes_ctx); - } - - /* CryptoNight Step 5: Apply Keccak to the state again, and then - * use the resulting data to select which of four finalizer - * hash functions to apply to the data (Blake, Groestl, JH, or Skein). - * Use this hash to squeeze the state array down - * to the final 256 bit hash output. - */ - - memcpy(state.init, text, INIT_SIZE_BYTE); - hash_permutation(&state.hs); - extra_hashes[state.hs.b[0] & 3](&state, 200, hash); -} - -#elif !defined NO_AES && (defined(__arm__) || defined(__aarch64__)) -void slow_hash_allocate_state(void) -{ - // Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c - return; -} - -void slow_hash_free_state(void) -{ - // As above - return; -} - -#if defined(__GNUC__) -#define RDATA_ALIGN16 __attribute__ ((aligned(16))) -#define STATIC static -#define INLINE inline -#else -#define RDATA_ALIGN16 -#define STATIC static -#define INLINE -#endif - -#define U64(x) ((uint64_t *) (x)) - -STATIC INLINE void xor64(uint64_t *a, const uint64_t b) -{ - *a ^= b; -} - -#pragma pack(push, 1) -union cn_slow_hash_state -{ - union hash_state hs; - struct - { - uint8_t k[64]; - uint8_t init[INIT_SIZE_BYTE]; - }; -}; -#pragma pack(pop) - -#if defined(__aarch64__) && defined(__ARM_FEATURE_CRYPTO) - -/* ARMv8-A optimized with NEON and AES instructions. - * Copied from the x86-64 AES-NI implementation. It has much the same - * characteristics as x86-64: there's no 64x64=128 multiplier for vectors, - * and moving between vector and regular registers stalls the pipeline. - */ -#include - -#define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE) - -#define state_index(x) (((*((uint64_t *)x) >> 4) & (TOTALBLOCKS - 1)) << 4) -#define __mul() __asm__("mul %0, %1, %2\n\t" : "=r"(lo) : "r"(c[0]), "r"(b[0]) ); \ - __asm__("umulh %0, %1, %2\n\t" : "=r"(hi) : "r"(c[0]), "r"(b[0]) ); - -#define pre_aes() \ - j = state_index(a); \ - _c = vld1q_u8(&hp_state[j]); \ - _a = vld1q_u8((const uint8_t *)a); \ - -#define post_aes() \ - vst1q_u8((uint8_t *)c, _c); \ - _b = veorq_u8(_b, _c); \ - vst1q_u8(&hp_state[j], _b); \ - VARIANT1_1(&hp_state[j]); \ - j = state_index(c); \ - p = U64(&hp_state[j]); \ - b[0] = p[0]; b[1] = p[1]; \ - __mul(); \ - a[0] += hi; a[1] += lo; \ - p = U64(&hp_state[j]); \ - p[0] = a[0]; p[1] = a[1]; \ - a[0] ^= b[0]; a[1] ^= b[1]; \ - VARIANT1_2(p + 1); \ - _b = _c; \ - - -/* Note: this was based on a standard 256bit key schedule but - * it's been shortened since Cryptonight doesn't use the full - * key schedule. Don't try to use this for vanilla AES. -*/ -static void aes_expand_key(const uint8_t *key, uint8_t *expandedKey) { -static const int rcon[] = { - 0x01,0x01,0x01,0x01, - 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d, // rotate-n-splat - 0x1b,0x1b,0x1b,0x1b }; -__asm__( -" eor v0.16b,v0.16b,v0.16b\n" -" ld1 {v3.16b},[%0],#16\n" -" ld1 {v1.4s,v2.4s},[%2],#32\n" -" ld1 {v4.16b},[%0]\n" -" mov w2,#5\n" -" st1 {v3.4s},[%1],#16\n" -"\n" -"1:\n" -" tbl v6.16b,{v4.16b},v2.16b\n" -" ext v5.16b,v0.16b,v3.16b,#12\n" -" st1 {v4.4s},[%1],#16\n" -" aese v6.16b,v0.16b\n" -" subs w2,w2,#1\n" -"\n" -" eor v3.16b,v3.16b,v5.16b\n" -" ext v5.16b,v0.16b,v5.16b,#12\n" -" eor v3.16b,v3.16b,v5.16b\n" -" ext v5.16b,v0.16b,v5.16b,#12\n" -" eor v6.16b,v6.16b,v1.16b\n" -" eor v3.16b,v3.16b,v5.16b\n" -" shl v1.16b,v1.16b,#1\n" -" eor v3.16b,v3.16b,v6.16b\n" -" st1 {v3.4s},[%1],#16\n" -" b.eq 2f\n" -"\n" -" dup v6.4s,v3.s[3] // just splat\n" -" ext v5.16b,v0.16b,v4.16b,#12\n" -" aese v6.16b,v0.16b\n" -"\n" -" eor v4.16b,v4.16b,v5.16b\n" -" ext v5.16b,v0.16b,v5.16b,#12\n" -" eor v4.16b,v4.16b,v5.16b\n" -" ext v5.16b,v0.16b,v5.16b,#12\n" -" eor v4.16b,v4.16b,v5.16b\n" -"\n" -" eor v4.16b,v4.16b,v6.16b\n" -" b 1b\n" -"\n" -"2:\n" : : "r"(key), "r"(expandedKey), "r"(rcon)); -} - -/* An ordinary AES round is a sequence of SubBytes, ShiftRows, MixColumns, AddRoundKey. There - * is also an InitialRound which consists solely of AddRoundKey. The ARM instructions slice - * this sequence differently; the aese instruction performs AddRoundKey, SubBytes, ShiftRows. - * The aesmc instruction does the MixColumns. Since the aese instruction moves the AddRoundKey - * up front, and Cryptonight's hash skips the InitialRound step, we have to kludge it here by - * feeding in a vector of zeros for our first step. Also we have to do our own Xor explicitly - * at the last step, to provide the AddRoundKey that the ARM instructions omit. - */ -STATIC INLINE void aes_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey, int nblocks) -{ - const uint8x16_t *k = (const uint8x16_t *)expandedKey, zero = {0}; - uint8x16_t tmp; - int i; - - for (i=0; ikey->exp_data, aes_ctx->key->exp_data_len); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - for(j = 0; j < INIT_SIZE_BLK; j++) - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey); - memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); - } - - U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0]; - U64(a)[1] = U64(&state.k[0])[1] ^ U64(&state.k[32])[1]; - U64(b)[0] = U64(&state.k[16])[0] ^ U64(&state.k[48])[0]; - U64(b)[1] = U64(&state.k[16])[1] ^ U64(&state.k[48])[1]; - - for(i = 0; i < ITER / 2; i++) - { - #define MASK ((uint32_t)(((MEMORY / AES_BLOCK_SIZE) - 1) << 4)) - #define state_index(x) ((*(uint32_t *) x) & MASK) - - // Iteration 1 - p = &long_state[state_index(a)]; - aesb_single_round(p, p, a); - - xor_blocks(b, p); - swap_blocks(b, p); - swap_blocks(a, b); - VARIANT1_1(p); - - // Iteration 2 - p = &long_state[state_index(a)]; - - mul(a, p, d); - sum_half_blocks(b, d); - swap_blocks(b, p); - xor_blocks(b, p); - swap_blocks(a, b); - VARIANT1_2(U64(p) + 1); - } - - memcpy(text, state.init, INIT_SIZE_BYTE); - oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); - memcpy(expandedKey, aes_ctx->key->exp_data, aes_ctx->key->exp_data_len); - for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) - { - for(j = 0; j < INIT_SIZE_BLK; j++) - { - xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey); - } - } - - oaes_free((OAES_CTX **) &aes_ctx); - memcpy(state.init, text, INIT_SIZE_BYTE); - hash_permutation(&state.hs); - extra_hashes[state.hs.b[0] & 3](&state, 200, hash); -#ifdef FORCE_USE_HEAP - free(long_state); -#endif -} -#endif /* !aarch64 || !crypto */ - -#else -// Portable implementation as a fallback - -void slow_hash_allocate_state(void) -{ - // Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c - return; -} - -void slow_hash_free_state(void) -{ - // As above - return; -} - -static void (*const extra_hashes[4])(const void *, size_t, char *) = { - hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein -}; - -extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey); -extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); - -static size_t e2i(const uint8_t* a, size_t count) { return (*((uint64_t*)a) / AES_BLOCK_SIZE) & (count - 1); } - -static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) { - uint64_t a0, b0; - uint64_t hi, lo; - - a0 = SWAP64LE(((uint64_t*)a)[0]); - b0 = SWAP64LE(((uint64_t*)b)[0]); - lo = mul128(a0, b0, &hi); - ((uint64_t*)res)[0] = SWAP64LE(hi); - ((uint64_t*)res)[1] = SWAP64LE(lo); -} - -static void sum_half_blocks(uint8_t* a, const uint8_t* b) { - uint64_t a0, a1, b0, b1; - - a0 = SWAP64LE(((uint64_t*)a)[0]); - a1 = SWAP64LE(((uint64_t*)a)[1]); - b0 = SWAP64LE(((uint64_t*)b)[0]); - b1 = SWAP64LE(((uint64_t*)b)[1]); - a0 += b0; - a1 += b1; - ((uint64_t*)a)[0] = SWAP64LE(a0); - ((uint64_t*)a)[1] = SWAP64LE(a1); -} -#define U64(x) ((uint64_t *) (x)) - -static void copy_block(uint8_t* dst, const uint8_t* src) { - memcpy(dst, src, AES_BLOCK_SIZE); -} - -static void swap_blocks(uint8_t *a, uint8_t *b){ - uint64_t t[2]; - U64(t)[0] = U64(a)[0]; - U64(t)[1] = U64(a)[1]; - U64(a)[0] = U64(b)[0]; - U64(a)[1] = U64(b)[1]; - U64(b)[0] = U64(t)[0]; - U64(b)[1] = U64(t)[1]; -} - -static void xor_blocks(uint8_t* a, const uint8_t* b) { - size_t i; - for (i = 0; i < AES_BLOCK_SIZE; i++) { - a[i] ^= b[i]; - } -} - -static void xor64(uint8_t* left, const uint8_t* right) -{ - size_t i; - for (i = 0; i < 8; ++i) - { - left[i] ^= right[i]; - } -} - -#pragma pack(push, 1) -union cn_slow_hash_state { - union hash_state hs; - struct { - uint8_t k[64]; - uint8_t init[INIT_SIZE_BYTE]; - }; -}; -#pragma pack(pop) - -void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) { - uint8_t long_state[MEMORY]; - union cn_slow_hash_state state; - uint8_t text[INIT_SIZE_BYTE]; - uint8_t a[AES_BLOCK_SIZE]; - uint8_t b[AES_BLOCK_SIZE]; - uint8_t c[AES_BLOCK_SIZE]; - uint8_t d[AES_BLOCK_SIZE]; - size_t i, j; - uint8_t aes_key[AES_KEY_SIZE]; - oaes_ctx *aes_ctx; - - if (prehashed) { - memcpy(&state.hs, data, length); - } else { - hash_process(&state.hs, data, length); - } - memcpy(text, state.init, INIT_SIZE_BYTE); - memcpy(aes_key, state.hs.b, AES_KEY_SIZE); - aes_ctx = (oaes_ctx *) oaes_alloc(); - - VARIANT1_PORTABLE_INIT(); - - oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE); - for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { - for (j = 0; j < INIT_SIZE_BLK; j++) { - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); - } - memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); - } - - for (i = 0; i < 16; i++) { - a[i] = state.k[ i] ^ state.k[32 + i]; - b[i] = state.k[16 + i] ^ state.k[48 + i]; - } - - for (i = 0; i < ITER / 2; i++) { - /* Dependency chain: address -> read value ------+ - * written value <-+ hard function (AES or MUL) <+ - * next address <-+ - */ - /* Iteration 1 */ - j = e2i(a, MEMORY / AES_BLOCK_SIZE); - copy_block(c, &long_state[j * AES_BLOCK_SIZE]); - aesb_single_round(c, c, a); - xor_blocks(b, c); - swap_blocks(b, c); - copy_block(&long_state[j * AES_BLOCK_SIZE], c); - assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); - swap_blocks(a, b); - VARIANT1_1(&long_state[j * AES_BLOCK_SIZE]); - /* Iteration 2 */ - j = e2i(a, MEMORY / AES_BLOCK_SIZE); - copy_block(c, &long_state[j * AES_BLOCK_SIZE]); - mul(a, c, d); - sum_half_blocks(b, d); - swap_blocks(b, c); - xor_blocks(b, c); - VARIANT1_2(c + 8); - copy_block(&long_state[j * AES_BLOCK_SIZE], c); - assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); - swap_blocks(a, b); - } - - memcpy(text, state.init, INIT_SIZE_BYTE); - oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); - for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { - for (j = 0; j < INIT_SIZE_BLK; j++) { - xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); - aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); - } - } - memcpy(state.init, text, INIT_SIZE_BYTE); - hash_permutation(&state.hs); - /*memcpy(hash, &state, 32);*/ - extra_hashes[state.hs.b[0] & 3](&state, 200, hash); - oaes_free((OAES_CTX **) &aes_ctx); -} - -#endif diff --git a/src/Native/libcryptonote/crypto/tree-hash.c b/src/Native/libcryptonote/crypto/tree-hash.c index e6d6a267c..b38443942 100644 --- a/src/Native/libcryptonote/crypto/tree-hash.c +++ b/src/Native/libcryptonote/crypto/tree-hash.c @@ -1,32 +1,12 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if !defined(WIN32) +#include +#else +#include +#endif #include #include @@ -34,52 +14,7 @@ #include "hash-ops.h" -#ifdef _MSC_VER -#include -#elif !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) - #include -#else - #include -#endif - -/*** -* Round to power of two, for count>=3 and for count being not too large (as reasonable for tree hash calculations) -*/ -size_t tree_hash_cnt(size_t count) { - // This algo has some bad history but all we are doing is 1 << floor(log2(count)) - // There are _many_ ways to do log2, for some reason the one selected was the most obscure one, - // and fixing it made it even more obscure. - // - // Iterative method implemented below aims for clarity over speed, if performance is needed - // then my advice is to use the BSR instruction on x86 - // - // All the paranoid asserts have been removed since it is trivial to mathematically prove that - // the return will always be a power of 2. - // Problem space has been defined as 3 <= count <= 2^28. Of course quarter of a billion transactions - // is not a sane upper limit for a block, so there will be tighter limits in other parts of the code - - assert( count >= 3 ); // cases for 0,1,2 are handled elsewhere - assert( count <= 0x10000000 ); // sanity limit to 2^28, MSB=1 will cause an inf loop - - size_t pow = 2; - while(pow < count) pow <<= 1; - return pow >> 1; -} - void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash) { -// The blockchain block at height 202612 http://monerochain.info/block/bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698 -// contained 514 transactions, that triggered bad calculation of variable "cnt" in the original version of this function -// as from CryptoNote code. -// -// This bug applies to all CN altcoins. -// -// Mathematical bug here was first published on 14:45:34 (GMT+2) 2014-09-04 by Rafal Freeman -// https://github.com/rfree2monero/bitmonero/commit/b417abfb7a297d09f1bbb6de29030f8de9952ac8 -// and soon also applied to CryptoNote (15:10 GMT+2), and BoolBerry used not fully correct work around: -// the work around of sizeof(size_t)*8 or <<3 as used before in 2 coins and in BBL later was blocking -// exploitation on normal platforms, how ever we strongly recommend the following fix because it removes -// mistake in mathematical formula. - assert(count > 0); if (count == 1) { memcpy(root_hash, hashes, HASH_SIZE); @@ -87,27 +22,116 @@ void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash) { cn_fast_hash(hashes, 2 * HASH_SIZE, root_hash); } else { size_t i, j; - - size_t cnt = tree_hash_cnt( count ); - + size_t cnt = count - 1; char (*ints)[HASH_SIZE]; - size_t ints_size = cnt * HASH_SIZE; - ints = alloca(ints_size); memset( ints , 0 , ints_size); // allocate, and zero out as extra protection for using uninitialized mem - + for (i = 1; i < sizeof(size_t) << 3; i <<= 1) { + cnt |= cnt >> i; + } + cnt &= ~(cnt >> 1); + ints = alloca(cnt * HASH_SIZE); memcpy(ints, hashes, (2 * cnt - count) * HASH_SIZE); - for (i = 2 * cnt - count, j = 2 * cnt - count; j < cnt; i += 2, ++j) { - cn_fast_hash(hashes[i], 64, ints[j]); + cn_fast_hash(hashes[i], 2 * HASH_SIZE, ints[j]); } assert(i == count); - while (cnt > 2) { cnt >>= 1; for (i = 0, j = 0; j < cnt; i += 2, ++j) { cn_fast_hash(ints[i], 64, ints[j]); } } + cn_fast_hash(ints[0], 2 * HASH_SIZE, root_hash); + } +} - cn_fast_hash(ints[0], 64, root_hash); +size_t tree_depth(size_t count) +{ + size_t i; + size_t depth = 0; + assert(count > 0); + for (i = sizeof(size_t) << 2; i > 0; i >>= 1) + { + if (count >> i > 0) + { + count >>= i; + depth += i; + } } + return depth; } + +void tree_branch(const char (*hashes)[HASH_SIZE], size_t count, char (*branch)[HASH_SIZE]) +{ + size_t i, j; + size_t cnt = 1; + size_t depth = 0; + char (*ints)[HASH_SIZE]; + assert(count > 0); + for (i = sizeof(size_t) << 2; i > 0; i >>= 1) + { + if (cnt << i <= count) + { + cnt <<= i; + depth += i; + } + } + assert(cnt == 1ULL << depth); + assert(depth == tree_depth(count)); + ints = alloca((cnt - 1) * HASH_SIZE); + memcpy(ints, hashes + 1, (2 * cnt - count - 1) * HASH_SIZE); + for (i = 2 * cnt - count, j = 2 * cnt - count - 1; j < cnt - 1; i += 2, ++j) + { + cn_fast_hash(hashes[i], 2 * HASH_SIZE, ints[j]); + } + assert(i == count); + while (depth > 0) + { + assert(cnt == 1ULL << depth); + cnt >>= 1; + --depth; + memcpy(branch[depth], ints[0], HASH_SIZE); + for (i = 1, j = 0; j < cnt - 1; i += 2, ++j) + { + cn_fast_hash(ints[i], 2 * HASH_SIZE, ints[j]); + } + } +} + +void tree_hash_from_branch(const char (*branch)[HASH_SIZE], size_t depth, const char* leaf, const void* path, char* root_hash) +{ + if (depth == 0) + { + memcpy(root_hash, leaf, HASH_SIZE); + } + else + { + char buffer[2][HASH_SIZE]; + int from_leaf = 1; + char *leaf_path, *branch_path; + while (depth > 0) + { + --depth; + if (path && (((const char*) path)[depth >> 3] & (1 << (depth & 7))) != 0) + { + leaf_path = buffer[1]; + branch_path = buffer[0]; + } + else + { + leaf_path = buffer[0]; + branch_path = buffer[1]; + } + if (from_leaf) + { + memcpy(leaf_path, leaf, HASH_SIZE); + from_leaf = 0; + } + else + { + cn_fast_hash(buffer, 2 * HASH_SIZE, leaf_path); + } + memcpy(branch_path, branch[depth], HASH_SIZE); + } + cn_fast_hash(buffer, 2 * HASH_SIZE, root_hash); + } +} \ No newline at end of file diff --git a/src/Native/libcryptonote/cryptonote_basic/CMakeLists.txt b/src/Native/libcryptonote/cryptonote_basic/CMakeLists.txt deleted file mode 100644 index d50a9df67..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/CMakeLists.txt +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (c) 2014-2018, The Monero Project -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, are -# permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, this list of -# conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright notice, this list -# of conditions and the following disclaimer in the documentation and/or other -# materials provided with the distribution. -# -# 3. Neither the name of the copyright holder nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -if(APPLE) - find_library(IOKIT_LIBRARY IOKit) - mark_as_advanced(IOKIT_LIBRARY) - list(APPEND EXTRA_LIBRARIES ${IOKIT_LIBRARY}) -endif() - -set(cryptonote_basic_sources - account.cpp - cryptonote_basic_impl.cpp - cryptonote_format_utils.cpp - difficulty.cpp - hardfork.cpp - miner.cpp) - -set(cryptonote_basic_headers) - -set(cryptonote_basic_private_headers - account.h - account_boost_serialization.h - connection_context.h - cryptonote_basic.h - cryptonote_basic_impl.h - cryptonote_boost_serialization.h - cryptonote_format_utils.h - cryptonote_stat_info.h - difficulty.h - hardfork.h - miner.h - tx_extra.h - verification_context.h) - -monero_private_headers(cryptonote_basic - ${cryptonote_basic_private_headers}) -monero_add_library(cryptonote_basic - ${cryptonote_basic_sources} - ${cryptonote_basic_headers} - ${cryptonote_basic_private_headers}) -target_link_libraries(cryptonote_basic - PUBLIC - common - cncrypto - checkpoints - device - ${Boost_DATE_TIME_LIBRARY} - ${Boost_PROGRAM_OPTIONS_LIBRARY} - ${Boost_SERIALIZATION_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY} - ${Boost_SYSTEM_LIBRARY} - ${Boost_THREAD_LIBRARY} - PRIVATE - ${EXTRA_LIBRARIES}) diff --git a/src/Native/libcryptonote/cryptonote_basic/account.cpp b/src/Native/libcryptonote/cryptonote_basic/account.cpp deleted file mode 100644 index bab991d19..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/account.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include - -#include "include_base_utils.h" -#include "account.h" -#include "warnings.h" -#include "crypto/crypto.h" -extern "C" -{ -#include "crypto/keccak.h" -} -#include "cryptonote_basic_impl.h" -#include "cryptonote_format_utils.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "account" - -using namespace std; - -DISABLE_VS_WARNINGS(4244 4345) - - namespace cryptonote -{ - - //----------------------------------------------------------------- - hw::device& account_keys::get_device() const { - return *m_device; - } - //----------------------------------------------------------------- - void account_keys::set_device( hw::device &hwdev) { - m_device = &hwdev; - MCDEBUG("device", "account_keys::set_device device type: "< &multisig_keys) - { - m_keys.m_account_address.m_spend_public_key = spend_public_key; - m_keys.m_view_secret_key = view_secret_key; - m_keys.m_spend_secret_key = spend_secret_key; - m_keys.m_multisig_keys = multisig_keys; - return crypto::secret_key_to_public_key(view_secret_key, m_keys.m_account_address.m_view_public_key); - } - //----------------------------------------------------------------- - void account_base::finalize_multisig(const crypto::public_key &spend_public_key) - { - m_keys.m_account_address.m_spend_public_key = spend_public_key; - } - //----------------------------------------------------------------- - const account_keys& account_base::get_keys() const - { - return m_keys; - } - //----------------------------------------------------------------- - std::string account_base::get_public_address_str(network_type nettype) const - { - //TODO: change this code into base 58 - return get_account_address_as_str(nettype, false, m_keys.m_account_address); - } - //----------------------------------------------------------------- - std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const - { - //TODO: change this code into base 58 - return get_account_integrated_address_as_str(nettype, m_keys.m_account_address, payment_id); - } - //----------------------------------------------------------------- -} diff --git a/src/Native/libcryptonote/cryptonote_basic/account.h b/src/Native/libcryptonote/cryptonote_basic/account.h deleted file mode 100644 index df4344730..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/account.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include "cryptonote_basic.h" -#include "crypto/crypto.h" -#include "serialization/keyvalue_serialization.h" - -namespace cryptonote -{ - - struct account_keys - { - account_public_address m_account_address; - crypto::secret_key m_spend_secret_key; - crypto::secret_key m_view_secret_key; - std::vector m_multisig_keys; - hw::device *m_device = &hw::get_device("default"); - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_account_address) - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_secret_key) - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_secret_key) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_multisig_keys) - END_KV_SERIALIZE_MAP() - - account_keys& operator=(account_keys const&) = default; - - hw::device& get_device() const ; - void set_device( hw::device &hwdev) ; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class account_base - { - public: - account_base(); - crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false); - void create_from_device(const std::string &device_name) ; - void create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey); - void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey); - bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector &multisig_keys); - void finalize_multisig(const crypto::public_key &spend_public_key); - const account_keys& get_keys() const; - std::string get_public_address_str(uint8_t nettype) const; - std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, uint8_t nettype) const; - - hw::device& get_device() const {return m_keys.get_device();} - void set_device( hw::device &hwdev) {m_keys.set_device(hwdev);} - - uint64_t get_createtime() const { return m_creation_timestamp; } - void set_createtime(uint64_t val) { m_creation_timestamp = val; } - - bool load(const std::string& file_path); - bool store(const std::string& file_path); - - void forget_spend_key(); - const std::vector &get_multisig_keys() const { return m_keys.m_multisig_keys; } - - template - inline void serialize(t_archive &a, const unsigned int /*ver*/) - { - a & m_keys; - a & m_creation_timestamp; - } - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_keys) - KV_SERIALIZE(m_creation_timestamp) - END_KV_SERIALIZE_MAP() - - private: - void set_null(); - account_keys m_keys; - uint64_t m_creation_timestamp; - }; -} diff --git a/src/Native/libcryptonote/cryptonote_basic/checkpoints.cpp b/src/Native/libcryptonote/cryptonote_basic/checkpoints.cpp deleted file mode 100644 index 98e509561..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/checkpoints.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (c) 2014-2017, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include "include_base_utils.h" - -using namespace epee; - -#include "checkpoints.h" - -#include "common/dns_utils.h" -#include "include_base_utils.h" -#include -#include - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "checkpoints" - -namespace cryptonote -{ - //--------------------------------------------------------------------------- - checkpoints::checkpoints() - { - } - //--------------------------------------------------------------------------- - bool checkpoints::add_checkpoint(uint64_t height, const std::string& hash_str) - { - crypto::hash h = null_hash; - bool r = epee::string_tools::parse_tpod_from_hex_string(hash_str, h); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!"); - - // return false if adding at a height we already have AND the hash is different - if (m_points.count(height)) - { - CHECK_AND_ASSERT_MES(h == m_points[height], false, "Checkpoint at given height already exists, and hash for new checkpoint was different!"); - } - m_points[height] = h; - return true; - } - //--------------------------------------------------------------------------- - bool checkpoints::is_in_checkpoint_zone(uint64_t height) const - { - return !m_points.empty() && (height <= (--m_points.end())->first); - } - //--------------------------------------------------------------------------- - bool checkpoints::check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const - { - auto it = m_points.find(height); - is_a_checkpoint = it != m_points.end(); - if(!is_a_checkpoint) - return true; - - if(it->second == h) - { - MINFO("CHECKPOINT PASSED FOR HEIGHT " << height << " " << h); - return true; - }else - { - MWARNING("CHECKPOINT FAILED FOR HEIGHT " << height << ". EXPECTED HASH: " << it->second << ", FETCHED HASH: " << h); - return false; - } - } - //--------------------------------------------------------------------------- - bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const - { - bool ignored; - return check_block(height, h, ignored); - } - //--------------------------------------------------------------------------- - //FIXME: is this the desired behavior? - bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const - { - if (0 == block_height) - return false; - - auto it = m_points.upper_bound(blockchain_height); - // Is blockchain_height before the first checkpoint? - if (it == m_points.begin()) - return true; - - --it; - uint64_t checkpoint_height = it->first; - return checkpoint_height < block_height; - } - //--------------------------------------------------------------------------- - uint64_t checkpoints::get_max_height() const - { - std::map< uint64_t, crypto::hash >::const_iterator highest = - std::max_element( m_points.begin(), m_points.end(), - ( boost::bind(&std::map< uint64_t, crypto::hash >::value_type::first, _1) < - boost::bind(&std::map< uint64_t, crypto::hash >::value_type::first, _2 ) ) ); - return highest->first; - } - //--------------------------------------------------------------------------- - const std::map& checkpoints::get_points() const - { - return m_points; - } - - bool checkpoints::check_for_conflicts(const checkpoints& other) const - { - for (auto& pt : other.get_points()) - { - if (m_points.count(pt.first)) - { - CHECK_AND_ASSERT_MES(pt.second == m_points.at(pt.first), false, "Checkpoint at given height already exists, and hash for new checkpoint was different!"); - } - } - return true; - } - - bool checkpoints::init_default_checkpoints() - { - ADD_CHECKPOINT(1, "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148"); - ADD_CHECKPOINT(10, "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381"); - ADD_CHECKPOINT(100, "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d"); - ADD_CHECKPOINT(1000, "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876"); - ADD_CHECKPOINT(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2"); - ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25"); - ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6"); - ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c"); - ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3"); - ADD_CHECKPOINT(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698"); - ADD_CHECKPOINT(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2"); - ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb"); - ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063"); - ADD_CHECKPOINT(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553"); - ADD_CHECKPOINT(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61"); - ADD_CHECKPOINT(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf"); - ADD_CHECKPOINT(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131"); - ADD_CHECKPOINT(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8"); - ADD_CHECKPOINT(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d"); - ADD_CHECKPOINT(460000, "75037a7aed3e765db96c75bcf908f59d690a5f3390baebb9edeafd336a1c4831"); - ADD_CHECKPOINT(500000, "2428f0dbe49796be05ed81b347f53e1f7f44aed0abf641446ec2b94cae066b02"); - ADD_CHECKPOINT(600000, "f5828ebf7d7d1cb61762c4dfe3ccf4ecab2e1aad23e8113668d981713b7a54c5"); - ADD_CHECKPOINT(700000, "12be9b3d210b93f574d2526abb9c1ab2a881b479131fd0d4f7dac93875f503cd"); - ADD_CHECKPOINT(825000, "56503f9ad766774b575be3aff73245e9d159be88132c93d1754764f28da2ff60"); - ADD_CHECKPOINT(900000, "d9958d0e7dcf91a5a7b11de225927bf7efc6eb26240315ce12372be902cc1337"); - ADD_CHECKPOINT(913193, "5292d5d56f6ba4de33a58d9a34d263e2cb3c6fee0aed2286fd4ac7f36d53c85f"); - ADD_CHECKPOINT(1000000, "a886ef5149902d8342475fee9bb296341b891ac67c4842f47a833f23c00ed721"); - ADD_CHECKPOINT(1100000, "3fd720c5c8b3072fc1ccda922dec1ef25f9ed88a1e6ad4103d0fe00b180a5903"); - ADD_CHECKPOINT(1150000, "1dd16f626d18e1e988490dfd06de5920e22629c972c58b4d8daddea0038627b2"); - ADD_CHECKPOINT(1200000, "fa7d13a90850882060479d100141ff84286599ae39c3277c8ea784393f882d1f"); - ADD_CHECKPOINT(1300000, "31b34272343a44a9f4ac7de7a8fcf3b7d8a3124d7d6870affd510d2f37e74cd0"); - ADD_CHECKPOINT(1390000, "a8f5649dd4ded60eedab475f2bec8c934681c07e3cf640e9be0617554f13ff6c"); - - - return true; - } - - bool checkpoints::load_checkpoints_from_json(const std::string json_hashfile_fullpath) - { - boost::system::error_code errcode; - if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode))) - { - LOG_PRINT_L1("Blockchain checkpoints file not found"); - return true; - } - - LOG_PRINT_L1("Adding checkpoints from blockchain hashfile"); - - uint64_t prev_max_height = get_max_height(); - LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height); - t_hash_json hashes; - epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath); - for (std::vector::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); ) - { - uint64_t height; - height = it->height; - if (height <= prev_max_height) { - LOG_PRINT_L1("ignoring checkpoint height " << height); - } else { - std::string blockhash = it->hash; - LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash); - ADD_CHECKPOINT(height, blockhash); - } - ++it; - } - - return true; - } - - bool checkpoints::load_checkpoints_from_dns(bool testnet) - { - std::vector records; - - // All four MoneroPulse domains have DNSSEC on and valid - static const std::vector dns_urls = { "checkpoints.moneropulse.se" - , "checkpoints.moneropulse.org" - , "checkpoints.moneropulse.net" - , "checkpoints.moneropulse.co" - }; - - static const std::vector testnet_dns_urls = { "testpoints.moneropulse.se" - , "testpoints.moneropulse.org" - , "testpoints.moneropulse.net" - , "testpoints.moneropulse.co" - }; - - if (!tools::dns_utils::load_txt_records_from_dns(records, testnet ? testnet_dns_urls : dns_urls)) - return true; // why true ? - - for (const auto& record : records) - { - auto pos = record.find(":"); - if (pos != std::string::npos) - { - uint64_t height; - crypto::hash hash; - - // parse the first part as uint64_t, - // if this fails move on to the next record - std::stringstream ss(record.substr(0, pos)); - if (!(ss >> height)) - { - continue; - } - - // parse the second part as crypto::hash, - // if this fails move on to the next record - std::string hashStr = record.substr(pos + 1); - if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash)) - { - continue; - } - - ADD_CHECKPOINT(height, hashStr); - } - } - return true; - } - - bool checkpoints::load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet, bool dns) - { - bool result; - - result = load_checkpoints_from_json(json_hashfile_fullpath); - if (dns) - { - result &= load_checkpoints_from_dns(testnet); - } - - return result; - } -} diff --git a/src/Native/libcryptonote/cryptonote_basic/checkpoints.h b/src/Native/libcryptonote/cryptonote_basic/checkpoints.h deleted file mode 100644 index 3a74d8a69..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/checkpoints.h +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) 2014-2017, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include -#include -#include "cryptonote_basic_impl.h" -#include "misc_log_ex.h" -#include "storages/portable_storage_template_helper.h" // epee json include - -#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(add_checkpoint(h, hash), false); -#define JSON_HASH_FILE_NAME "checkpoints.json" - - -namespace cryptonote -{ - /** - * @brief A container for blockchain checkpoints - * - * A checkpoint is a pre-defined hash for the block at a given height. - * Some of these are compiled-in, while others can be loaded at runtime - * either from a json file or via DNS from a checkpoint-hosting server. - */ - class checkpoints - { - public: - - /** - * @brief default constructor - */ - checkpoints(); - - /** - * @brief adds a checkpoint to the container - * - * @param height the height of the block the checkpoint is for - * @param hash_str the hash of the block, as a string - * - * @return false if parsing the hash fails, or if the height is a duplicate - * AND the existing checkpoint hash does not match the new one, - * otherwise returns true - */ - bool add_checkpoint(uint64_t height, const std::string& hash_str); - - /** - * @brief checks if there is a checkpoint in the future - * - * This function checks if the height passed is lower than the highest - * checkpoint. - * - * @param height the height to check against - * - * @return false if no checkpoints, otherwise returns whether or not - * the height passed is lower than the highest checkpoint. - */ - bool is_in_checkpoint_zone(uint64_t height) const; - - /** - * @brief checks if the given height and hash agree with the checkpoints - * - * This function checks if the given height and hash exist in the - * checkpoints container. If so, it returns whether or not the passed - * parameters match the stored values. - * - * @param height the height to be checked - * @param h the hash to be checked - * @param is_a_checkpoint return-by-reference if there is a checkpoint at the given height - * - * @return true if there is no checkpoint at the given height, - * true if the passed parameters match the stored checkpoint, - * false otherwise - */ - bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const; - - /** - * @overload - */ - bool check_block(uint64_t height, const crypto::hash& h) const; - - /** - * @brief checks if alternate chain blocks should be kept for a given height - * - * this basically says if the blockchain is smaller than the first - * checkpoint then alternate blocks are allowed. Alternatively, if the - * last checkpoint *before* the end of the current chain is also before - * the block to be added, then this is fine. - * - * @param blockchain_height the current blockchain height - * @param block_height the height of the block to be added as alternate - * - * @return true if alternate blocks are allowed given the parameters, - * otherwise false - */ - bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const; - - /** - * @brief gets the highest checkpoint height - * - * @return the height of the highest checkpoint - */ - uint64_t get_max_height() const; - - /** - * @brief gets the checkpoints container - * - * @return a const reference to the checkpoints container - */ - const std::map& get_points() const; - - /** - * @brief checks if our checkpoints container conflicts with another - * - * A conflict refers to a case where both checkpoint sets have a checkpoint - * for a specific height but their hashes for that height do not match. - * - * @param other the other checkpoints instance to check against - * - * @return false if any conflict is found, otherwise true - */ - bool check_for_conflicts(const checkpoints& other) const; - - /** - * @brief loads the default main chain checkpoints - * - * @return true unless adding a checkpoint fails - */ - bool init_default_checkpoints(); - - /** - * @brief load new checkpoints - * - * Loads new checkpoints from the specified json file, as well as - * (optionally) from DNS. - * - * @param json_hashfile_fullpath path to the json checkpoints file - * @param testnet whether to load testnet checkpoints or mainnet - * @param dns whether or not to load DNS checkpoints - * - * @return true if loading successful and no conflicts - */ - bool load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet=false, bool dns=true); - - /** - * @brief load new checkpoints from json - * - * @param json_hashfile_fullpath path to the json checkpoints file - * - * @return true if loading successful and no conflicts - */ - bool load_checkpoints_from_json(const std::string json_hashfile_fullpath); - - /** - * @brief load new checkpoints from DNS - * - * @param testnet whether to load testnet checkpoints or mainnet - * - * @return true if loading successful and no conflicts - */ - bool load_checkpoints_from_dns(bool testnet = false); - - private: - - - /** - * @brief struct for loading a checkpoint from json - */ - struct t_hashline - { - uint64_t height; //!< the height of the checkpoint - std::string hash; //!< the hash for the checkpoint - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - KV_SERIALIZE(hash) - END_KV_SERIALIZE_MAP() - }; - - /** - * @brief struct for loading many checkpoints from json - */ - struct t_hash_json { - std::vector hashlines; //!< the checkpoint lines from the file - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(hashlines) - END_KV_SERIALIZE_MAP() - }; - - std::map m_points; //!< the checkpoints container - - }; -} diff --git a/src/Native/libcryptonote/cryptonote_basic/connection_context.h b/src/Native/libcryptonote/cryptonote_basic/connection_context.h deleted file mode 100644 index 5cd1709ab..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/connection_context.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include -#include -#include "net/net_utils_base.h" -#include "copyable_atomic.h" - -namespace cryptonote -{ - - struct cryptonote_connection_context: public epee::net_utils::connection_context_base - { - cryptonote_connection_context(): m_state(state_before_handshake), m_remote_blockchain_height(0), m_last_response_height(0), - m_last_request_time(boost::posix_time::microsec_clock::universal_time()), m_callback_request_count(0), m_last_known_hash(crypto::null_hash) {} - - enum state - { - state_before_handshake = 0, //default state - state_synchronizing, - state_standby, - state_idle, - state_normal - }; - - state m_state; - std::list m_needed_objects; - std::unordered_set m_requested_objects; - uint64_t m_remote_blockchain_height; - uint64_t m_last_response_height; - boost::posix_time::ptime m_last_request_time; - epee::copyable_atomic m_callback_request_count; //in debug purpose: problem with double callback rise - crypto::hash m_last_known_hash; - //size_t m_score; TODO: add score calculations - }; - - inline std::string get_protocol_state_string(cryptonote_connection_context::state s) - { - switch (s) - { - case cryptonote_connection_context::state_before_handshake: - return "state_before_handshake"; - case cryptonote_connection_context::state_synchronizing: - return "state_synchronizing"; - case cryptonote_connection_context::state_standby: - return "state_standby"; - case cryptonote_connection_context::state_idle: - return "state_idle"; - case cryptonote_connection_context::state_normal: - return "state_normal"; - default: - return "unknown"; - } - } - -} diff --git a/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic.h b/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic.h deleted file mode 100644 index 3f00d1d13..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic.h +++ /dev/null @@ -1,506 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include -#include -#include -#include // memcmp -#include -#include -#include "serialization/variant.h" -#include "serialization/vector.h" -#include "serialization/binary_archive.h" -#include "serialization/json_archive.h" -#include "serialization/debug_archive.h" -#include "serialization/crypto.h" -#include "serialization/keyvalue_serialization.h" // eepe named serialization -#include "cryptonote_config.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "misc_language.h" -#include "tx_extra.h" -#include "ringct/rctTypes.h" -#include "device/device.hpp" - -namespace cryptonote -{ - typedef std::vector ring_signature; - - - /* outputs */ - - struct txout_to_script - { - std::vector keys; - std::vector script; - - BEGIN_SERIALIZE_OBJECT() - FIELD(keys) - FIELD(script) - END_SERIALIZE() - }; - - struct txout_to_scripthash - { - crypto::hash hash; - }; - - struct txout_to_key - { - txout_to_key() { } - txout_to_key(const crypto::public_key &_key) : key(_key) { } - crypto::public_key key; - }; - - - /* inputs */ - - struct txin_gen - { - size_t height; - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(height) - END_SERIALIZE() - }; - - struct txin_to_script - { - crypto::hash prev; - size_t prevout; - std::vector sigset; - - BEGIN_SERIALIZE_OBJECT() - FIELD(prev) - VARINT_FIELD(prevout) - FIELD(sigset) - END_SERIALIZE() - }; - - struct txin_to_scripthash - { - crypto::hash prev; - size_t prevout; - txout_to_script script; - std::vector sigset; - - BEGIN_SERIALIZE_OBJECT() - FIELD(prev) - VARINT_FIELD(prevout) - FIELD(script) - FIELD(sigset) - END_SERIALIZE() - }; - - struct txin_to_key - { - uint64_t amount; - std::vector key_offsets; - crypto::key_image k_image; // double spending protection - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(amount) - FIELD(key_offsets) - FIELD(k_image) - END_SERIALIZE() - }; - - - typedef boost::variant txin_v; - - typedef boost::variant txout_target_v; - - //typedef std::pair out_t; - struct tx_out - { - uint64_t amount; - txout_target_v target; - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(amount) - FIELD(target) - END_SERIALIZE() - - - }; - - class transaction_prefix - { - - public: - // tx information - size_t version; - uint64_t unlock_time; //number of block (or time), used as a limitation like: spend this tx not early then block/time - - std::vector vin; - std::vector vout; - //extra - std::vector extra; - - BEGIN_SERIALIZE() - VARINT_FIELD(version) - if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false; - VARINT_FIELD(unlock_time) - FIELD(vin) - FIELD(vout) - FIELD(extra) - END_SERIALIZE() - - public: - transaction_prefix(){} - }; - - class transaction: public transaction_prefix - { - private: - // hash cash - mutable std::atomic hash_valid; - mutable std::atomic blob_size_valid; - - public: - std::vector > signatures; //count signatures always the same as inputs count - rct::rctSig rct_signatures; - - // hash cash - mutable crypto::hash hash; - mutable size_t blob_size; - - transaction(); - transaction(const transaction &t): transaction_prefix(t), hash_valid(false), blob_size_valid(false), signatures(t.signatures), rct_signatures(t.rct_signatures) { if (t.is_hash_valid()) { hash = t.hash; set_hash_valid(true); } if (t.is_blob_size_valid()) { blob_size = t.blob_size; set_blob_size_valid(true); } } - transaction &operator=(const transaction &t) { transaction_prefix::operator=(t); set_hash_valid(false); set_blob_size_valid(false); signatures = t.signatures; rct_signatures = t.rct_signatures; if (t.is_hash_valid()) { hash = t.hash; set_hash_valid(true); } if (t.is_blob_size_valid()) { blob_size = t.blob_size; set_blob_size_valid(true); } return *this; } - virtual ~transaction(); - void set_null(); - void invalidate_hashes(); - bool is_hash_valid() const { return hash_valid.load(std::memory_order_acquire); } - void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); } - bool is_blob_size_valid() const { return blob_size_valid.load(std::memory_order_acquire); } - void set_blob_size_valid(bool v) const { blob_size_valid.store(v,std::memory_order_release); } - - BEGIN_SERIALIZE_OBJECT() - if (!typename Archive::is_saving()) - { - set_hash_valid(false); - set_blob_size_valid(false); - } - - FIELDS(*static_cast(this)) - - if (version == 1) - { - ar.tag("signatures"); - ar.begin_array(); - PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures); - bool signatures_not_expected = signatures.empty(); - if (!signatures_not_expected && vin.size() != signatures.size()) - return false; - - for (size_t i = 0; i < vin.size(); ++i) - { - size_t signature_size = get_signature_size(vin[i]); - if (signatures_not_expected) - { - if (0 == signature_size) - continue; - else - return false; - } - - PREPARE_CUSTOM_VECTOR_SERIALIZATION(signature_size, signatures[i]); - if (signature_size != signatures[i].size()) - return false; - - FIELDS(signatures[i]); - - if (vin.size() - i > 1) - ar.delimit_array(); - } - ar.end_array(); - } - else - { - ar.tag("rct_signatures"); - if (!vin.empty()) - { - ar.begin_object(); - bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size()); - if (!r || !ar.stream().good()) return false; - ar.end_object(); - if (rct_signatures.type != rct::RCTTypeNull) - { - ar.tag("rctsig_prunable"); - ar.begin_object(); - r = rct_signatures.p.serialize_rctsig_prunable(ar, rct_signatures.type, vin.size(), vout.size(), - vin.size() > 0 && vin[0].type() == typeid(txin_to_key) ? boost::get(vin[0]).key_offsets.size() - 1 : 0); - if (!r || !ar.stream().good()) return false; - ar.end_object(); - } - } - } - END_SERIALIZE() - - template class Archive> - bool serialize_base(Archive &ar) - { - FIELDS(*static_cast(this)) - - if (version == 1) - { - } - else - { - ar.tag("rct_signatures"); - if (!vin.empty()) - { - ar.begin_object(); - bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size()); - if (!r || !ar.stream().good()) return false; - ar.end_object(); - } - } - return true; - } - - private: - static size_t get_signature_size(const txin_v& tx_in); - }; - - - inline - transaction::transaction() - { - set_null(); - } - - inline - transaction::~transaction() - { - //set_null(); - } - - inline - void transaction::set_null() - { - version = 1; - unlock_time = 0; - vin.clear(); - vout.clear(); - extra.clear(); - signatures.clear(); - rct_signatures.type = rct::RCTTypeNull; - set_hash_valid(false); - set_blob_size_valid(false); - } - - inline - void transaction::invalidate_hashes() - { - set_hash_valid(false); - set_blob_size_valid(false); - } - - inline - size_t transaction::get_signature_size(const txin_v& tx_in) - { - struct txin_signature_size_visitor : public boost::static_visitor - { - size_t operator()(const txin_gen& txin) const{return 0;} - size_t operator()(const txin_to_script& txin) const{return 0;} - size_t operator()(const txin_to_scripthash& txin) const{return 0;} - size_t operator()(const txin_to_key& txin) const {return txin.key_offsets.size();} - }; - - return boost::apply_visitor(txin_signature_size_visitor(), tx_in); - } - - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct block_header - { - uint8_t major_version; - uint8_t minor_version; // now used as a voting mechanism, rather than how this particular block is built - uint64_t timestamp; - crypto::hash prev_id; - uint32_t nonce; - - BEGIN_SERIALIZE() - VARINT_FIELD(major_version) - VARINT_FIELD(minor_version) - VARINT_FIELD(timestamp) - FIELD(prev_id) - FIELD(nonce) - END_SERIALIZE() - }; - - struct block: public block_header - { - private: - // hash cash - mutable std::atomic hash_valid; - - public: - block(): block_header(), hash_valid(false) {} - block(const block &b): block_header(b), hash_valid(false), miner_tx(b.miner_tx), tx_hashes(b.tx_hashes) { if (b.is_hash_valid()) { hash = b.hash; set_hash_valid(true); } } - block &operator=(const block &b) { block_header::operator=(b); hash_valid = false; miner_tx = b.miner_tx; tx_hashes = b.tx_hashes; if (b.is_hash_valid()) { hash = b.hash; set_hash_valid(true); } return *this; } - void invalidate_hashes() { set_hash_valid(false); } - bool is_hash_valid() const { return hash_valid.load(std::memory_order_acquire); } - void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); } - - transaction miner_tx; - std::vector tx_hashes; - - // hash cash - mutable crypto::hash hash; - - BEGIN_SERIALIZE_OBJECT() - if (!typename Archive::is_saving()) - set_hash_valid(false); - - FIELDS(*static_cast(this)) - FIELD(miner_tx) - FIELD(tx_hashes) - END_SERIALIZE() - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct account_public_address - { - crypto::public_key m_spend_public_key; - crypto::public_key m_view_public_key; - - BEGIN_SERIALIZE_OBJECT() - FIELD(m_spend_public_key) - FIELD(m_view_public_key) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_public_key) - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_public_key) - END_KV_SERIALIZE_MAP() - - bool operator==(const account_public_address& rhs) const - { - return m_spend_public_key == rhs.m_spend_public_key && - m_view_public_key == rhs.m_view_public_key; - } - - bool operator!=(const account_public_address& rhs) const - { - return !(*this == rhs); - } - }; - - struct integrated_address - { - account_public_address adr; - crypto::hash8 payment_id; - - BEGIN_SERIALIZE_OBJECT() - FIELD(adr) - FIELD(payment_id) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(adr) - KV_SERIALIZE(payment_id) - END_KV_SERIALIZE_MAP() - }; - - - struct keypair - { - crypto::public_key pub; - crypto::secret_key sec; - - static inline keypair generate(hw::device &hwdev) - { - keypair k; - hwdev.generate_keys(k.pub, k.sec); - return k; - } - }; - //--------------------------------------------------------------- - -} - -namespace std { - template <> - struct hash - { - std::size_t operator()(const cryptonote::account_public_address& addr) const - { - // https://stackoverflow.com/a/17017281 - size_t res = 17; - res = res * 31 + hash()(addr.m_spend_public_key); - res = res * 31 + hash()(addr.m_view_public_key); - return res; - } - }; -} - -BLOB_SERIALIZER(cryptonote::txout_to_key); -BLOB_SERIALIZER(cryptonote::txout_to_scripthash); - -VARIANT_TAG(binary_archive, cryptonote::txin_gen, 0xff); -VARIANT_TAG(binary_archive, cryptonote::txin_to_script, 0x0); -VARIANT_TAG(binary_archive, cryptonote::txin_to_scripthash, 0x1); -VARIANT_TAG(binary_archive, cryptonote::txin_to_key, 0x2); -VARIANT_TAG(binary_archive, cryptonote::txout_to_script, 0x0); -VARIANT_TAG(binary_archive, cryptonote::txout_to_scripthash, 0x1); -VARIANT_TAG(binary_archive, cryptonote::txout_to_key, 0x2); -VARIANT_TAG(binary_archive, cryptonote::transaction, 0xcc); -VARIANT_TAG(binary_archive, cryptonote::block, 0xbb); - -VARIANT_TAG(json_archive, cryptonote::txin_gen, "gen"); -VARIANT_TAG(json_archive, cryptonote::txin_to_script, "script"); -VARIANT_TAG(json_archive, cryptonote::txin_to_scripthash, "scripthash"); -VARIANT_TAG(json_archive, cryptonote::txin_to_key, "key"); -VARIANT_TAG(json_archive, cryptonote::txout_to_script, "script"); -VARIANT_TAG(json_archive, cryptonote::txout_to_scripthash, "scripthash"); -VARIANT_TAG(json_archive, cryptonote::txout_to_key, "key"); -VARIANT_TAG(json_archive, cryptonote::transaction, "tx"); -VARIANT_TAG(json_archive, cryptonote::block, "block"); - -VARIANT_TAG(debug_archive, cryptonote::txin_gen, "gen"); -VARIANT_TAG(debug_archive, cryptonote::txin_to_script, "script"); -VARIANT_TAG(debug_archive, cryptonote::txin_to_scripthash, "scripthash"); -VARIANT_TAG(debug_archive, cryptonote::txin_to_key, "key"); -VARIANT_TAG(debug_archive, cryptonote::txout_to_script, "script"); -VARIANT_TAG(debug_archive, cryptonote::txout_to_scripthash, "scripthash"); -VARIANT_TAG(debug_archive, cryptonote::txout_to_key, "key"); -VARIANT_TAG(debug_archive, cryptonote::transaction, "tx"); -VARIANT_TAG(debug_archive, cryptonote::block, "block"); diff --git a/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic_impl.cpp b/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic_impl.cpp deleted file mode 100644 index 9a9362466..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic_impl.cpp +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include "include_base_utils.h" -using namespace epee; - -#include "cryptonote_basic_impl.h" -#include "string_tools.h" -#include "serialization/binary_utils.h" -#include "serialization/container.h" -#include "cryptonote_format_utils.h" -#include "cryptonote_config.h" -#include "misc_language.h" -#include "common/base58.h" -#include "crypto/hash.h" -#include "common/int-util.h" -#include "common/dns_utils.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "cn" - -namespace cryptonote { - - struct integrated_address { - account_public_address adr; - crypto::hash8 payment_id; - - BEGIN_SERIALIZE_OBJECT() - FIELD(adr) - FIELD(payment_id) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(adr) - KV_SERIALIZE(payment_id) - END_KV_SERIALIZE_MAP() - }; - - /************************************************************************/ - /* Cryptonote helper functions */ - /************************************************************************/ - //----------------------------------------------------------------------------------------------- - size_t get_min_block_size(uint8_t version) - { - if (version < 2) - return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1; - if (version < 5) - return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2; - return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5; - } - //----------------------------------------------------------------------------------------------- - size_t get_max_block_size() - { - return CRYPTONOTE_MAX_BLOCK_SIZE; - } - //----------------------------------------------------------------------------------------------- - size_t get_max_tx_size() - { - return CRYPTONOTE_MAX_TX_SIZE; - } - //----------------------------------------------------------------------------------------------- - bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version) { - static_assert(DIFFICULTY_TARGET_V2%60==0&&DIFFICULTY_TARGET_V1%60==0,"difficulty targets must be a multiple of 60"); - const int target = version < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; - const int target_minutes = target / 60; - const int emission_speed_factor = EMISSION_SPEED_FACTOR_PER_MINUTE - (target_minutes-1); - - uint64_t base_reward = (MONEY_SUPPLY - already_generated_coins) >> emission_speed_factor; - if (base_reward < FINAL_SUBSIDY_PER_MINUTE*target_minutes) - { - base_reward = FINAL_SUBSIDY_PER_MINUTE*target_minutes; - } - - uint64_t full_reward_zone = get_min_block_size(version); - - //make it soft - if (median_size < full_reward_zone) { - median_size = full_reward_zone; - } - - if (current_block_size <= median_size) { - reward = base_reward; - return true; - } - - if(current_block_size > 2 * median_size) { - MERROR("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size); - return false; - } - - assert(median_size < std::numeric_limits::max()); - assert(current_block_size < std::numeric_limits::max()); - - uint64_t product_hi; - // BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being - // treated as 32-bit by default. - uint64_t multiplicand = 2 * median_size - current_block_size; - multiplicand *= current_block_size; - uint64_t product_lo = mul128(base_reward, multiplicand, &product_hi); - - uint64_t reward_hi; - uint64_t reward_lo; - div128_32(product_hi, product_lo, static_cast(median_size), &reward_hi, &reward_lo); - div128_32(reward_hi, reward_lo, static_cast(median_size), &reward_hi, &reward_lo); - assert(0 == reward_hi); - assert(reward_lo < base_reward); - - reward = reward_lo; - return true; - } - //------------------------------------------------------------------------------------ - uint8_t get_account_address_checksum(const public_address_outer_blob& bl) - { - const unsigned char* pbuf = reinterpret_cast(&bl); - uint8_t summ = 0; - for(size_t i = 0; i!= sizeof(public_address_outer_blob)-1; i++) - summ += pbuf[i]; - - return summ; - } - //------------------------------------------------------------------------------------ - uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl) - { - const unsigned char* pbuf = reinterpret_cast(&bl); - uint8_t summ = 0; - for(size_t i = 0; i!= sizeof(public_integrated_address_outer_blob)-1; i++) - summ += pbuf[i]; - - return summ; - } - //----------------------------------------------------------------------- - std::string get_account_address_as_str( - uint8_t nettype - , bool subaddress - , account_public_address const & adr - ) - { - uint64_t address_prefix = nettype == TESTNET ? - (subaddress ? config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) : nettype == STAGENET ? - (subaddress ? config::stagenet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) : - (subaddress ? config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX); - - return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr)); - } - //----------------------------------------------------------------------- - std::string get_account_integrated_address_as_str( - uint8_t nettype - , account_public_address const & adr - , crypto::hash8 const & payment_id - ) - { - uint64_t integrated_address_prefix = nettype == TESTNET ? config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : nettype == STAGENET ? config::stagenet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; - - integrated_address iadr = { - adr, payment_id - }; - return tools::base58::encode_addr(integrated_address_prefix, t_serializable_object_to_blob(iadr)); - } - //----------------------------------------------------------------------- - bool is_coinbase(const transaction& tx) - { - if(tx.vin.size() != 1) - return false; - - if(tx.vin[0].type() != typeid(txin_gen)) - return false; - - return true; - } - //----------------------------------------------------------------------- - bool get_account_address_from_str( - address_parse_info& info - , uint8_t nettype - , std::string const & str - ) - { - uint64_t address_prefix = nettype == TESTNET ? - config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : nettype == STAGENET ? - config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; - uint64_t integrated_address_prefix = nettype == TESTNET ? - config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : nettype == STAGENET ? - config::stagenet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; - uint64_t subaddress_prefix = nettype == TESTNET ? - config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : nettype == STAGENET ? - config::stagenet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX; - - if (2 * sizeof(public_address_outer_blob) != str.size()) - { - blobdata data; - uint64_t prefix; - if (!tools::base58::decode_addr(str, prefix, data)) - { - LOG_PRINT_L2("Invalid address format"); - return false; - } - - if (integrated_address_prefix == prefix) - { - info.is_subaddress = false; - info.has_payment_id = true; - } - else if (address_prefix == prefix) - { - info.is_subaddress = false; - info.has_payment_id = false; - } - else if (subaddress_prefix == prefix) - { - info.is_subaddress = true; - info.has_payment_id = false; - } - else { - LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << address_prefix - << " or " << integrated_address_prefix - << " or " << subaddress_prefix); - return false; - } - - if (info.has_payment_id) - { - integrated_address iadr; - if (!::serialization::parse_binary(data, iadr)) - { - LOG_PRINT_L1("Account public address keys can't be parsed"); - return false; - } - info.address = iadr.adr; - info.payment_id = iadr.payment_id; - } - else - { - if (!::serialization::parse_binary(data, info.address)) - { - LOG_PRINT_L1("Account public address keys can't be parsed"); - return false; - } - } - - if (!crypto::check_key(info.address.m_spend_public_key) || !crypto::check_key(info.address.m_view_public_key)) - { - LOG_PRINT_L1("Failed to validate address keys"); - return false; - } - } - else - { - // Old address format - std::string buff; - if(!string_tools::parse_hexstr_to_binbuff(str, buff)) - return false; - - if(buff.size()!=sizeof(public_address_outer_blob)) - { - LOG_PRINT_L1("Wrong public address size: " << buff.size() << ", expected size: " << sizeof(public_address_outer_blob)); - return false; - } - - public_address_outer_blob blob = *reinterpret_cast(buff.data()); - - - if(blob.m_ver > CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER) - { - LOG_PRINT_L1("Unknown version of public address: " << blob.m_ver << ", expected " << CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER); - return false; - } - - if(blob.check_sum != get_account_address_checksum(blob)) - { - LOG_PRINT_L1("Wrong public address checksum"); - return false; - } - - //we success - info.address = blob.m_address; - info.is_subaddress = false; - info.has_payment_id = false; - } - - return true; - } - //-------------------------------------------------------------------------------- - bool get_account_address_from_str_or_url( - address_parse_info& info - , uint8_t nettype - , const std::string& str_or_url - , std::function&, bool)> dns_confirm - ) - { - if (get_account_address_from_str(info, nettype, str_or_url)) - return true; - bool dnssec_valid; - std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, dns_confirm); - return !address_str.empty() && - get_account_address_from_str(info, nettype, address_str); - } - //-------------------------------------------------------------------------------- - bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) { - return cryptonote::get_transaction_hash(a) == cryptonote::get_transaction_hash(b); - } - - bool operator ==(const cryptonote::block& a, const cryptonote::block& b) { - return cryptonote::get_block_hash(a) == cryptonote::get_block_hash(b); - } -} - -//-------------------------------------------------------------------------------- -bool parse_hash256(const std::string str_hash, crypto::hash& hash) -{ - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(crypto::hash)) - { - std::cout << "invalid hash format: <" << str_hash << '>' << std::endl; - return false; - } - else - { - buf.copy(reinterpret_cast(&hash), sizeof(crypto::hash)); - return true; - } -} diff --git a/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic_impl.h b/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic_impl.h deleted file mode 100644 index 4ec2b403d..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/cryptonote_basic_impl.h +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include "cryptonote_basic.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" - - -namespace cryptonote { - /************************************************************************/ - /* */ - /************************************************************************/ - template - struct array_hasher: std::unary_function - { - std::size_t operator()(const t_array& val) const - { - return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]); - } - }; - - -#pragma pack(push, 1) - struct public_address_outer_blob - { - uint8_t m_ver; - account_public_address m_address; - uint8_t check_sum; - }; - struct public_integrated_address_outer_blob - { - uint8_t m_ver; - account_public_address m_address; - crypto::hash8 payment_id; - uint8_t check_sum; - }; -#pragma pack (pop) - - namespace - { - inline std::string return_first_address(const std::string &url, const std::vector &addresses, bool dnssec_valid) - { - if (addresses.empty()) - return {}; - return addresses[0]; - } - } - - struct address_parse_info - { - account_public_address address; - bool is_subaddress; - bool has_payment_id; - crypto::hash8 payment_id; - }; - - /************************************************************************/ - /* Cryptonote helper functions */ - /************************************************************************/ - size_t get_min_block_size(uint8_t version); - size_t get_max_block_size(); - size_t get_max_tx_size(); - bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version); - uint8_t get_account_address_checksum(const public_address_outer_blob& bl); - uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl); - - std::string get_account_address_as_str( - uint8_t nettype - , bool subaddress - , const account_public_address& adr - ); - - std::string get_account_integrated_address_as_str( - uint8_t nettype - , const account_public_address& adr - , const crypto::hash8& payment_id - ); - - bool get_account_address_from_str( - address_parse_info& info - , uint8_t nettype - , const std::string& str - ); - - bool get_account_address_from_str_or_url( - address_parse_info& info - , uint8_t nettype - , const std::string& str_or_url - , std::function&, bool)> dns_confirm = return_first_address - ); - - bool is_coinbase(const transaction& tx); - - bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b); - bool operator ==(const cryptonote::block& a, const cryptonote::block& b); -} - -bool parse_hash256(const std::string str_hash, crypto::hash& hash); - diff --git a/src/Native/libcryptonote/cryptonote_basic/cryptonote_boost_serialization.h b/src/Native/libcryptonote/cryptonote_basic/cryptonote_boost_serialization.h deleted file mode 100644 index 143133163..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/cryptonote_boost_serialization.h +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cryptonote_basic.h" -#include "common/unordered_containers_boost_serialization.h" -#include "crypto/crypto.h" -#include "ringct/rctTypes.h" -#include "ringct/rctOps.h" - -//namespace cryptonote { -namespace boost -{ - namespace serialization - { - - //--------------------------------------------------- - template - inline void serialize(Archive &a, crypto::public_key &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::secret_key &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::key_derivation &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::key_image &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - - template - inline void serialize(Archive &a, crypto::signature &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::hash &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::hash8 &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - - template - inline void serialize(Archive &a, cryptonote::txout_to_script &x, const boost::serialization::version_type ver) - { - a & x.keys; - a & x.script; - } - - - template - inline void serialize(Archive &a, cryptonote::txout_to_key &x, const boost::serialization::version_type ver) - { - a & x.key; - } - - template - inline void serialize(Archive &a, cryptonote::txout_to_scripthash &x, const boost::serialization::version_type ver) - { - a & x.hash; - } - - template - inline void serialize(Archive &a, cryptonote::txin_gen &x, const boost::serialization::version_type ver) - { - a & x.height; - } - - template - inline void serialize(Archive &a, cryptonote::txin_to_script &x, const boost::serialization::version_type ver) - { - a & x.prev; - a & x.prevout; - a & x.sigset; - } - - template - inline void serialize(Archive &a, cryptonote::txin_to_scripthash &x, const boost::serialization::version_type ver) - { - a & x.prev; - a & x.prevout; - a & x.script; - a & x.sigset; - } - - template - inline void serialize(Archive &a, cryptonote::txin_to_key &x, const boost::serialization::version_type ver) - { - a & x.amount; - a & x.key_offsets; - a & x.k_image; - } - - template - inline void serialize(Archive &a, cryptonote::tx_out &x, const boost::serialization::version_type ver) - { - a & x.amount; - a & x.target; - } - - - template - inline void serialize(Archive &a, cryptonote::transaction_prefix &x, const boost::serialization::version_type ver) - { - a & x.version; - a & x.unlock_time; - a & x.vin; - a & x.vout; - a & x.extra; - } - - template - inline void serialize(Archive &a, cryptonote::transaction &x, const boost::serialization::version_type ver) - { - a & x.version; - a & x.unlock_time; - a & x.vin; - a & x.vout; - a & x.extra; - if (x.version == 1) - { - a & x.signatures; - } - else - { - a & (rct::rctSigBase&)x.rct_signatures; - if (x.rct_signatures.type != rct::RCTTypeNull) - a & x.rct_signatures.p; - } - } - - template - inline void serialize(Archive &a, cryptonote::block &b, const boost::serialization::version_type ver) - { - a & b.major_version; - a & b.minor_version; - a & b.timestamp; - a & b.prev_id; - a & b.nonce; - //------------------ - a & b.miner_tx; - a & b.tx_hashes; - } - - template - inline void serialize(Archive &a, rct::key &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - - template - inline void serialize(Archive &a, rct::ctkey &x, const boost::serialization::version_type ver) - { - a & x.dest; - a & x.mask; - } - - template - inline void serialize(Archive &a, rct::rangeSig &x, const boost::serialization::version_type ver) - { - a & x.asig; - a & x.Ci; - } - - template - inline void serialize(Archive &a, rct::Bulletproof &x, const boost::serialization::version_type ver) - { - a & x.V; - a & x.A; - a & x.S; - a & x.T1; - a & x.T2; - a & x.taux; - a & x.mu; - a & x.L; - a & x.R; - a & x.a; - a & x.b; - a & x.t; - } - - template - inline void serialize(Archive &a, rct::boroSig &x, const boost::serialization::version_type ver) - { - a & x.s0; - a & x.s1; - a & x.ee; - } - - template - inline void serialize(Archive &a, rct::mgSig &x, const boost::serialization::version_type ver) - { - a & x.ss; - a & x.cc; - // a & x.II; // not serialized, we can recover it from the tx vin - } - - template - inline void serialize(Archive &a, rct::ecdhTuple &x, const boost::serialization::version_type ver) - { - a & x.mask; - a & x.amount; - // a & x.senderPk; // not serialized, as we do not use it in monero currently - } - - template - inline void serialize(Archive &a, rct::multisig_kLRki &x, const boost::serialization::version_type ver) - { - a & x.k; - a & x.L; - a & x.R; - a & x.ki; - } - - template - inline void serialize(Archive &a, rct::multisig_out &x, const boost::serialization::version_type ver) - { - a & x.c; - } - - template - inline typename std::enable_if::type serializeOutPk(Archive &a, rct::ctkeyV &outPk_, const boost::serialization::version_type ver) - { - rct::keyV outPk; - a & outPk; - outPk_.resize(outPk.size()); - for (size_t n = 0; n < outPk_.size(); ++n) - { - outPk_[n].dest = rct::identity(); - outPk_[n].mask = outPk[n]; - } - } - - template - inline typename std::enable_if::type serializeOutPk(Archive &a, rct::ctkeyV &outPk_, const boost::serialization::version_type ver) - { - rct::keyV outPk(outPk_.size()); - for (size_t n = 0; n < outPk_.size(); ++n) - outPk[n] = outPk_[n].mask; - a & outPk; - } - - template - inline void serialize(Archive &a, rct::rctSigBase &x, const boost::serialization::version_type ver) - { - a & x.type; - if (x.type == rct::RCTTypeNull) - return; - if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeSimpleBulletproof) - throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); - // a & x.message; message is not serialized, as it can be reconstructed from the tx data - // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets - if (x.type == rct::RCTTypeSimple) // moved to prunable with bulletproofs - a & x.pseudoOuts; - a & x.ecdhInfo; - serializeOutPk(a, x.outPk, ver); - a & x.txnFee; - } - - template - inline void serialize(Archive &a, rct::rctSigPrunable &x, const boost::serialization::version_type ver) - { - a & x.rangeSigs; - if (x.rangeSigs.empty()) - a & x.bulletproofs; - a & x.MGs; - if (x.rangeSigs.empty()) - a & x.pseudoOuts; - } - - template - inline void serialize(Archive &a, rct::rctSig &x, const boost::serialization::version_type ver) - { - a & x.type; - if (x.type == rct::RCTTypeNull) - return; - if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeSimpleBulletproof) - throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); - // a & x.message; message is not serialized, as it can be reconstructed from the tx data - // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets - if (x.type == rct::RCTTypeSimple) - a & x.pseudoOuts; - a & x.ecdhInfo; - serializeOutPk(a, x.outPk, ver); - a & x.txnFee; - //-------------- - a & x.p.rangeSigs; - if (x.p.rangeSigs.empty()) - a & x.p.bulletproofs; - a & x.p.MGs; - if (x.type == rct::RCTTypeSimpleBulletproof) - a & x.p.pseudoOuts; - } -} -} - -//} diff --git a/src/Native/libcryptonote/cryptonote_basic/cryptonote_config.h b/src/Native/libcryptonote/cryptonote_basic/cryptonote_config.h deleted file mode 100644 index abfa665ff..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/cryptonote_config.h +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2014-2017, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include -#include - -#define CRYPTONOTE_DNS_TIMEOUT_MS 20000 - -#define CRYPTONOTE_MAX_BLOCK_NUMBER 500000000 -#define CRYPTONOTE_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used! -#define CRYPTONOTE_GETBLOCKTEMPLATE_MAX_BLOCK_SIZE 196608 //size of block (bytes) that is the maximum that miners will produce -#define CRYPTONOTE_MAX_TX_SIZE 1000000000 -#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0 -#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60 -#define CURRENT_TRANSACTION_VERSION 2 -#define CURRENT_BLOCK_MAJOR_VERSION 1 -#define CURRENT_BLOCK_MINOR_VERSION 0 -#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2 -#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE 10 - -#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60 - -// MONEY_SUPPLY - total number coins to be generated -#define MONEY_SUPPLY ((uint64_t)(-1)) -#define EMISSION_SPEED_FACTOR_PER_MINUTE (20) -#define FINAL_SUBSIDY_PER_MINUTE ((uint64_t)300000000000) // 3 * pow(10, 11) - -#define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100 -#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 60000 //size of block (bytes) after which reward for block calculated using block size -#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 20000 //size of block (bytes) after which reward for block calculated using block size - before first fork -#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 300000 //size of block (bytes) after which reward for block calculated using block size - second change, from v5 -#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600 -#define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12 -// COIN - number of smallest units in one coin -#define COIN ((uint64_t)1000000000000) // pow(10, 12) - -#define FEE_PER_KB_OLD ((uint64_t)10000000000) // pow(10, 10) -#define FEE_PER_KB ((uint64_t)2000000000) // 2 * pow(10, 9) -#define DYNAMIC_FEE_PER_KB_BASE_FEE ((uint64_t)2000000000) // 2 * pow(10,9) -#define DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD ((uint64_t)10000000000000) // 10 * pow(10,12) -#define DYNAMIC_FEE_PER_KB_BASE_FEE_V5 ((uint64_t)2000000000 * (uint64_t)CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5) - -#define ORPHANED_BLOCKS_MAX_COUNT 100 - - -#define DIFFICULTY_TARGET_V2 120 // seconds -#define DIFFICULTY_TARGET_V1 60 // seconds - before first fork -#define DIFFICULTY_WINDOW 720 // blocks -#define DIFFICULTY_LAG 15 // !!! -#define DIFFICULTY_CUT 60 // timestamps to cut after sorting -#define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG - - -#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 DIFFICULTY_TARGET_V1 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS -#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2 DIFFICULTY_TARGET_V2 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS -#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS 1 - - -#define DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN DIFFICULTY_TARGET_V1 //just alias; used by tests - - -#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT 10000 //by default, blocks ids count in synchronizing -#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 200 //by default, blocks count in blocks downloading -#define CRYPTONOTE_PROTOCOL_HOP_RELAX_COUNT 3 //value of hop, after which we use only announce of new block - -#define CRYPTONOTE_MEMPOOL_TX_LIVETIME 86400 //seconds, one day -#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 604800 //seconds, one week - -#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT 1000 - -#define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000 -#define P2P_LOCAL_GRAY_PEERLIST_LIMIT 5000 - -#define P2P_DEFAULT_CONNECTIONS_COUNT 8 -#define P2P_DEFAULT_HANDSHAKE_INTERVAL 60 //secondes -#define P2P_DEFAULT_PACKET_MAX_SIZE 50000000 //50000000 bytes maximum packet size -#define P2P_DEFAULT_PEERS_IN_HANDSHAKE 250 -#define P2P_DEFAULT_CONNECTION_TIMEOUT 5000 //5 seconds -#define P2P_DEFAULT_PING_CONNECTION_TIMEOUT 2000 //2 seconds -#define P2P_DEFAULT_INVOKE_TIMEOUT 60*2*1000 //2 minutes -#define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 5000 //5 seconds -#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70 - -#define P2P_FAILED_ADDR_FORGET_SECONDS (60*60) //1 hour -#define P2P_IP_BLOCKTIME (60*60*24) //24 hour -#define P2P_IP_FAILS_BEFORE_BLOCK 10 -#define P2P_IDLE_CONNECTION_KILL_INTERVAL (5*60) //5 minutes - -#define P2P_SUPPORT_FLAG_FLUFFY_BLOCKS 0x01 -#define P2P_SUPPORT_FLAGS P2P_SUPPORT_FLAG_FLUFFY_BLOCKS - -#define ALLOW_DEBUG_COMMANDS - -#define CRYPTONOTE_NAME "bitmonero" -#define CRYPTONOTE_POOLDATA_FILENAME "poolstate.bin" -#define CRYPTONOTE_BLOCKCHAINDATA_FILENAME "data.mdb" -#define CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME "lock.mdb" -#define P2P_NET_DATA_FILENAME "p2pstate.bin" -#define MINER_CONFIG_FILE_NAME "miner_conf.json" - -#define THREAD_STACK_SIZE 5 * 1024 * 1024 - -#define HF_VERSION_DYNAMIC_FEE 4 -#define HF_VERSION_MIN_MIXIN_4 6 -#define HF_VERSION_ENFORCE_RCT 6 - -#define PER_KB_FEE_QUANTIZATION_DECIMALS 8 - -// New constants are intended to go here -namespace config -{ - uint64_t const DEFAULT_FEE_ATOMIC_XMR_PER_KB = 500; // Just a placeholder! Change me! - uint8_t const FEE_CALCULATION_MAX_RETRIES = 10; - uint64_t const DEFAULT_DUST_THRESHOLD = ((uint64_t)2000000000); // 2 * pow(10, 9) - uint64_t const BASE_REWARD_CLAMP_THRESHOLD = ((uint64_t)100000000); // pow(10, 8) - std::string const P2P_REMOTE_DEBUG_TRUSTED_PUB_KEY = "0000000000000000000000000000000000000000000000000000000000000000"; - - uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18; - uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 19; - uint16_t const P2P_DEFAULT_PORT = 18080; - uint16_t const RPC_DEFAULT_PORT = 18081; - boost::uuids::uuid const NETWORK_ID = { { - 0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10 - } }; // Bender's nightmare - std::string const GENESIS_TX = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1"; - uint32_t const GENESIS_NONCE = 10000; - - namespace testnet - { - uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 53; - uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 54; - uint16_t const P2P_DEFAULT_PORT = 28080; - uint16_t const RPC_DEFAULT_PORT = 28081; - boost::uuids::uuid const NETWORK_ID = { { - 0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x11 - } }; // Bender's daydream - std::string const GENESIS_TX = "013c01ff0001ffffffffffff0f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd0880712101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b"; - uint32_t const GENESIS_NONCE = 10001; - } -} diff --git a/src/Native/libcryptonote/cryptonote_basic/cryptonote_format_utils.cpp b/src/Native/libcryptonote/cryptonote_basic/cryptonote_format_utils.cpp deleted file mode 100644 index 934767960..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/cryptonote_format_utils.cpp +++ /dev/null @@ -1,958 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include "include_base_utils.h" -using namespace epee; - -#include -#include -#include "wipeable_string.h" -#include "string_tools.h" -#include "serialization/string.h" -#include "cryptonote_format_utils.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "ringct/rctSigs.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "cn" - -#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d - -// #define ENABLE_HASH_CASH_INTEGRITY_CHECK - -using namespace crypto; - -static const uint64_t valid_decomposed_outputs[] = { - (uint64_t)1, (uint64_t)2, (uint64_t)3, (uint64_t)4, (uint64_t)5, (uint64_t)6, (uint64_t)7, (uint64_t)8, (uint64_t)9, // 1 piconero - (uint64_t)10, (uint64_t)20, (uint64_t)30, (uint64_t)40, (uint64_t)50, (uint64_t)60, (uint64_t)70, (uint64_t)80, (uint64_t)90, - (uint64_t)100, (uint64_t)200, (uint64_t)300, (uint64_t)400, (uint64_t)500, (uint64_t)600, (uint64_t)700, (uint64_t)800, (uint64_t)900, - (uint64_t)1000, (uint64_t)2000, (uint64_t)3000, (uint64_t)4000, (uint64_t)5000, (uint64_t)6000, (uint64_t)7000, (uint64_t)8000, (uint64_t)9000, - (uint64_t)10000, (uint64_t)20000, (uint64_t)30000, (uint64_t)40000, (uint64_t)50000, (uint64_t)60000, (uint64_t)70000, (uint64_t)80000, (uint64_t)90000, - (uint64_t)100000, (uint64_t)200000, (uint64_t)300000, (uint64_t)400000, (uint64_t)500000, (uint64_t)600000, (uint64_t)700000, (uint64_t)800000, (uint64_t)900000, - (uint64_t)1000000, (uint64_t)2000000, (uint64_t)3000000, (uint64_t)4000000, (uint64_t)5000000, (uint64_t)6000000, (uint64_t)7000000, (uint64_t)8000000, (uint64_t)9000000, // 1 micronero - (uint64_t)10000000, (uint64_t)20000000, (uint64_t)30000000, (uint64_t)40000000, (uint64_t)50000000, (uint64_t)60000000, (uint64_t)70000000, (uint64_t)80000000, (uint64_t)90000000, - (uint64_t)100000000, (uint64_t)200000000, (uint64_t)300000000, (uint64_t)400000000, (uint64_t)500000000, (uint64_t)600000000, (uint64_t)700000000, (uint64_t)800000000, (uint64_t)900000000, - (uint64_t)1000000000, (uint64_t)2000000000, (uint64_t)3000000000, (uint64_t)4000000000, (uint64_t)5000000000, (uint64_t)6000000000, (uint64_t)7000000000, (uint64_t)8000000000, (uint64_t)9000000000, - (uint64_t)10000000000, (uint64_t)20000000000, (uint64_t)30000000000, (uint64_t)40000000000, (uint64_t)50000000000, (uint64_t)60000000000, (uint64_t)70000000000, (uint64_t)80000000000, (uint64_t)90000000000, - (uint64_t)100000000000, (uint64_t)200000000000, (uint64_t)300000000000, (uint64_t)400000000000, (uint64_t)500000000000, (uint64_t)600000000000, (uint64_t)700000000000, (uint64_t)800000000000, (uint64_t)900000000000, - (uint64_t)1000000000000, (uint64_t)2000000000000, (uint64_t)3000000000000, (uint64_t)4000000000000, (uint64_t)5000000000000, (uint64_t)6000000000000, (uint64_t)7000000000000, (uint64_t)8000000000000, (uint64_t)9000000000000, // 1 monero - (uint64_t)10000000000000, (uint64_t)20000000000000, (uint64_t)30000000000000, (uint64_t)40000000000000, (uint64_t)50000000000000, (uint64_t)60000000000000, (uint64_t)70000000000000, (uint64_t)80000000000000, (uint64_t)90000000000000, - (uint64_t)100000000000000, (uint64_t)200000000000000, (uint64_t)300000000000000, (uint64_t)400000000000000, (uint64_t)500000000000000, (uint64_t)600000000000000, (uint64_t)700000000000000, (uint64_t)800000000000000, (uint64_t)900000000000000, - (uint64_t)1000000000000000, (uint64_t)2000000000000000, (uint64_t)3000000000000000, (uint64_t)4000000000000000, (uint64_t)5000000000000000, (uint64_t)6000000000000000, (uint64_t)7000000000000000, (uint64_t)8000000000000000, (uint64_t)9000000000000000, - (uint64_t)10000000000000000, (uint64_t)20000000000000000, (uint64_t)30000000000000000, (uint64_t)40000000000000000, (uint64_t)50000000000000000, (uint64_t)60000000000000000, (uint64_t)70000000000000000, (uint64_t)80000000000000000, (uint64_t)90000000000000000, - (uint64_t)100000000000000000, (uint64_t)200000000000000000, (uint64_t)300000000000000000, (uint64_t)400000000000000000, (uint64_t)500000000000000000, (uint64_t)600000000000000000, (uint64_t)700000000000000000, (uint64_t)800000000000000000, (uint64_t)900000000000000000, - (uint64_t)1000000000000000000, (uint64_t)2000000000000000000, (uint64_t)3000000000000000000, (uint64_t)4000000000000000000, (uint64_t)5000000000000000000, (uint64_t)6000000000000000000, (uint64_t)7000000000000000000, (uint64_t)8000000000000000000, (uint64_t)9000000000000000000, // 1 meganero - (uint64_t)10000000000000000000ull -}; - -static std::atomic default_decimal_point(CRYPTONOTE_DISPLAY_DECIMAL_POINT); - -static std::atomic tx_hashes_calculated_count(0); -static std::atomic tx_hashes_cached_count(0); -static std::atomic block_hashes_calculated_count(0); -static std::atomic block_hashes_cached_count(0); - -#define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) {if(!(expr)) {MWARNING(message); throw std::runtime_error(message);}} - -namespace cryptonote -{ - static inline unsigned char *operator &(ec_point &point) { - return &reinterpret_cast(point); - } - static inline const unsigned char *operator &(const ec_point &point) { - return &reinterpret_cast(point); - } - - // a copy of rct::addKeys, since we can't link to libringct to avoid circular dependencies - static void add_public_key(crypto::public_key &AB, const crypto::public_key &A, const crypto::public_key &B) { - ge_p3 B2, A2; - CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&B2, &B) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast(__LINE__)); - CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A2, &A) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast(__LINE__)); - ge_cached tmp2; - ge_p3_to_cached(&tmp2, &B2); - ge_p1p1 tmp3; - ge_add(&tmp3, &A2, &tmp2); - ge_p1p1_to_p3(&A2, &tmp3); - ge_p3_tobytes(&AB, &A2); - } -} - -namespace cryptonote -{ - //--------------------------------------------------------------- - void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h) - { - std::ostringstream s; - binary_archive a(s); - ::serialization::serialize(a, const_cast(tx)); - crypto::cn_fast_hash(s.str().data(), s.str().size(), h); - } - //--------------------------------------------------------------- - crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx) - { - crypto::hash h = null_hash; - get_transaction_prefix_hash(tx, h); - return h; - } - //--------------------------------------------------------------- - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx) - { - std::stringstream ss; - ss << tx_blob; - binary_archive ba(ss); - bool r = ::serialization::serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - tx.invalidate_hashes(); - return true; - } - //--------------------------------------------------------------- - bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx) - { - std::stringstream ss; - ss << tx_blob; - binary_archive ba(ss); - bool r = tx.serialize_base(ba); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - return true; - } - //--------------------------------------------------------------- - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash) - { - std::stringstream ss; - ss << tx_blob; - binary_archive ba(ss); - bool r = ::serialization::serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - tx.invalidate_hashes(); - //TODO: validate tx - - get_transaction_hash(tx, tx_hash); - get_transaction_prefix_hash(tx, tx_prefix_hash); - return true; - } - //--------------------------------------------------------------- - bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev) - { - if (ack.m_spend_secret_key == crypto::null_skey) - { - // for watch-only wallet, simply copy the known output pubkey - in_ephemeral.pub = out_key; - in_ephemeral.sec = crypto::null_skey; - } - else - { - // derive secret key with subaddress - step 1: original CN derivation - crypto::secret_key scalar_step1; - hwdev.derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, scalar_step1); // computes Hs(a*R || idx) + b - - // step 2: add Hs(a || index_major || index_minor) - crypto::secret_key subaddr_sk; - crypto::secret_key scalar_step2; - if (received_index.is_zero()) - { - scalar_step2 = scalar_step1; // treat index=(0,0) as a special case representing the main address - } - else - { - subaddr_sk = hwdev.get_subaddress_secret_key(ack.m_view_secret_key, received_index); - hwdev.sc_secret_add(scalar_step2, scalar_step1,subaddr_sk); - } - - in_ephemeral.sec = scalar_step2; - - if (ack.m_multisig_keys.empty()) - { - // when not in multisig, we know the full spend secret key, so the output pubkey can be obtained by scalarmultBase - CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key"); - } - else - { - // when in multisig, we only know the partial spend secret key. but we do know the full spend public key, so the output pubkey can be obtained by using the standard CN key derivation - CHECK_AND_ASSERT_MES(hwdev.derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key"); - // and don't forget to add the contribution from the subaddress part - if (!received_index.is_zero()) - { - crypto::public_key subaddr_pk; - CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key"); - add_public_key(in_ephemeral.pub, in_ephemeral.pub, subaddr_pk); - } - } - - CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, - false, "key image helper precomp: given output pubkey doesn't match the derived one"); - } - - hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki); - return true; - } - //--------------------------------------------------------------- - uint64_t power_integral(uint64_t a, uint64_t b) - { - if(b == 0) - return 1; - uint64_t total = a; - for(uint64_t i = 1; i != b; i++) - total *= a; - return total; - } - //--------------------------------------------------------------- - bool parse_amount(uint64_t& amount, const std::string& str_amount_) - { - std::string str_amount = str_amount_; - boost::algorithm::trim(str_amount); - - size_t point_index = str_amount.find_first_of('.'); - size_t fraction_size; - if (std::string::npos != point_index) - { - fraction_size = str_amount.size() - point_index - 1; - while (default_decimal_point < fraction_size && '0' == str_amount.back()) - { - str_amount.erase(str_amount.size() - 1, 1); - --fraction_size; - } - if (default_decimal_point < fraction_size) - return false; - str_amount.erase(point_index, 1); - } - else - { - fraction_size = 0; - } - - if (str_amount.empty()) - return false; - - if (fraction_size < default_decimal_point) - { - str_amount.append(default_decimal_point - fraction_size, '0'); - } - - return string_tools::get_xtype_from_string(amount, str_amount); - } - //--------------------------------------------------------------- - bool get_tx_fee(const transaction& tx, uint64_t & fee) - { - if (tx.version > 1) - { - fee = tx.rct_signatures.txnFee; - return true; - } - uint64_t amount_in = 0; - uint64_t amount_out = 0; - for(auto& in: tx.vin) - { - CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key), 0, "unexpected type id in transaction"); - amount_in += boost::get(in).amount; - } - for(auto& o: tx.vout) - amount_out += o.amount; - - CHECK_AND_ASSERT_MES(amount_in >= amount_out, false, "transaction spend (" <& tx_extra, std::vector& tx_extra_fields) - { - tx_extra_fields.clear(); - - if(tx_extra.empty()) - return true; - - std::string extra_str(reinterpret_cast(tx_extra.data()), tx_extra.size()); - std::istringstream iss(extra_str); - binary_archive ar(iss); - - bool eof = false; - while (!eof) - { - tx_extra_field field; - bool r = ::do_serialize(ar, field); - CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); - tx_extra_fields.push_back(field); - - std::ios_base::iostate state = iss.rdstate(); - eof = (EOF == iss.peek()); - iss.clear(state); - } - CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); - - return true; - } - //--------------------------------------------------------------- - crypto::public_key get_tx_pub_key_from_extra(const std::vector& tx_extra, size_t pk_index) - { - std::vector tx_extra_fields; - parse_tx_extra(tx_extra, tx_extra_fields); - - tx_extra_pub_key pub_key_field; - if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index)) - return null_pkey; - - return pub_key_field.pub_key; - } - //--------------------------------------------------------------- - crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx_prefix, size_t pk_index) - { - return get_tx_pub_key_from_extra(tx_prefix.extra, pk_index); - } - //--------------------------------------------------------------- - crypto::public_key get_tx_pub_key_from_extra(const transaction& tx, size_t pk_index) - { - return get_tx_pub_key_from_extra(tx.extra, pk_index); - } - //--------------------------------------------------------------- - bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key) - { - return add_tx_pub_key_to_extra(tx.extra, tx_pub_key); - } - //--------------------------------------------------------------- - bool add_tx_pub_key_to_extra(transaction_prefix& tx, const crypto::public_key& tx_pub_key) - { - return add_tx_pub_key_to_extra(tx.extra, tx_pub_key); - } - //--------------------------------------------------------------- - bool add_tx_pub_key_to_extra(std::vector& tx_extra, const crypto::public_key& tx_pub_key) - { - tx_extra.resize(tx_extra.size() + 1 + sizeof(crypto::public_key)); - tx_extra[tx_extra.size() - 1 - sizeof(crypto::public_key)] = TX_EXTRA_TAG_PUBKEY; - *reinterpret_cast(&tx_extra[tx_extra.size() - sizeof(crypto::public_key)]) = tx_pub_key; - return true; - } - //--------------------------------------------------------------- - std::vector get_additional_tx_pub_keys_from_extra(const std::vector& tx_extra) - { - // parse - std::vector tx_extra_fields; - parse_tx_extra(tx_extra, tx_extra_fields); - // find corresponding field - tx_extra_additional_pub_keys additional_pub_keys; - if(!find_tx_extra_field_by_type(tx_extra_fields, additional_pub_keys)) - return {}; - return additional_pub_keys.data; - } - //--------------------------------------------------------------- - std::vector get_additional_tx_pub_keys_from_extra(const transaction_prefix& tx) - { - return get_additional_tx_pub_keys_from_extra(tx.extra); - } - //--------------------------------------------------------------- - bool add_additional_tx_pub_keys_to_extra(std::vector& tx_extra, const std::vector& additional_pub_keys) - { - // convert to variant - tx_extra_field field = tx_extra_additional_pub_keys{ additional_pub_keys }; - // serialize - std::ostringstream oss; - binary_archive ar(oss); - bool r = ::do_serialize(ar, field); - CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra additional tx pub keys"); - // append - std::string tx_extra_str = oss.str(); - size_t pos = tx_extra.size(); - tx_extra.resize(tx_extra.size() + tx_extra_str.size()); - memcpy(&tx_extra[pos], tx_extra_str.data(), tx_extra_str.size()); - return true; - } - //--------------------------------------------------------------- - bool add_extra_nonce_to_tx_extra(std::vector& tx_extra, const blobdata& extra_nonce) - { - CHECK_AND_ASSERT_MES(extra_nonce.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max"); - size_t start_pos = tx_extra.size(); - tx_extra.resize(tx_extra.size() + 2 + extra_nonce.size()); - //write tag - tx_extra[start_pos] = TX_EXTRA_NONCE; - //write len - ++start_pos; - tx_extra[start_pos] = static_cast(extra_nonce.size()); - //write data - ++start_pos; - memcpy(&tx_extra[start_pos], extra_nonce.data(), extra_nonce.size()); - return true; - } - //--------------------------------------------------------------- - bool remove_field_from_tx_extra(std::vector& tx_extra, const std::type_info &type) - { - if (tx_extra.empty()) - return true; - std::string extra_str(reinterpret_cast(tx_extra.data()), tx_extra.size()); - std::istringstream iss(extra_str); - binary_archive ar(iss); - std::ostringstream oss; - binary_archive newar(oss); - - bool eof = false; - while (!eof) - { - tx_extra_field field; - bool r = ::do_serialize(ar, field); - CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); - if (field.type() != type) - ::do_serialize(newar, field); - - std::ios_base::iostate state = iss.rdstate(); - eof = (EOF == iss.peek()); - iss.clear(state); - } - CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); - tx_extra.clear(); - std::string s = oss.str(); - tx_extra.reserve(s.size()); - std::copy(s.begin(), s.end(), std::back_inserter(tx_extra)); - return true; - } - //--------------------------------------------------------------- - void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id) - { - extra_nonce.clear(); - extra_nonce.push_back(TX_EXTRA_NONCE_PAYMENT_ID); - const uint8_t* payment_id_ptr = reinterpret_cast(&payment_id); - std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce)); - } - //--------------------------------------------------------------- - void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id) - { - extra_nonce.clear(); - extra_nonce.push_back(TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID); - const uint8_t* payment_id_ptr = reinterpret_cast(&payment_id); - std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce)); - } - //--------------------------------------------------------------- - bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id) - { - if(sizeof(crypto::hash) + 1 != extra_nonce.size()) - return false; - if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0]) - return false; - payment_id = *reinterpret_cast(extra_nonce.data() + 1); - return true; - } - //--------------------------------------------------------------- - bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id) - { - if(sizeof(crypto::hash8) + 1 != extra_nonce.size()) - return false; - if (TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID != extra_nonce[0]) - return false; - payment_id = *reinterpret_cast(extra_nonce.data() + 1); - return true; - } - //--------------------------------------------------------------- - bool get_inputs_money_amount(const transaction& tx, uint64_t& money) - { - money = 0; - for(const auto& in: tx.vin) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); - money += tokey_in.amount; - } - return true; - } - //--------------------------------------------------------------- - uint64_t get_block_height(const block& b) - { - CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, 0, "wrong miner tx in block: " << get_block_hash(b) << ", b.miner_tx.vin.size() != 1"); - CHECKED_GET_SPECIFIC_VARIANT(b.miner_tx.vin[0], const txin_gen, coinbase_in, 0); - return coinbase_in.height; - } - //--------------------------------------------------------------- - bool check_inputs_types_supported(const transaction& tx) - { - for(const auto& in: tx.vin) - { - CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key), false, "wrong variant type: " - << in.type().name() << ", expected " << typeid(txin_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); - - } - return true; - } - //----------------------------------------------------------------------------------------------- - bool check_outs_valid(const transaction& tx) - { - for(const tx_out& out: tx.vout) - { - CHECK_AND_ASSERT_MES(out.target.type() == typeid(txout_to_key), false, "wrong variant type: " - << out.target.type().name() << ", expected " << typeid(txout_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); - - if (tx.version == 1) - { - CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx)); - } - - if(!check_key(boost::get(out.target).key)) - return false; - } - return true; - } - //----------------------------------------------------------------------------------------------- - bool check_money_overflow(const transaction& tx) - { - return check_inputs_overflow(tx) && check_outs_overflow(tx); - } - //--------------------------------------------------------------- - bool check_inputs_overflow(const transaction& tx) - { - uint64_t money = 0; - for(const auto& in: tx.vin) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); - if(money > tokey_in.amount + money) - return false; - money += tokey_in.amount; - } - return true; - } - //--------------------------------------------------------------- - bool check_outs_overflow(const transaction& tx) - { - uint64_t money = 0; - for(const auto& o: tx.vout) - { - if(money > o.amount + money) - return false; - money += o.amount; - } - return true; - } - //--------------------------------------------------------------- - uint64_t get_outs_money_amount(const transaction& tx) - { - uint64_t outputs_amount = 0; - for(const auto& o: tx.vout) - outputs_amount += o.amount; - return outputs_amount; - } - //--------------------------------------------------------------- - std::string short_hash_str(const crypto::hash& h) - { - std::string res = string_tools::pod_to_hex(h); - CHECK_AND_ASSERT_MES(res.size() == 64, res, "wrong hash256 with string_tools::pod_to_hex conversion"); - auto erased_pos = res.erase(8, 48); - res.insert(8, "...."); - return res; - } - boost::optional is_out_to_acc_precomp(const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector& additional_derivations, size_t output_index, hw::device &hwdev) - { - // try the shared tx pubkey - crypto::public_key subaddress_spendkey; - hwdev.derive_subaddress_public_key(out_key, derivation, output_index, subaddress_spendkey); - auto found = subaddresses.find(subaddress_spendkey); - if (found != subaddresses.end()) - return subaddress_receive_info{ found->second, derivation }; - // try additional tx pubkeys if available - if (!additional_derivations.empty()) - { - CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations"); - hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey); - found = subaddresses.find(subaddress_spendkey); - if (found != subaddresses.end()) - return subaddress_receive_info{ found->second, additional_derivations[output_index] }; - } - return boost::none; - } - //--------------------------------------------------------------- - //--------------------------------------------------------------- - void get_blob_hash(const blobdata& blob, crypto::hash& res) - { - cn_fast_hash(blob.data(), blob.size(), res); - } - //--------------------------------------------------------------- - void set_default_decimal_point(unsigned int decimal_point) - { - switch (decimal_point) - { - case 12: - case 9: - case 6: - case 3: - case 0: - default_decimal_point = decimal_point; - break; - default: - ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point); - } - } - //--------------------------------------------------------------- - unsigned int get_default_decimal_point() - { - return default_decimal_point; - } - //--------------------------------------------------------------- - std::string get_unit(unsigned int decimal_point) - { - if (decimal_point == (unsigned int)-1) - decimal_point = default_decimal_point; - switch (std::atomic_load(&default_decimal_point)) - { - case 12: - return "monero"; - case 9: - return "millinero"; - case 6: - return "micronero"; - case 3: - return "nanonero"; - case 0: - return "piconero"; - default: - ASSERT_MES_AND_THROW("Invalid decimal point specification: " << default_decimal_point); - } - } - //--------------------------------------------------------------- - std::string print_money(uint64_t amount, unsigned int decimal_point) - { - if (decimal_point == (unsigned int)-1) - decimal_point = default_decimal_point; - std::string s = std::to_string(amount); - if(s.size() < decimal_point+1) - { - s.insert(0, decimal_point+1 - s.size(), '0'); - } - if (decimal_point > 0) - s.insert(s.size() - decimal_point, "."); - return s; - } - //--------------------------------------------------------------- - crypto::hash get_blob_hash(const blobdata& blob) - { - crypto::hash h = null_hash; - get_blob_hash(blob, h); - return h; - } - //--------------------------------------------------------------- - crypto::hash get_transaction_hash(const transaction& t) - { - crypto::hash h = null_hash; - get_transaction_hash(t, h, NULL); - return h; - } - //--------------------------------------------------------------- - bool get_transaction_hash(const transaction& t, crypto::hash& res) - { - return get_transaction_hash(t, res, NULL); - } - //--------------------------------------------------------------- - bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size) - { - // v1 transactions hash the entire blob - if (t.version == 1) - { - size_t ignored_blob_size, &blob_size_ref = blob_size ? *blob_size : ignored_blob_size; - return get_object_hash(t, res, blob_size_ref); - } - - // v2 transactions hash different parts together, than hash the set of those hashes - crypto::hash hashes[3]; - - // prefix - get_transaction_prefix_hash(t, hashes[0]); - - transaction &tt = const_cast(t); - - // base rct - { - std::stringstream ss; - binary_archive ba(ss); - const size_t inputs = t.vin.size(); - const size_t outputs = t.vout.size(); - bool r = tt.rct_signatures.serialize_rctsig_base(ba, inputs, outputs); - CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures base"); - cryptonote::get_blob_hash(ss.str(), hashes[1]); - } - - // prunable rct - if (t.rct_signatures.type == rct::RCTTypeNull) - { - hashes[2] = crypto::null_hash; - } - else - { - std::stringstream ss; - binary_archive ba(ss); - const size_t inputs = t.vin.size(); - const size_t outputs = t.vout.size(); - const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get(t.vin[0]).key_offsets.size() - 1 : 0; - bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin); - CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable"); - cryptonote::get_blob_hash(ss.str(), hashes[2]); - } - - // the tx hash is the hash of the 3 hashes - res = cn_fast_hash(hashes, sizeof(hashes)); - - // we still need the size - if (blob_size) - *blob_size = get_object_blobsize(t); - - return true; - } - //--------------------------------------------------------------- - bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size) - { - if (t.is_hash_valid()) - { -#ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK - CHECK_AND_ASSERT_THROW_MES(!calculate_transaction_hash(t, res, blob_size) || t.hash == res, "tx hash cash integrity failure"); -#endif - res = t.hash; - if (blob_size) - { - if (!t.is_blob_size_valid()) - { - t.blob_size = get_object_blobsize(t); - t.set_blob_size_valid(true); - } - *blob_size = t.blob_size; - } - ++tx_hashes_cached_count; - return true; - } - ++tx_hashes_calculated_count; - bool ret = calculate_transaction_hash(t, res, blob_size); - if (!ret) - return false; - t.hash = res; - t.set_hash_valid(true); - if (blob_size) - { - t.blob_size = *blob_size; - t.set_blob_size_valid(true); - } - return true; - } - //--------------------------------------------------------------- - bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size) - { - return get_transaction_hash(t, res, &blob_size); - } - //--------------------------------------------------------------- - blobdata get_block_hashing_blob(const block& b) - { - blobdata blob = t_serializable_object_to_blob(static_cast(b)); - crypto::hash tree_root_hash = get_tx_tree_hash(b); - blob.append(reinterpret_cast(&tree_root_hash), sizeof(tree_root_hash)); - blob.append(tools::get_varint_data(b.tx_hashes.size()+1)); - return blob; - } - //--------------------------------------------------------------- - bool calculate_block_hash(const block& b, crypto::hash& res) - { - // EXCEPTION FOR BLOCK 202612 - const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966"; - const std::string existing_block_id_202612 = "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698"; - crypto::hash block_blob_hash = get_blob_hash(block_to_blob(b)); - - if (string_tools::pod_to_hex(block_blob_hash) == correct_blob_hash_202612) - { - string_tools::hex_to_pod(existing_block_id_202612, res); - return true; - } - bool hash_result = get_object_hash(get_block_hashing_blob(b), res); - - if (hash_result) - { - // make sure that we aren't looking at a block with the 202612 block id but not the correct blobdata - if (string_tools::pod_to_hex(res) == existing_block_id_202612) - { - LOG_ERROR("Block with block id for 202612 but incorrect block blob hash found!"); - res = null_hash; - return false; - } - } - return hash_result; - } - //--------------------------------------------------------------- - bool get_block_hash(const block& b, crypto::hash& res) - { - if (b.is_hash_valid()) - { -#ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK - CHECK_AND_ASSERT_THROW_MES(!calculate_block_hash(b, res) || b.hash == res, "block hash cash integrity failure"); -#endif - res = b.hash; - ++block_hashes_cached_count; - return true; - } - ++block_hashes_calculated_count; - bool ret = calculate_block_hash(b, res); - if (!ret) - return false; - b.hash = res; - b.set_hash_valid(true); - return true; - } - //--------------------------------------------------------------- - crypto::hash get_block_hash(const block& b) - { - crypto::hash p = null_hash; - get_block_hash(b, p); - return p; - } - //--------------------------------------------------------------- - bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height) - { - // block 202612 bug workaround - const std::string longhash_202612 = "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000"; - if (height == 202612) - { - string_tools::hex_to_pod(longhash_202612, res); - return true; - } - blobdata bd = get_block_hashing_blob(b); - const int cn_variant = b.major_version >= 7 ? b.major_version - 6 : 0; - crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant); - return true; - } - //--------------------------------------------------------------- - std::vector relative_output_offsets_to_absolute(const std::vector& off) - { - std::vector res = off; - for(size_t i = 1; i < res.size(); i++) - res[i] += res[i-1]; - return res; - } - //--------------------------------------------------------------- - std::vector absolute_output_offsets_to_relative(const std::vector& off) - { - std::vector res = off; - if(!off.size()) - return res; - std::sort(res.begin(), res.end());//just to be sure, actually it is already should be sorted - for(size_t i = res.size()-1; i != 0; i--) - res[i] -= res[i-1]; - - return res; - } - //--------------------------------------------------------------- - crypto::hash get_block_longhash(const block& b, uint64_t height) - { - crypto::hash p = null_hash; - get_block_longhash(b, p, height); - return p; - } - //--------------------------------------------------------------- - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b) - { - std::stringstream ss; - ss << b_blob; - binary_archive ba(ss); - bool r = ::serialization::serialize(ba, b); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob"); - b.invalidate_hashes(); - b.miner_tx.invalidate_hashes(); - return true; - } - //--------------------------------------------------------------- - blobdata block_to_blob(const block& b) - { - return t_serializable_object_to_blob(b); - } - //--------------------------------------------------------------- - bool block_to_blob(const block& b, blobdata& b_blob) - { - return t_serializable_object_to_blob(b, b_blob); - } - //--------------------------------------------------------------- - blobdata tx_to_blob(const transaction& tx) - { - return t_serializable_object_to_blob(tx); - } - //--------------------------------------------------------------- - bool tx_to_blob(const transaction& tx, blobdata& b_blob) - { - return t_serializable_object_to_blob(tx, b_blob); - } - //--------------------------------------------------------------- - void get_tx_tree_hash(const std::vector& tx_hashes, crypto::hash& h) - { - tree_hash(tx_hashes.data(), tx_hashes.size(), h); - } - //--------------------------------------------------------------- - crypto::hash get_tx_tree_hash(const std::vector& tx_hashes) - { - crypto::hash h = null_hash; - get_tx_tree_hash(tx_hashes, h); - return h; - } - //--------------------------------------------------------------- - crypto::hash get_tx_tree_hash(const block& b) - { - std::vector txs_ids; - crypto::hash h = null_hash; - size_t bl_sz = 0; - get_transaction_hash(b.miner_tx, h, bl_sz); - txs_ids.push_back(h); - for(auto& th: b.tx_hashes) - txs_ids.push_back(th); - return get_tx_tree_hash(txs_ids); - } - //--------------------------------------------------------------- - bool is_valid_decomposed_amount(uint64_t amount) - { - const uint64_t *begin = valid_decomposed_outputs; - const uint64_t *end = valid_decomposed_outputs + sizeof(valid_decomposed_outputs) / sizeof(valid_decomposed_outputs[0]); - return std::binary_search(begin, end, amount); - } - //--------------------------------------------------------------- - void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t & block_hashes_cached) - { - tx_hashes_calculated = tx_hashes_calculated_count; - tx_hashes_cached = tx_hashes_cached_count; - block_hashes_calculated = block_hashes_calculated_count; - block_hashes_cached = block_hashes_cached_count; - } - //--------------------------------------------------------------- - crypto::secret_key encrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase) - { - crypto::hash hash; - crypto::cn_slow_hash(passphrase.data(), passphrase.size(), hash); - sc_add((unsigned char*)key.data, (const unsigned char*)key.data, (const unsigned char*)hash.data); - return key; - } - //--------------------------------------------------------------- - crypto::secret_key decrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase) - { - crypto::hash hash; - crypto::cn_slow_hash(passphrase.data(), passphrase.size(), hash); - sc_sub((unsigned char*)key.data, (const unsigned char*)key.data, (const unsigned char*)hash.data); - return key; - } -} diff --git a/src/Native/libcryptonote/cryptonote_basic/cryptonote_format_utils.h b/src/Native/libcryptonote/cryptonote_basic/cryptonote_format_utils.h deleted file mode 100644 index 79466e9c4..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/cryptonote_format_utils.h +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include "blobdatatype.h" -#include "cryptonote_basic_impl.h" -#include "account.h" -#include "subaddress_index.h" -#include "include_base_utils.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include - -namespace epee -{ - class wipeable_string; -} - -namespace cryptonote -{ - //--------------------------------------------------------------- - void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h); - crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx); - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx); - bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx); - - template - bool find_tx_extra_field_by_type(const std::vector& tx_extra_fields, T& field, size_t index = 0) - { - auto it = std::find_if(tx_extra_fields.begin(), tx_extra_fields.end(), [&index](const tx_extra_field& f) { return typeid(T) == f.type() && !index--; }); - if(tx_extra_fields.end() == it) - return false; - - field = boost::get(*it); - return true; - } - - bool parse_tx_extra(const std::vector& tx_extra, std::vector& tx_extra_fields); - crypto::public_key get_tx_pub_key_from_extra(const std::vector& tx_extra, size_t pk_index = 0); - crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx, size_t pk_index = 0); - crypto::public_key get_tx_pub_key_from_extra(const transaction& tx, size_t pk_index = 0); - bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key); - bool add_tx_pub_key_to_extra(transaction_prefix& tx, const crypto::public_key& tx_pub_key); - bool add_tx_pub_key_to_extra(std::vector& tx_extra, const crypto::public_key& tx_pub_key); - std::vector get_additional_tx_pub_keys_from_extra(const std::vector& tx_extra); - std::vector get_additional_tx_pub_keys_from_extra(const transaction_prefix& tx); - bool add_additional_tx_pub_keys_to_extra(std::vector& tx_extra, const std::vector& additional_pub_keys); - bool add_extra_nonce_to_tx_extra(std::vector& tx_extra, const blobdata& extra_nonce); - bool remove_field_from_tx_extra(std::vector& tx_extra, const std::type_info &type); - void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id); - void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id); - bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); - bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id); - bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector& additional_tx_public_keys, size_t output_index); - struct subaddress_receive_info - { - subaddress_index index; - crypto::key_derivation derivation; - }; - boost::optional is_out_to_acc_precomp(const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector& additional_derivations, size_t output_index, hw::device &hwdev); - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, const std::vector& additional_tx_public_keys, std::vector& outs, uint64_t& money_transfered); - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered); - bool get_tx_fee(const transaction& tx, uint64_t & fee); - uint64_t get_tx_fee(const transaction& tx); - bool generate_key_image_helper(const account_keys& ack, const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); - bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); - void get_blob_hash(const blobdata& blob, crypto::hash& res); - crypto::hash get_blob_hash(const blobdata& blob); - std::string short_hash_str(const crypto::hash& h); - - crypto::hash get_transaction_hash(const transaction& t); - bool get_transaction_hash(const transaction& t, crypto::hash& res); - bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size); - bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size); - bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size); - blobdata get_block_hashing_blob(const block& b); - bool calculate_block_hash(const block& b, crypto::hash& res); - bool get_block_hash(const block& b, crypto::hash& res); - crypto::hash get_block_hash(const block& b); - bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height); - crypto::hash get_block_longhash(const block& b, uint64_t height); - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b); - bool get_inputs_money_amount(const transaction& tx, uint64_t& money); - uint64_t get_outs_money_amount(const transaction& tx); - bool check_inputs_types_supported(const transaction& tx); - bool check_outs_valid(const transaction& tx); - bool parse_amount(uint64_t& amount, const std::string& str_amount); - - bool check_money_overflow(const transaction& tx); - bool check_outs_overflow(const transaction& tx); - bool check_inputs_overflow(const transaction& tx); - uint64_t get_block_height(const block& b); - std::vector relative_output_offsets_to_absolute(const std::vector& off); - std::vector absolute_output_offsets_to_relative(const std::vector& off); - void set_default_decimal_point(unsigned int decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT); - unsigned int get_default_decimal_point(); - std::string get_unit(unsigned int decimal_point = -1); - std::string print_money(uint64_t amount, unsigned int decimal_point = -1); - //--------------------------------------------------------------- - template - bool t_serializable_object_to_blob(const t_object& to, blobdata& b_blob) - { - std::stringstream ss; - binary_archive ba(ss); - bool r = ::serialization::serialize(ba, const_cast(to)); - b_blob = ss.str(); - return r; - } - //--------------------------------------------------------------- - template - blobdata t_serializable_object_to_blob(const t_object& to) - { - blobdata b; - t_serializable_object_to_blob(to, b); - return b; - } - //--------------------------------------------------------------- - template - bool get_object_hash(const t_object& o, crypto::hash& res) - { - get_blob_hash(t_serializable_object_to_blob(o), res); - return true; - } - //--------------------------------------------------------------- - template - size_t get_object_blobsize(const t_object& o) - { - blobdata b = t_serializable_object_to_blob(o); - return b.size(); - } - //--------------------------------------------------------------- - template - bool get_object_hash(const t_object& o, crypto::hash& res, size_t& blob_size) - { - blobdata bl = t_serializable_object_to_blob(o); - blob_size = bl.size(); - get_blob_hash(bl, res); - return true; - } - //--------------------------------------------------------------- - template - std::string obj_to_json_str(T& obj) - { - std::stringstream ss; - json_archive ar(ss, true); - bool r = ::serialization::serialize(ar, obj); - CHECK_AND_ASSERT_MES(r, "", "obj_to_json_str failed: serialization::serialize returned false"); - return ss.str(); - } - //--------------------------------------------------------------- - // 62387455827 -> 455827 + 7000000 + 80000000 + 300000000 + 2000000000 + 60000000000, where 455827 <= dust_threshold - template - void decompose_amount_into_digits(uint64_t amount, uint64_t dust_threshold, const chunk_handler_t& chunk_handler, const dust_handler_t& dust_handler) - { - if (0 == amount) - { - return; - } - - bool is_dust_handled = false; - uint64_t dust = 0; - uint64_t order = 1; - while (0 != amount) - { - uint64_t chunk = (amount % 10) * order; - amount /= 10; - order *= 10; - - if (dust + chunk <= dust_threshold) - { - dust += chunk; - } - else - { - if (!is_dust_handled && 0 != dust) - { - dust_handler(dust); - is_dust_handled = true; - } - if (0 != chunk) - { - chunk_handler(chunk); - } - } - } - - if (!is_dust_handled && 0 != dust) - { - dust_handler(dust); - } - } - //--------------------------------------------------------------- - blobdata block_to_blob(const block& b); - bool block_to_blob(const block& b, blobdata& b_blob); - blobdata tx_to_blob(const transaction& b); - bool tx_to_blob(const transaction& b, blobdata& b_blob); - void get_tx_tree_hash(const std::vector& tx_hashes, crypto::hash& h); - crypto::hash get_tx_tree_hash(const std::vector& tx_hashes); - crypto::hash get_tx_tree_hash(const block& b); - bool is_valid_decomposed_amount(uint64_t amount); - void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t & block_hashes_cached); - - crypto::secret_key encrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase); - crypto::secret_key decrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase); -#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \ - CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \ - specific_type& variable_name = boost::get(variant_var); -} diff --git a/src/Native/libcryptonote/cryptonote_basic/cryptonote_stat_info.h b/src/Native/libcryptonote/cryptonote_basic/cryptonote_stat_info.h deleted file mode 100644 index c0be2144e..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/cryptonote_stat_info.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include "serialization/keyvalue_serialization.h" - - -namespace cryptonote -{ - struct core_stat_info - { - uint64_t tx_pool_size; - uint64_t blockchain_height; - uint64_t mining_speed; - uint64_t alternative_blocks; - std::string top_block_id_str; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_pool_size) - KV_SERIALIZE(blockchain_height) - KV_SERIALIZE(mining_speed) - KV_SERIALIZE(alternative_blocks) - KV_SERIALIZE(top_block_id_str) - END_KV_SERIALIZE_MAP() - }; -} diff --git a/src/Native/libcryptonote/cryptonote_basic/difficulty.cpp b/src/Native/libcryptonote/cryptonote_basic/difficulty.cpp deleted file mode 100644 index cb2a00a12..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/difficulty.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include -#include -#include -#include - -#include "common/int-util.h" -#include "crypto/hash.h" -#include "cryptonote_config.h" -#include "difficulty.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "difficulty" - -namespace cryptonote { - - using std::size_t; - using std::uint64_t; - using std::vector; - -#if defined(__x86_64__) - static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - low = mul128(a, b, &high); - } - -#else - - static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - // __int128 isn't part of the standard, so the previous function wasn't portable. mul128() in Windows is fine, - // but this portable function should be used elsewhere. Credit for this function goes to latexi95. - - uint64_t aLow = a & 0xFFFFFFFF; - uint64_t aHigh = a >> 32; - uint64_t bLow = b & 0xFFFFFFFF; - uint64_t bHigh = b >> 32; - - uint64_t res = aLow * bLow; - uint64_t lowRes1 = res & 0xFFFFFFFF; - uint64_t carry = res >> 32; - - res = aHigh * bLow + carry; - uint64_t highResHigh1 = res >> 32; - uint64_t highResLow1 = res & 0xFFFFFFFF; - - res = aLow * bHigh; - uint64_t lowRes2 = res & 0xFFFFFFFF; - carry = res >> 32; - - res = aHigh * bHigh + carry; - uint64_t highResHigh2 = res >> 32; - uint64_t highResLow2 = res & 0xFFFFFFFF; - - //Addition - - uint64_t r = highResLow1 + lowRes2; - carry = r >> 32; - low = (r << 32) | lowRes1; - r = highResHigh1 + highResLow2 + carry; - uint64_t d3 = r & 0xFFFFFFFF; - carry = r >> 32; - r = highResHigh2 + carry; - high = d3 | (r << 32); - } - -#endif - - static inline bool cadd(uint64_t a, uint64_t b) { - return a + b < a; - } - - static inline bool cadc(uint64_t a, uint64_t b, bool c) { - return a + b < a || (c && a + b == (uint64_t) -1); - } - - bool check_hash(const crypto::hash &hash, difficulty_type difficulty) { - uint64_t low, high, top, cur; - // First check the highest word, this will most likely fail for a random hash. - mul(swap64le(((const uint64_t *) &hash)[3]), difficulty, top, high); - if (high != 0) { - return false; - } - mul(swap64le(((const uint64_t *) &hash)[0]), difficulty, low, cur); - mul(swap64le(((const uint64_t *) &hash)[1]), difficulty, low, high); - bool carry = cadd(cur, low); - cur = high; - mul(swap64le(((const uint64_t *) &hash)[2]), difficulty, low, high); - carry = cadc(cur, low, carry); - carry = cadc(high, top, carry); - return !carry; - } - - difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds) { - - if(timestamps.size() > DIFFICULTY_WINDOW) - { - timestamps.resize(DIFFICULTY_WINDOW); - cumulative_difficulties.resize(DIFFICULTY_WINDOW); - } - - - size_t length = timestamps.size(); - assert(length == cumulative_difficulties.size()); - if (length <= 1) { - return 1; - } - static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small"); - assert(length <= DIFFICULTY_WINDOW); - sort(timestamps.begin(), timestamps.end()); - size_t cut_begin, cut_end; - static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large"); - if (length <= DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) { - cut_begin = 0; - cut_end = length; - } else { - cut_begin = (length - (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) + 1) / 2; - cut_end = cut_begin + (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT); - } - assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length); - uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin]; - if (time_span == 0) { - time_span = 1; - } - difficulty_type total_work = cumulative_difficulties[cut_end - 1] - cumulative_difficulties[cut_begin]; - assert(total_work > 0); - uint64_t low, high; - mul(total_work, target_seconds, low, high); - // blockchain errors "difficulty overhead" if this function returns zero. - // TODO: consider throwing an exception instead - if (high != 0 || low + time_span - 1 < low) { - return 0; - } - return (low + time_span - 1) / time_span; - } - -} diff --git a/src/Native/libcryptonote/cryptonote_basic/difficulty.h b/src/Native/libcryptonote/cryptonote_basic/difficulty.h deleted file mode 100644 index b06538467..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/difficulty.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include -#include - -#include "crypto/hash.h" - -namespace cryptonote -{ - typedef std::uint64_t difficulty_type; - - /** - * @brief checks if a hash fits the given difficulty - * - * The hash passes if (hash * difficulty) < 2^256. - * Phrased differently, if (hash * difficulty) fits without overflow into - * the least significant 256 bits of the 320 bit multiplication result. - * - * @param hash the hash to check - * @param difficulty the difficulty to check against - * - * @return true if valid, else false - */ - bool check_hash(const crypto::hash &hash, difficulty_type difficulty); - difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds); -} diff --git a/src/Native/libcryptonote/cryptonote_basic/hardfork.cpp b/src/Native/libcryptonote/cryptonote_basic/hardfork.cpp deleted file mode 100644 index 95f1ecab9..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/hardfork.cpp +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include - -#include "cryptonote_basic/cryptonote_basic.h" -#include "blockchain_db/blockchain_db.h" -#include "hardfork.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "hardfork" - -using namespace cryptonote; - -static uint8_t get_block_vote(const cryptonote::block &b) -{ - // Pre-hardfork blocks have a minor version hardcoded to 0. - // For the purposes of voting, we consider 0 to refer to - // version number 1, which is what all blocks from the genesis - // block are. It makes things simpler. - if (b.minor_version == 0) - return 1; - return b.minor_version; -} - -static uint8_t get_block_version(const cryptonote::block &b) -{ - return b.major_version; -} - -HardFork::HardFork(cryptonote::BlockchainDB &db, uint8_t original_version, uint64_t original_version_till_height, time_t forked_time, time_t update_time, uint64_t window_size, uint8_t default_threshold_percent): - db(db), - original_version(original_version), - original_version_till_height(original_version_till_height), - forked_time(forked_time), - update_time(update_time), - window_size(window_size), - default_threshold_percent(default_threshold_percent) -{ - if (window_size == 0) - throw "window_size needs to be strictly positive"; - if (default_threshold_percent > 100) - throw "default_threshold_percent needs to be between 0 and 100"; -} - -bool HardFork::add_fork(uint8_t version, uint64_t height, uint8_t threshold, time_t time) -{ - CRITICAL_REGION_LOCAL(lock); - - // add in order - if (version == 0) - return false; - if (!heights.empty()) { - if (version <= heights.back().version) - return false; - if (height <= heights.back().height) - return false; - if (time <= heights.back().time) - return false; - } - if (threshold > 100) - return false; - heights.push_back(Params(version, height, threshold, time)); - return true; -} - -bool HardFork::add_fork(uint8_t version, uint64_t height, time_t time) -{ - return add_fork(version, height, default_threshold_percent, time); -} - -uint8_t HardFork::get_effective_version(uint8_t voting_version) const -{ - if (!heights.empty()) { - uint8_t max_version = heights.back().version; - if (voting_version > max_version) - voting_version = max_version; - } - return voting_version; -} - -bool HardFork::do_check(uint8_t block_version, uint8_t voting_version) const -{ - return block_version == heights[current_fork_index].version - && voting_version >= heights[current_fork_index].version; -} - -bool HardFork::check(const cryptonote::block &block) const -{ - CRITICAL_REGION_LOCAL(lock); - return do_check(::get_block_version(block), ::get_block_vote(block)); -} - -bool HardFork::do_check_for_height(uint8_t block_version, uint8_t voting_version, uint64_t height) const -{ - int fork_index = get_voted_fork_index(height); - return block_version == heights[fork_index].version - && voting_version >= heights[fork_index].version; -} - -bool HardFork::check_for_height(const cryptonote::block &block, uint64_t height) const -{ - CRITICAL_REGION_LOCAL(lock); - return do_check_for_height(::get_block_version(block), ::get_block_vote(block), height); -} - -bool HardFork::add(uint8_t block_version, uint8_t voting_version, uint64_t height) -{ - CRITICAL_REGION_LOCAL(lock); - - if (!do_check(block_version, voting_version)) - return false; - - db.set_hard_fork_version(height, heights[current_fork_index].version); - - voting_version = get_effective_version(voting_version); - - while (versions.size() >= window_size) { - const uint8_t old_version = versions.front(); - assert(last_versions[old_version] >= 1); - last_versions[old_version]--; - versions.pop_front(); - } - - last_versions[voting_version]++; - versions.push_back(voting_version); - - uint8_t voted = get_voted_fork_index(height + 1); - if (voted > current_fork_index) { - current_fork_index = voted; - } - - return true; -} - -bool HardFork::add(const cryptonote::block &block, uint64_t height) -{ - return add(::get_block_version(block), ::get_block_vote(block), height); -} - -void HardFork::init() -{ - CRITICAL_REGION_LOCAL(lock); - - // add a placeholder for the default version, to avoid special cases - if (heights.empty()) - heights.push_back(Params(original_version, 0, 0, 0)); - - versions.clear(); - for (size_t n = 0; n < 256; ++n) - last_versions[n] = 0; - current_fork_index = 0; - - // restore state from DB - uint64_t height = db.height(); - if (height > window_size) - height -= window_size - 1; - else - height = 1; - - bool populate = false; - try - { - db.get_hard_fork_version(0); - } - catch (...) { populate = true; } - if (populate) { - MINFO("The DB has no hard fork info, reparsing from start"); - height = 1; - } - MDEBUG("reorganizing from " << height); - if (populate) { - reorganize_from_chain_height(height); - // reorg will not touch the genesis block, use this as a flag for populating done - db.set_hard_fork_version(0, original_version); - } - else { - rescan_from_chain_height(height); - } - MDEBUG("reorganization done"); -} - -uint8_t HardFork::get_block_version(uint64_t height) const -{ - if (height <= original_version_till_height) - return original_version; - - const cryptonote::block &block = db.get_block_from_height(height); - return ::get_block_version(block); -} - -bool HardFork::reorganize_from_block_height(uint64_t height) -{ - CRITICAL_REGION_LOCAL(lock); - if (height >= db.height()) - return false; - - db.set_batch_transactions(true); - bool stop_batch = db.batch_start(); - - versions.clear(); - - for (size_t n = 0; n < 256; ++n) - last_versions[n] = 0; - const uint64_t rescan_height = height >= (window_size - 1) ? height - (window_size -1) : 0; - const uint8_t start_version = height == 0 ? original_version : db.get_hard_fork_version(height); - while (current_fork_index > 0 && heights[current_fork_index].version > start_version) { - --current_fork_index; - } - for (uint64_t h = rescan_height; h <= height; ++h) { - cryptonote::block b = db.get_block_from_height(h); - const uint8_t v = get_effective_version(get_block_vote(b)); - last_versions[v]++; - versions.push_back(v); - } - - uint8_t voted = get_voted_fork_index(height + 1); - if (voted > current_fork_index) { - current_fork_index = voted; - } - - const uint64_t bc_height = db.height(); - for (uint64_t h = height + 1; h < bc_height; ++h) { - add(db.get_block_from_height(h), h); - } - - if (stop_batch) - db.batch_stop(); - - return true; -} - -bool HardFork::reorganize_from_chain_height(uint64_t height) -{ - if (height == 0) - return false; - return reorganize_from_block_height(height - 1); -} - -bool HardFork::rescan_from_block_height(uint64_t height) -{ - CRITICAL_REGION_LOCAL(lock); - db.block_txn_start(true); - if (height >= db.height()) { - db.block_txn_stop(); - return false; - } - - versions.clear(); - - for (size_t n = 0; n < 256; ++n) - last_versions[n] = 0; - for (uint64_t h = height; h < db.height(); ++h) { - cryptonote::block b = db.get_block_from_height(h); - const uint8_t v = get_effective_version(get_block_vote(b)); - last_versions[v]++; - versions.push_back(v); - } - - uint8_t lastv = db.get_hard_fork_version(db.height() - 1); - current_fork_index = 0; - while (current_fork_index + 1 < heights.size() && heights[current_fork_index].version != lastv) - ++current_fork_index; - - uint8_t voted = get_voted_fork_index(db.height()); - if (voted > current_fork_index) { - current_fork_index = voted; - } - - db.block_txn_stop(); - - return true; -} - -bool HardFork::rescan_from_chain_height(uint64_t height) -{ - if (height == 0) - return false; - return rescan_from_block_height(height - 1); -} - -int HardFork::get_voted_fork_index(uint64_t height) const -{ - CRITICAL_REGION_LOCAL(lock); - uint32_t accumulated_votes = 0; - for (unsigned int n = heights.size() - 1; n > current_fork_index; --n) { - uint8_t v = heights[n].version; - accumulated_votes += last_versions[v]; - uint32_t threshold = (window_size * heights[n].threshold + 99) / 100; - if (height >= heights[n].height && accumulated_votes >= threshold) { - return n; - } - } - return current_fork_index; -} - -HardFork::State HardFork::get_state(time_t t) const -{ - CRITICAL_REGION_LOCAL(lock); - - // no hard forks setup yet - if (heights.size() <= 1) - return Ready; - - time_t t_last_fork = heights.back().time; - if (t >= t_last_fork + forked_time) - return LikelyForked; - if (t >= t_last_fork + update_time) - return UpdateNeeded; - return Ready; -} - -HardFork::State HardFork::get_state() const -{ - return get_state(time(NULL)); -} - -uint8_t HardFork::get(uint64_t height) const -{ - CRITICAL_REGION_LOCAL(lock); - if (height > db.height()) { - assert(false); - return 255; - } - if (height == db.height()) { - return get_current_version(); - } - return db.get_hard_fork_version(height); -} - -uint8_t HardFork::get_current_version() const -{ - CRITICAL_REGION_LOCAL(lock); - return heights[current_fork_index].version; -} - -uint8_t HardFork::get_ideal_version() const -{ - CRITICAL_REGION_LOCAL(lock); - return heights.back().version; -} - -uint8_t HardFork::get_ideal_version(uint64_t height) const -{ - CRITICAL_REGION_LOCAL(lock); - for (unsigned int n = heights.size() - 1; n > 0; --n) { - if (height >= heights[n].height) { - return heights[n].version; - } - } - return original_version; -} - -uint64_t HardFork::get_earliest_ideal_height_for_version(uint8_t version) const -{ - for (unsigned int n = heights.size() - 1; n > 0; --n) { - if (heights[n].version <= version) - return heights[n].height; - } - return 0; -} - -uint8_t HardFork::get_next_version() const -{ - CRITICAL_REGION_LOCAL(lock); - uint64_t height = db.height(); - for (unsigned int n = heights.size() - 1; n > 0; --n) { - if (height >= heights[n].height) { - return heights[n < heights.size() - 1 ? n + 1 : n].version; - } - } - return original_version; -} - -bool HardFork::get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const -{ - CRITICAL_REGION_LOCAL(lock); - - const uint8_t current_version = heights[current_fork_index].version; - const bool enabled = current_version >= version; - window = versions.size(); - votes = 0; - for (size_t n = version; n < 256; ++n) - votes += last_versions[n]; - threshold = (window * heights[current_fork_index].threshold + 99) / 100; - //assert((votes >= threshold) == enabled); - earliest_height = get_earliest_ideal_height_for_version(version); - voting = heights.back().version; - return enabled; -} - diff --git a/src/Native/libcryptonote/cryptonote_basic/hardfork.h b/src/Native/libcryptonote/cryptonote_basic/hardfork.h deleted file mode 100644 index ee5ec0596..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/hardfork.h +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "syncobj.h" -#include "cryptonote_basic/cryptonote_basic.h" - -namespace cryptonote -{ - class BlockchainDB; - - class HardFork - { - public: - typedef enum { - LikelyForked, - UpdateNeeded, - Ready, - } State; - - static const uint64_t DEFAULT_ORIGINAL_VERSION_TILL_HEIGHT = 0; // <= actual height - static const time_t DEFAULT_FORKED_TIME = 31557600; // a year in seconds - static const time_t DEFAULT_UPDATE_TIME = 31557600 / 2; - static const uint64_t DEFAULT_WINDOW_SIZE = 10080; // supermajority window check length - a week - static const uint8_t DEFAULT_THRESHOLD_PERCENT = 80; - - /** - * @brief creates a new HardFork object - * - * @param original_version the block version for blocks 0 through to the first fork - * @param forked_time the time in seconds before thinking we're forked - * @param update_time the time in seconds before thinking we need to update - * @param window_size the size of the window in blocks to consider for version voting - * @param default_threshold_percent the size of the majority in percents - */ - HardFork(cryptonote::BlockchainDB &db, uint8_t original_version = 1, uint64_t original_version_till_height = DEFAULT_ORIGINAL_VERSION_TILL_HEIGHT, time_t forked_time = DEFAULT_FORKED_TIME, time_t update_time = DEFAULT_UPDATE_TIME, uint64_t window_size = DEFAULT_WINDOW_SIZE, uint8_t default_threshold_percent = DEFAULT_THRESHOLD_PERCENT); - - /** - * @brief add a new hardfork height - * - * returns true if no error, false otherwise - * - * @param version the major block version for the fork - * @param height The height the hardfork takes effect - * @param threshold The threshold of votes needed for this fork (0-100) - * @param time Approximate time of the hardfork (seconds since epoch) - */ - bool add_fork(uint8_t version, uint64_t height, uint8_t threshold, time_t time); - - /** - * @brief add a new hardfork height - * - * returns true if no error, false otherwise - * - * @param version the major block version for the fork - * @param height The height the hardfork takes effect - * @param time Approximate time of the hardfork (seconds since epoch) - */ - bool add_fork(uint8_t version, uint64_t height, time_t time); - - /** - * @brief initialize the object - * - * Must be done after adding all the required hardforks via add above - */ - void init(); - - /** - * @brief check whether a new block would be accepted - * - * returns true if the block is accepted, false otherwise - * - * @param block the new block - * - * This check is made by add. It is exposed publicly to allow - * the caller to inexpensively check whether a block would be - * accepted or rejected by its version number. Indeed, if this - * check could only be done as part of add, the caller would - * either have to add the block to the blockchain first, then - * call add, then have to pop the block from the blockchain if - * its version did not satisfy the hard fork requirements, or - * call add first, then, if the hard fork requirements are met, - * add the block to the blockchain, upon which a failure (the - * block being invalid, double spending, etc) would cause the - * hardfork object to reorganize. - */ - bool check(const cryptonote::block &block) const; - - /** - * @brief same as check, but for a particular height, rather than the top - * - * NOTE: this does not play well with voting, and relies on voting to be - * disabled (that is, forks happen on the scheduled date, whether or not - * enough blocks have voted for the fork). - * - * returns true if no error, false otherwise - * - * @param block the new block - * @param height which height to check for - */ - bool check_for_height(const cryptonote::block &block, uint64_t height) const; - - /** - * @brief add a new block - * - * returns true if no error, false otherwise - * - * @param block the new block - */ - bool add(const cryptonote::block &block, uint64_t height); - - /** - * @brief called when the blockchain is reorganized - * - * This will rescan the blockchain to determine which hard forks - * have been triggered - * - * returns true if no error, false otherwise - * - * @param blockchain the blockchain - * @param height of the last block kept from the previous blockchain - */ - bool reorganize_from_block_height(uint64_t height); - bool reorganize_from_chain_height(uint64_t height); - - /** - * @brief returns current state at the given time - * - * Based on the approximate time of the last known hard fork, - * estimate whether we need to update, or if we're way behind - * - * @param t the time to consider - */ - State get_state(time_t t) const; - State get_state() const; - - /** - * @brief returns the hard fork version for the given block height - * - * @param height height of the block to check - */ - uint8_t get(uint64_t height) const; - - /** - * @brief returns the latest "ideal" version - * - * This is the latest version that's been scheduled - */ - uint8_t get_ideal_version() const; - - /** - * @brief returns the "ideal" version for a given height - * - * @param height height of the block to check - */ - uint8_t get_ideal_version(uint64_t height) const; - - /** - * @brief returns the next version - * - * This is the version which will we fork to next - */ - uint8_t get_next_version() const; - - /** - * @brief returns the current version - * - * This is the latest version that's past its trigger date and had enough votes - * at one point in the past. - */ - uint8_t get_current_version() const; - - /** - * @brief returns the earliest block a given version may activate - */ - uint64_t get_earliest_ideal_height_for_version(uint8_t version) const; - - /** - * @brief returns information about current voting state - * - * returns true if the given version is enabled (ie, the current version - * is at least the passed version), false otherwise - * - * @param version the version to check voting for - * @param window the number of blocks considered in voting - * @param votes number of votes for next version - * @param threshold number of votes needed to switch to next version - * @param earliest_height earliest height at which the version can take effect - */ - bool get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const; - - /** - * @brief returns the size of the voting window in blocks - */ - uint64_t get_window_size() const { return window_size; } - - private: - - uint8_t get_block_version(uint64_t height) const; - bool do_check(uint8_t block_version, uint8_t voting_version) const; - bool do_check_for_height(uint8_t block_version, uint8_t voting_version, uint64_t height) const; - int get_voted_fork_index(uint64_t height) const; - uint8_t get_effective_version(uint8_t voting_version) const; - bool add(uint8_t block_version, uint8_t voting_version, uint64_t height); - - bool rescan_from_block_height(uint64_t height); - bool rescan_from_chain_height(uint64_t height); - - private: - - BlockchainDB &db; - - time_t forked_time; - time_t update_time; - uint64_t window_size; - uint8_t default_threshold_percent; - - uint8_t original_version; - uint64_t original_version_till_height; - - struct Params { - uint8_t version; - uint8_t threshold; - uint64_t height; - time_t time; - Params(uint8_t version, uint64_t height, uint8_t threshold, time_t time): version(version), threshold(threshold), height(height), time(time) {} - }; - std::vector heights; - - std::deque versions; /* rolling window of the last N blocks' versions */ - unsigned int last_versions[256]; /* count of the block versions in the last N blocks */ - uint32_t current_fork_index; - - mutable epee::critical_section lock; - }; - -} // namespace cryptonote - diff --git a/src/Native/libcryptonote/cryptonote_basic/miner.cpp b/src/Native/libcryptonote/cryptonote_basic/miner.cpp deleted file mode 100644 index f949bbd2b..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/miner.cpp +++ /dev/null @@ -1,1037 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include -#include -#include -#include -#include -#include -#include "include_base_utils.h" -#include "misc_language.h" -#include "syncobj.h" -#include "cryptonote_basic_impl.h" -#include "cryptonote_format_utils.h" -#include "file_io_utils.h" -#include "common/command_line.h" -#include "string_coding.h" -#include "string_tools.h" -#include "storages/portable_storage_template_helper.h" -#include "boost/logic/tribool.hpp" - -#ifdef __APPLE__ - #include - #include - #include - #include - #include - #include - #include -#endif - -#ifdef __FreeBSD__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "miner" - -using namespace epee; - -#include "miner.h" - - -extern "C" void slow_hash_allocate_state(); -extern "C" void slow_hash_free_state(); -namespace cryptonote -{ - - namespace - { - const command_line::arg_descriptor arg_extra_messages = {"extra-messages-file", "Specify file for extra messages to include into coinbase transactions", "", true}; - const command_line::arg_descriptor arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true}; - const command_line::arg_descriptor arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true}; - const command_line::arg_descriptor arg_bg_mining_enable = {"bg-mining-enable", "enable/disable background mining", true, true}; - const command_line::arg_descriptor arg_bg_mining_ignore_battery = {"bg-mining-ignore-battery", "if true, assumes plugged in when unable to query system power status", false, true}; - const command_line::arg_descriptor arg_bg_mining_min_idle_interval_seconds = {"bg-mining-min-idle-interval", "Specify min lookback interval in seconds for determining idle state", miner::BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS, true}; - const command_line::arg_descriptor arg_bg_mining_idle_threshold_percentage = {"bg-mining-idle-threshold", "Specify minimum avg idle percentage over lookback interval", miner::BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE, true}; - const command_line::arg_descriptor arg_bg_mining_miner_target_percentage = {"bg-mining-miner-target", "Specificy maximum percentage cpu use by miner(s)", miner::BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE, true}; - } - - - miner::miner(i_miner_handler* phandler):m_stop(1), - m_template(boost::value_initialized()), - m_template_no(0), - m_diffic(0), - m_thread_index(0), - m_phandler(phandler), - m_height(0), - m_pausers_count(0), - m_threads_total(0), - m_starter_nonce(0), - m_last_hr_merge_time(0), - m_hashes(0), - m_do_print_hashrate(false), - m_do_mining(false), - m_current_hash_rate(0), - m_is_background_mining_enabled(false), - m_min_idle_seconds(BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS), - m_idle_threshold(BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE), - m_mining_target(BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE), - m_miner_extra_sleep(BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS) - { - - } - //----------------------------------------------------------------------------------------------------- - miner::~miner() - { - stop(); - } - //----------------------------------------------------------------------------------------------------- - bool miner::set_block_template(const block& bl, const difficulty_type& di, uint64_t height) - { - CRITICAL_REGION_LOCAL(m_template_lock); - m_template = bl; - m_diffic = di; - m_height = height; - ++m_template_no; - m_starter_nonce = crypto::rand(); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::on_block_chain_update() - { - if(!is_mining()) - return true; - - return request_block_template(); - } - //----------------------------------------------------------------------------------------------------- - bool miner::request_block_template() - { - block bl = AUTO_VAL_INIT(bl); - difficulty_type di = AUTO_VAL_INIT(di); - uint64_t height = AUTO_VAL_INIT(height); - uint64_t expected_reward; //only used for RPC calls - could possibly be useful here too? - - cryptonote::blobdata extra_nonce; - if(m_extra_messages.size() && m_config.current_extra_message_index < m_extra_messages.size()) - { - extra_nonce = m_extra_messages[m_config.current_extra_message_index]; - } - - if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce)) - { - LOG_ERROR("Failed to get_block_template(), stopping mining"); - return false; - } - set_block_template(bl, di, height); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::on_idle() - { - m_update_block_template_interval.do_call([&](){ - if(is_mining())request_block_template(); - return true; - }); - - m_update_merge_hr_interval.do_call([&](){ - merge_hr(); - return true; - }); - - return true; - } - //----------------------------------------------------------------------------------------------------- - void miner::do_print_hashrate(bool do_hr) - { - m_do_print_hashrate = do_hr; - } - //----------------------------------------------------------------------------------------------------- - void miner::merge_hr() - { - if(m_last_hr_merge_time && is_mining()) - { - m_current_hash_rate = m_hashes * 1000 / ((misc_utils::get_tick_count() - m_last_hr_merge_time + 1)); - CRITICAL_REGION_LOCAL(m_last_hash_rates_lock); - m_last_hash_rates.push_back(m_current_hash_rate); - if(m_last_hash_rates.size() > 19) - m_last_hash_rates.pop_front(); - if(m_do_print_hashrate) - { - uint64_t total_hr = std::accumulate(m_last_hash_rates.begin(), m_last_hash_rates.end(), 0); - float hr = static_cast(total_hr)/static_cast(m_last_hash_rates.size()); - const auto precision = std::cout.precision(); - std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << precision << ENDL; - } - } - m_last_hr_merge_time = misc_utils::get_tick_count(); - m_hashes = 0; - } - //----------------------------------------------------------------------------------------------------- - void miner::init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, arg_extra_messages); - command_line::add_arg(desc, arg_start_mining); - command_line::add_arg(desc, arg_mining_threads); - command_line::add_arg(desc, arg_bg_mining_enable); - command_line::add_arg(desc, arg_bg_mining_ignore_battery); - command_line::add_arg(desc, arg_bg_mining_min_idle_interval_seconds); - command_line::add_arg(desc, arg_bg_mining_idle_threshold_percentage); - command_line::add_arg(desc, arg_bg_mining_miner_target_percentage); - } - //----------------------------------------------------------------------------------------------------- - bool miner::init(const boost::program_options::variables_map& vm, network_type nettype) - { - if(command_line::has_arg(vm, arg_extra_messages)) - { - std::string buff; - bool r = file_io_utils::load_file_to_string(command_line::get_arg(vm, arg_extra_messages), buff); - CHECK_AND_ASSERT_MES(r, false, "Failed to load file with extra messages: " << command_line::get_arg(vm, arg_extra_messages)); - std::vector extra_vec; - boost::split(extra_vec, buff, boost::is_any_of("\n"), boost::token_compress_on ); - m_extra_messages.resize(extra_vec.size()); - for(size_t i = 0; i != extra_vec.size(); i++) - { - string_tools::trim(extra_vec[i]); - if(!extra_vec[i].size()) - continue; - std::string buff = string_encoding::base64_decode(extra_vec[i]); - if(buff != "0") - m_extra_messages[i] = buff; - } - m_config_folder_path = boost::filesystem::path(command_line::get_arg(vm, arg_extra_messages)).parent_path().string(); - m_config = AUTO_VAL_INIT(m_config); - epee::serialization::load_t_from_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME); - MINFO("Loaded " << m_extra_messages.size() << " extra messages, current index " << m_config.current_extra_message_index); - } - - if(command_line::has_arg(vm, arg_start_mining)) - { - address_parse_info info; - if(!cryptonote::get_account_address_from_str(info, nettype, command_line::get_arg(vm, arg_start_mining)) || info.is_subaddress) - { - LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled"); - return false; - } - m_mine_address = info.address; - m_threads_total = 1; - m_do_mining = true; - if(command_line::has_arg(vm, arg_mining_threads)) - { - m_threads_total = command_line::get_arg(vm, arg_mining_threads); - } - } - - // Background mining parameters - // Let init set all parameters even if background mining is not enabled, they can start later with params set - if(command_line::has_arg(vm, arg_bg_mining_enable)) - set_is_background_mining_enabled( command_line::get_arg(vm, arg_bg_mining_enable) ); - if(command_line::has_arg(vm, arg_bg_mining_ignore_battery)) - set_ignore_battery( command_line::get_arg(vm, arg_bg_mining_ignore_battery) ); - if(command_line::has_arg(vm, arg_bg_mining_min_idle_interval_seconds)) - set_min_idle_seconds( command_line::get_arg(vm, arg_bg_mining_min_idle_interval_seconds) ); - if(command_line::has_arg(vm, arg_bg_mining_idle_threshold_percentage)) - set_idle_threshold( command_line::get_arg(vm, arg_bg_mining_idle_threshold_percentage) ); - if(command_line::has_arg(vm, arg_bg_mining_miner_target_percentage)) - set_mining_target( command_line::get_arg(vm, arg_bg_mining_miner_target_percentage) ); - - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::is_mining() const - { - return !m_stop; - } - //----------------------------------------------------------------------------------------------------- - const account_public_address& miner::get_mining_address() const - { - return m_mine_address; - } - //----------------------------------------------------------------------------------------------------- - uint32_t miner::get_threads_count() const { - return m_threads_total; - } - //----------------------------------------------------------------------------------------------------- - bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background, bool ignore_battery) - { - m_mine_address = adr; - m_threads_total = static_cast(threads_count); - m_starter_nonce = crypto::rand(); - CRITICAL_REGION_LOCAL(m_threads_lock); - if(is_mining()) - { - LOG_ERROR("Starting miner but it's already started"); - return false; - } - - if(!m_threads.empty()) - { - LOG_ERROR("Unable to start miner because there are active mining threads"); - return false; - } - - request_block_template();//lets update block template - - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0); - boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0); - set_is_background_mining_enabled(do_background); - set_ignore_battery(ignore_battery); - - for(size_t i = 0; i != threads_count; i++) - { - m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this))); - } - - LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" ); - - if( get_is_background_mining_enabled() ) - { - m_background_mining_thread = boost::thread(attrs, boost::bind(&miner::background_worker_thread, this)); - LOG_PRINT_L0("Background mining controller thread started" ); - } - - return true; - } - //----------------------------------------------------------------------------------------------------- - uint64_t miner::get_speed() const - { - if(is_mining()) { - return m_current_hash_rate; - } - else { - return 0; - } - } - //----------------------------------------------------------------------------------------------------- - void miner::send_stop_signal() - { - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1); - } - //----------------------------------------------------------------------------------------------------- - bool miner::stop() - { - MTRACE("Miner has received stop signal"); - - if (!is_mining()) - { - MDEBUG("Not mining - nothing to stop" ); - return true; - } - - send_stop_signal(); - CRITICAL_REGION_LOCAL(m_threads_lock); - - // In case background mining was active and the miner threads are waiting - // on the background miner to signal start. - m_is_background_mining_started_cond.notify_all(); - - for(boost::thread& th: m_threads) - th.join(); - - // The background mining thread could be sleeping for a long time, so we - // interrupt it just in case - m_background_mining_thread.interrupt(); - m_background_mining_thread.join(); - - MINFO("Mining has been stopped, " << m_threads.size() << " finished" ); - m_threads.clear(); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height) - { - for(; bl.nonce != std::numeric_limits::max(); bl.nonce++) - { - crypto::hash h; - get_block_longhash(bl, h, height); - - if(check_hash(h, diffic)) - { - bl.invalidate_hashes(); - return true; - } - } - bl.invalidate_hashes(); - return false; - } - //----------------------------------------------------------------------------------------------------- - void miner::on_synchronized() - { - if(m_do_mining) - { - boost::thread::attributes attrs; - attrs.set_stack_size(THREAD_STACK_SIZE); - - start(m_mine_address, m_threads_total, attrs, get_is_background_mining_enabled(), get_ignore_battery()); - } - } - //----------------------------------------------------------------------------------------------------- - void miner::pause() - { - CRITICAL_REGION_LOCAL(m_miners_count_lock); - MDEBUG("miner::pause: " << m_pausers_count << " -> " << (m_pausers_count + 1)); - ++m_pausers_count; - if(m_pausers_count == 1 && is_mining()) - MDEBUG("MINING PAUSED"); - } - //----------------------------------------------------------------------------------------------------- - void miner::resume() - { - CRITICAL_REGION_LOCAL(m_miners_count_lock); - MDEBUG("miner::resume: " << m_pausers_count << " -> " << (m_pausers_count - 1)); - --m_pausers_count; - if(m_pausers_count < 0) - { - m_pausers_count = 0; - MERROR("Unexpected miner::resume() called"); - } - if(!m_pausers_count && is_mining()) - MDEBUG("MINING RESUMED"); - } - //----------------------------------------------------------------------------------------------------- - bool miner::worker_thread() - { - uint32_t th_local_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); - MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]"); - MGINFO("Miner thread was started ["<< th_local_index << "]"); - uint32_t nonce = m_starter_nonce + th_local_index; - uint64_t height = 0; - difficulty_type local_diff = 0; - uint32_t local_template_ver = 0; - block b; - slow_hash_allocate_state(); - while(!m_stop) - { - if(m_pausers_count)//anti split workaround - { - misc_utils::sleep_no_w(100); - continue; - } - else if( m_is_background_mining_enabled ) - { - misc_utils::sleep_no_w(m_miner_extra_sleep); - while( !m_is_background_mining_started ) - { - MGINFO("background mining is enabled, but not started, waiting until start triggers"); - boost::unique_lock started_lock( m_is_background_mining_started_mutex ); - m_is_background_mining_started_cond.wait( started_lock ); - if( m_stop ) break; - } - - if( m_stop ) continue; - } - - if(local_template_ver != m_template_no) - { - CRITICAL_REGION_BEGIN(m_template_lock); - b = m_template; - local_diff = m_diffic; - height = m_height; - CRITICAL_REGION_END(); - local_template_ver = m_template_no; - nonce = m_starter_nonce + th_local_index; - } - - if(!local_template_ver)//no any set_block_template call - { - LOG_PRINT_L2("Block template not set yet"); - epee::misc_utils::sleep_no_w(1000); - continue; - } - - b.nonce = nonce; - crypto::hash h; - get_block_longhash(b, h, height); - - if(check_hash(h, local_diff)) - { - //we lucky! - ++m_config.current_extra_message_index; - MGINFO_GREEN("Found block for difficulty: " << local_diff); - if(!m_phandler->handle_block_found(b)) - { - --m_config.current_extra_message_index; - }else - { - //success update, lets update config - if (!m_config_folder_path.empty()) - epee::serialization::store_t_to_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME); - } - } - nonce+=m_threads_total; - ++m_hashes; - } - slow_hash_free_state(); - MGINFO("Miner thread stopped ["<< th_local_index << "]"); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::get_is_background_mining_enabled() const - { - return m_is_background_mining_enabled; - } - //----------------------------------------------------------------------------------------------------- - bool miner::get_ignore_battery() const - { - return m_ignore_battery; - } - //----------------------------------------------------------------------------------------------------- - /** - * This has differing behaviour depending on if mining has been started/etc. - * Note: add documentation - */ - bool miner::set_is_background_mining_enabled(bool is_background_mining_enabled) - { - m_is_background_mining_enabled = is_background_mining_enabled; - // Extra logic will be required if we make this function public in the future - // and allow toggling smart mining without start/stop - //m_is_background_mining_enabled_cond.notify_one(); - return true; - } - //----------------------------------------------------------------------------------------------------- - void miner::set_ignore_battery(bool ignore_battery) - { - m_ignore_battery = ignore_battery; - } - //----------------------------------------------------------------------------------------------------- - uint64_t miner::get_min_idle_seconds() const - { - return m_min_idle_seconds; - } - //----------------------------------------------------------------------------------------------------- - bool miner::set_min_idle_seconds(uint64_t min_idle_seconds) - { - if(min_idle_seconds > BACKGROUND_MINING_MAX_MIN_IDLE_INTERVAL_IN_SECONDS) return false; - if(min_idle_seconds < BACKGROUND_MINING_MIN_MIN_IDLE_INTERVAL_IN_SECONDS) return false; - m_min_idle_seconds = min_idle_seconds; - return true; - } - //----------------------------------------------------------------------------------------------------- - uint8_t miner::get_idle_threshold() const - { - return m_idle_threshold; - } - //----------------------------------------------------------------------------------------------------- - bool miner::set_idle_threshold(uint8_t idle_threshold) - { - if(idle_threshold > BACKGROUND_MINING_MAX_IDLE_THRESHOLD_PERCENTAGE) return false; - if(idle_threshold < BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE) return false; - m_idle_threshold = idle_threshold; - return true; - } - //----------------------------------------------------------------------------------------------------- - uint8_t miner::get_mining_target() const - { - return m_mining_target; - } - //----------------------------------------------------------------------------------------------------- - bool miner::set_mining_target(uint8_t mining_target) - { - if(mining_target > BACKGROUND_MINING_MAX_MINING_TARGET_PERCENTAGE) return false; - if(mining_target < BACKGROUND_MINING_MIN_MINING_TARGET_PERCENTAGE) return false; - m_mining_target = mining_target; - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::background_worker_thread() - { - uint64_t prev_total_time, current_total_time; - uint64_t prev_idle_time, current_idle_time; - uint64_t previous_process_time = 0, current_process_time = 0; - m_is_background_mining_started = false; - - if(!get_system_times(prev_total_time, prev_idle_time)) - { - LOG_ERROR("get_system_times call failed, background mining will NOT work!"); - return false; - } - - while(!m_stop) - { - - try - { - // Commenting out the below since we're going with privatizing the bg mining enabled - // function, but I'll leave the code/comments here for anyone that wants to modify the - // patch in the future - // ------------------------------------------------------------------------------------- - // All of this might be overkill if we just enforced some simple requirements - // about changing this variable before/after the miner starts, but I envision - // in the future a checkbox that you can tick on/off for background mining after - // you've clicked "start mining". There's still an issue here where if background - // mining is disabled when start is called, this thread is never created, and so - // enabling after does nothing, something I have to fix in the future. However, - // this should take care of the case where mining is started with bg-enabled, - // and then the user decides to un-check background mining, and just do - // regular full-speed mining. I might just be over-doing it and thinking up - // non-existant use-cases, so if the consensus is to simplify, we can remove all this fluff. - /* - while( !m_is_background_mining_enabled ) - { - MGINFO("background mining is disabled, waiting until enabled!"); - boost::unique_lock enabled_lock( m_is_background_mining_enabled_mutex ); - m_is_background_mining_enabled_cond.wait( enabled_lock ); - } - */ - - // If we're already mining, then sleep for the miner monitor interval. - // If we're NOT mining, then sleep for the idle monitor interval - uint64_t sleep_for_seconds = BACKGROUND_MINING_MINER_MONITOR_INVERVAL_IN_SECONDS; - if( !m_is_background_mining_started ) sleep_for_seconds = get_min_idle_seconds(); - boost::this_thread::sleep_for(boost::chrono::seconds(sleep_for_seconds)); - } - catch(const boost::thread_interrupted&) - { - MDEBUG("background miner thread interrupted "); - continue; // if interrupted because stop called, loop should end .. - } - - bool on_ac_power = m_ignore_battery; - if(!m_ignore_battery) - { - boost::tribool battery_powered(on_battery_power()); - if(!indeterminate( battery_powered )) - { - on_ac_power = !battery_powered; - } - } - - if( m_is_background_mining_started ) - { - // figure out if we need to stop, and monitor mining usage - - // If we get here, then previous values are initialized. - // Let's get some current data for comparison. - - if(!get_system_times(current_total_time, current_idle_time)) - { - MERROR("get_system_times call failed"); - continue; - } - - if(!get_process_time(current_process_time)) - { - MERROR("get_process_time call failed!"); - continue; - } - - uint64_t total_diff = (current_total_time - prev_total_time); - uint64_t idle_diff = (current_idle_time - prev_idle_time); - uint64_t process_diff = (current_process_time - previous_process_time); - uint8_t idle_percentage = get_percent_of_total(idle_diff, total_diff); - uint8_t process_percentage = get_percent_of_total(process_diff, total_diff); - - MGINFO("idle percentage is " << unsigned(idle_percentage) << "\%, miner percentage is " << unsigned(process_percentage) << "\%, ac power : " << on_ac_power); - if( idle_percentage + process_percentage < get_idle_threshold() || !on_ac_power ) - { - MGINFO("cpu is " << unsigned(idle_percentage) << "% idle, idle threshold is " << unsigned(get_idle_threshold()) << "\%, ac power : " << on_ac_power << ", background mining stopping, thanks for your contribution!"); - m_is_background_mining_started = false; - - // reset process times - previous_process_time = 0; - current_process_time = 0; - } - else - { - previous_process_time = current_process_time; - - // adjust the miner extra sleep variable - int64_t miner_extra_sleep_change = (-1 * (get_mining_target() - process_percentage) ); - int64_t new_miner_extra_sleep = m_miner_extra_sleep + miner_extra_sleep_change; - // if you start the miner with few threads on a multicore system, this could - // fall below zero because all the time functions aggregate across all processors. - // I'm just hard limiting to 5 millis min sleep here, other options? - m_miner_extra_sleep = std::max( new_miner_extra_sleep , (int64_t)5 ); - MDEBUG("m_miner_extra_sleep " << m_miner_extra_sleep); - } - - prev_total_time = current_total_time; - prev_idle_time = current_idle_time; - } - else if( on_ac_power ) - { - // figure out if we need to start - - if(!get_system_times(current_total_time, current_idle_time)) - { - MERROR("get_system_times call failed"); - continue; - } - - uint64_t total_diff = (current_total_time - prev_total_time); - uint64_t idle_diff = (current_idle_time - prev_idle_time); - uint8_t idle_percentage = get_percent_of_total(idle_diff, total_diff); - - MGINFO("idle percentage is " << unsigned(idle_percentage)); - if( idle_percentage >= get_idle_threshold() && on_ac_power ) - { - MGINFO("cpu is " << unsigned(idle_percentage) << "% idle, idle threshold is " << unsigned(get_idle_threshold()) << "\%, ac power : " << on_ac_power << ", background mining started, good luck!"); - m_is_background_mining_started = true; - m_is_background_mining_started_cond.notify_all(); - - // Wait for a little mining to happen .. - boost::this_thread::sleep_for(boost::chrono::seconds( 1 )); - - // Starting data ... - if(!get_process_time(previous_process_time)) - { - m_is_background_mining_started = false; - MERROR("get_process_time call failed!"); - } - } - - prev_total_time = current_total_time; - prev_idle_time = current_idle_time; - } - } - - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::get_system_times(uint64_t& total_time, uint64_t& idle_time) - { - #ifdef _WIN32 - - FILETIME idleTime; - FILETIME kernelTime; - FILETIME userTime; - if ( GetSystemTimes( &idleTime, &kernelTime, &userTime ) != -1 ) - { - total_time = - ( (((uint64_t)(kernelTime.dwHighDateTime)) << 32) | ((uint64_t)kernelTime.dwLowDateTime) ) - + ( (((uint64_t)(userTime.dwHighDateTime)) << 32) | ((uint64_t)userTime.dwLowDateTime) ); - - idle_time = ( (((uint64_t)(idleTime.dwHighDateTime)) << 32) | ((uint64_t)idleTime.dwLowDateTime) ); - - return true; - } - - #elif defined(__linux__) - - const std::string STAT_FILE_PATH = "/proc/stat"; - - if( !epee::file_io_utils::is_file_exist(STAT_FILE_PATH) ) - { - LOG_ERROR("'" << STAT_FILE_PATH << "' file does not exist"); - return false; - } - - std::ifstream stat_file_stream(STAT_FILE_PATH); - if( stat_file_stream.fail() ) - { - LOG_ERROR("failed to open '" << STAT_FILE_PATH << "'"); - return false; - } - - std::string line; - std::getline(stat_file_stream, line); - std::istringstream stat_file_iss(line); - stat_file_iss.ignore(65536, ' '); // skip cpu label ... - uint64_t utime, ntime, stime, itime; - if( !(stat_file_iss >> utime && stat_file_iss >> ntime && stat_file_iss >> stime && stat_file_iss >> itime) ) - { - LOG_ERROR("failed to read '" << STAT_FILE_PATH << "'"); - return false; - } - - idle_time = itime; - total_time = utime + ntime + stime + itime; - - return true; - - #elif defined(__APPLE__) - - mach_msg_type_number_t count; - kern_return_t status; - host_cpu_load_info_data_t stats; - count = HOST_CPU_LOAD_INFO_COUNT; - status = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&stats, &count); - if(status != KERN_SUCCESS) - { - return false; - } - - idle_time = stats.cpu_ticks[CPU_STATE_IDLE]; - total_time = idle_time + stats.cpu_ticks[CPU_STATE_USER] + stats.cpu_ticks[CPU_STATE_SYSTEM]; - - return true; - - #elif defined(__FreeBSD__) - - struct statinfo s; - size_t n = sizeof(s.cp_time); - if( sysctlbyname("kern.cp_time", s.cp_time, &n, NULL, 0) == -1 ) - { - LOG_ERROR("sysctlbyname(\"kern.cp_time\"): " << strerror(errno)); - return false; - } - if( n != sizeof(s.cp_time) ) - { - LOG_ERROR("sysctlbyname(\"kern.cp_time\") output is unexpectedly " - << n << " bytes instead of the expected " << sizeof(s.cp_time) - << " bytes."); - return false; - } - - idle_time = s.cp_time[CP_IDLE]; - total_time = - s.cp_time[CP_USER] + - s.cp_time[CP_NICE] + - s.cp_time[CP_SYS] + - s.cp_time[CP_INTR] + - s.cp_time[CP_IDLE]; - - return true; - - #endif - - return false; // unsupported system - } - //----------------------------------------------------------------------------------------------------- - bool miner::get_process_time(uint64_t& total_time) - { - #ifdef _WIN32 - - FILETIME createTime; - FILETIME exitTime; - FILETIME kernelTime; - FILETIME userTime; - if ( GetProcessTimes( GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime ) != -1 ) - { - total_time = - ( (((uint64_t)(kernelTime.dwHighDateTime)) << 32) | ((uint64_t)kernelTime.dwLowDateTime) ) - + ( (((uint64_t)(userTime.dwHighDateTime)) << 32) | ((uint64_t)userTime.dwLowDateTime) ); - - return true; - } - - #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || defined(__APPLE__) || defined(__FreeBSD__) - - struct tms tms; - if ( times(&tms) != (clock_t)-1 ) - { - total_time = tms.tms_utime + tms.tms_stime; - return true; - } - - #endif - - return false; // unsupported system - } - //----------------------------------------------------------------------------------------------------- - uint8_t miner::get_percent_of_total(uint64_t other, uint64_t total) - { - return (uint8_t)( ceil( (other * 1.f / total * 1.f) * 100) ); - } - //----------------------------------------------------------------------------------------------------- - boost::logic::tribool miner::on_battery_power() - { - #ifdef _WIN32 - - SYSTEM_POWER_STATUS power_status; - if ( GetSystemPowerStatus( &power_status ) != 0 ) - { - return boost::logic::tribool(power_status.ACLineStatus != 1); - } - - #elif defined(__APPLE__) - - #if TARGET_OS_MAC && (!defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7) - return boost::logic::tribool(IOPSGetTimeRemainingEstimate() != kIOPSTimeRemainingUnlimited); - #else - // iOS or OSX <10.7 - return boost::logic::tribool(boost::logic::indeterminate); - #endif - - #elif defined(__linux__) - - // Use the power_supply class http://lxr.linux.no/#linux+v4.10.1/Documentation/power/power_supply_class.txt - std::string power_supply_class_path = "/sys/class/power_supply"; - - boost::tribool on_battery = boost::logic::tribool(boost::logic::indeterminate); - if (boost::filesystem::is_directory(power_supply_class_path)) - { - const boost::filesystem::directory_iterator end_itr; - for (boost::filesystem::directory_iterator iter(power_supply_class_path); iter != end_itr; ++iter) - { - const boost::filesystem::path& power_supply_path = iter->path(); - if (boost::filesystem::is_directory(power_supply_path)) - { - boost::filesystem::path power_supply_type_path = power_supply_path / "type"; - if (boost::filesystem::is_regular_file(power_supply_type_path)) - { - std::ifstream power_supply_type_stream(power_supply_type_path.string()); - if (power_supply_type_stream.fail()) - { - LOG_PRINT_L0("Unable to read from " << power_supply_type_path << " to check power supply type"); - continue; - } - - std::string power_supply_type; - std::getline(power_supply_type_stream, power_supply_type); - - // If there is an AC adapter that's present and online we can break early - if (boost::starts_with(power_supply_type, "Mains")) - { - boost::filesystem::path power_supply_online_path = power_supply_path / "online"; - if (boost::filesystem::is_regular_file(power_supply_online_path)) - { - std::ifstream power_supply_online_stream(power_supply_online_path.string()); - if (power_supply_online_stream.fail()) - { - LOG_PRINT_L0("Unable to read from " << power_supply_online_path << " to check ac power supply status"); - continue; - } - - if (power_supply_online_stream.get() == '1') - { - return boost::logic::tribool(false); - } - } - } - else if (boost::starts_with(power_supply_type, "Battery") && boost::logic::indeterminate(on_battery)) - { - boost::filesystem::path power_supply_status_path = power_supply_path / "status"; - if (boost::filesystem::is_regular_file(power_supply_status_path)) - { - std::ifstream power_supply_status_stream(power_supply_status_path.string()); - if (power_supply_status_stream.fail()) - { - LOG_PRINT_L0("Unable to read from " << power_supply_status_path << " to check battery power supply status"); - continue; - } - - // Possible status are Charging, Full, Discharging, Not Charging, and Unknown - // We are only need to handle negative states right now - std::string power_supply_status; - std::getline(power_supply_status_stream, power_supply_status); - if (boost::starts_with(power_supply_status, "Charging") || boost::starts_with(power_supply_status, "Full")) - { - on_battery = boost::logic::tribool(false); - } - - if (boost::starts_with(power_supply_status, "Discharging")) - { - on_battery = boost::logic::tribool(true); - } - } - } - } - } - } - } - - if (boost::logic::indeterminate(on_battery)) - { - LOG_ERROR("couldn't query power status from " << power_supply_class_path); - } - return on_battery; - - #elif defined(__FreeBSD__) - int ac; - size_t n = sizeof(ac); - if( sysctlbyname("hw.acpi.acline", &ac, &n, NULL, 0) == -1 ) - { - if( errno != ENOENT ) - { - LOG_ERROR("Cannot query battery status: " - << "sysctlbyname(\"hw.acpi.acline\"): " << strerror(errno)); - return boost::logic::tribool(boost::logic::indeterminate); - } - - // If sysctl fails with ENOENT, then try querying /dev/apm. - - static const char* dev_apm = "/dev/apm"; - const int fd = open(dev_apm, O_RDONLY); - if( fd == -1 ) { - LOG_ERROR("Cannot query battery status: " - << "open(): " << dev_apm << ": " << strerror(errno)); - return boost::logic::tribool(boost::logic::indeterminate); - } - - apm_info info; - if( ioctl(fd, APMIO_GETINFO, &info) == -1 ) { - close(fd); - LOG_ERROR("Cannot query battery status: " - << "ioctl(" << dev_apm << ", APMIO_GETINFO): " << strerror(errno)); - return boost::logic::tribool(boost::logic::indeterminate); - } - - close(fd); - - // See apm(8). - switch( info.ai_acline ) - { - case 0: // off-line - case 2: // backup power - return boost::logic::tribool(true); - case 1: // on-line - return boost::logic::tribool(false); - } - switch( info.ai_batt_stat ) - { - case 0: // high - case 1: // low - case 2: // critical - return boost::logic::tribool(true); - case 3: // charging - return boost::logic::tribool(false); - } - - LOG_ERROR("Cannot query battery status: " - << "sysctl hw.acpi.acline is not available and /dev/apm returns " - << "unexpected ac-line status (" << info.ai_acline << ") and " - << "battery status (" << info.ai_batt_stat << ")."); - return boost::logic::tribool(boost::logic::indeterminate); - } - if( n != sizeof(ac) ) - { - LOG_ERROR("sysctlbyname(\"hw.acpi.acline\") output is unexpectedly " - << n << " bytes instead of the expected " << sizeof(ac) << " bytes."); - return boost::logic::tribool(boost::logic::indeterminate); - } - return boost::logic::tribool(ac == 0); - #endif - - LOG_ERROR("couldn't query power status"); - return boost::logic::tribool(boost::logic::indeterminate); - } -} diff --git a/src/Native/libcryptonote/cryptonote_basic/miner.h b/src/Native/libcryptonote/cryptonote_basic/miner.h deleted file mode 100644 index 2bff784c7..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/miner.h +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include -#include -#include -#include "cryptonote_basic.h" -#include "difficulty.h" -#include "math_helper.h" -#ifdef _WIN32 -#include -#elif defined(__linux__) -#include -#include -#include -#include -#endif - -namespace cryptonote -{ - - struct i_miner_handler - { - virtual bool handle_block_found(block& b) = 0; - virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce) = 0; - protected: - ~i_miner_handler(){}; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class miner - { - public: - miner(i_miner_handler* phandler); - ~miner(); - bool init(const boost::program_options::variables_map& vm, network_type nettype); - static void init_options(boost::program_options::options_description& desc); - bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height); - bool on_block_chain_update(); - bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background = false, bool ignore_battery = false); - uint64_t get_speed() const; - uint32_t get_threads_count() const; - void send_stop_signal(); - bool stop(); - bool is_mining() const; - const account_public_address& get_mining_address() const; - bool on_idle(); - void on_synchronized(); - //synchronous analog (for fast calls) - static bool find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height); - void pause(); - void resume(); - void do_print_hashrate(bool do_hr); - bool get_is_background_mining_enabled() const; - bool get_ignore_battery() const; - uint64_t get_min_idle_seconds() const; - bool set_min_idle_seconds(uint64_t min_idle_seconds); - uint8_t get_idle_threshold() const; - bool set_idle_threshold(uint8_t idle_threshold); - uint8_t get_mining_target() const; - bool set_mining_target(uint8_t mining_target); - - static constexpr uint8_t BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE = 90; - static constexpr uint8_t BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE = 50; - static constexpr uint8_t BACKGROUND_MINING_MAX_IDLE_THRESHOLD_PERCENTAGE = 99; - static constexpr uint16_t BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS = 10; - static constexpr uint16_t BACKGROUND_MINING_MIN_MIN_IDLE_INTERVAL_IN_SECONDS = 10; - static constexpr uint16_t BACKGROUND_MINING_MAX_MIN_IDLE_INTERVAL_IN_SECONDS = 3600; - static constexpr uint8_t BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE = 40; - static constexpr uint8_t BACKGROUND_MINING_MIN_MINING_TARGET_PERCENTAGE = 5; - static constexpr uint8_t BACKGROUND_MINING_MAX_MINING_TARGET_PERCENTAGE = 50; - static constexpr uint8_t BACKGROUND_MINING_MINER_MONITOR_INVERVAL_IN_SECONDS = 10; - static constexpr uint64_t BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS = 400; // ramp up - static constexpr uint64_t BACKGROUND_MINING_MIN_MINER_EXTRA_SLEEP_MILLIS = 5; - - private: - bool worker_thread(); - bool request_block_template(); - void merge_hr(); - - struct miner_config - { - uint64_t current_extra_message_index; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(current_extra_message_index) - END_KV_SERIALIZE_MAP() - }; - - - volatile uint32_t m_stop; - epee::critical_section m_template_lock; - block m_template; - std::atomic m_template_no; - std::atomic m_starter_nonce; - difficulty_type m_diffic; - uint64_t m_height; - volatile uint32_t m_thread_index; - volatile uint32_t m_threads_total; - std::atomic m_pausers_count; - epee::critical_section m_miners_count_lock; - - std::list m_threads; - epee::critical_section m_threads_lock; - i_miner_handler* m_phandler; - account_public_address m_mine_address; - epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval; - epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval; - std::vector m_extra_messages; - miner_config m_config; - std::string m_config_folder_path; - std::atomic m_last_hr_merge_time; - std::atomic m_hashes; - std::atomic m_current_hash_rate; - epee::critical_section m_last_hash_rates_lock; - std::list m_last_hash_rates; - bool m_do_print_hashrate; - bool m_do_mining; - - // background mining stuffs .. - - bool set_is_background_mining_enabled(bool is_background_mining_enabled); - void set_ignore_battery(bool ignore_battery); - bool background_worker_thread(); - std::atomic m_is_background_mining_enabled; - bool m_ignore_battery; - boost::mutex m_is_background_mining_enabled_mutex; - boost::condition_variable m_is_background_mining_enabled_cond; - std::atomic m_is_background_mining_started; - boost::mutex m_is_background_mining_started_mutex; - boost::condition_variable m_is_background_mining_started_cond; - boost::thread m_background_mining_thread; - uint64_t m_min_idle_seconds; - uint8_t m_idle_threshold; - uint8_t m_mining_target; - std::atomic m_miner_extra_sleep; - static bool get_system_times(uint64_t& total_time, uint64_t& idle_time); - static bool get_process_time(uint64_t& total_time); - static uint8_t get_percent_of_total(uint64_t some_time, uint64_t total_time); - static boost::logic::tribool on_battery_power(); - }; -} diff --git a/src/Native/libcryptonote/cryptonote_basic/subaddress_index.h b/src/Native/libcryptonote/cryptonote_basic/subaddress_index.h deleted file mode 100644 index 9b71448f9..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/subaddress_index.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2017-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "serialization/keyvalue_serialization.h" -#include -#include -#include - -namespace cryptonote -{ - struct subaddress_index - { - uint32_t major; - uint32_t minor; - bool operator==(const subaddress_index& rhs) const { return !memcmp(this, &rhs, sizeof(subaddress_index)); } - bool operator!=(const subaddress_index& rhs) const { return !(*this == rhs); } - bool is_zero() const { return major == 0 && minor == 0; } - - BEGIN_SERIALIZE_OBJECT() - FIELD(major) - FIELD(minor) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(major) - KV_SERIALIZE(minor) - END_KV_SERIALIZE_MAP() - }; -} - -namespace cryptonote { - inline std::ostream& operator<<(std::ostream& out, const cryptonote::subaddress_index& subaddr_index) - { - return out << subaddr_index.major << '/' << subaddr_index.minor; - } -} - -namespace std -{ - template <> - struct hash - { - size_t operator()(const cryptonote::subaddress_index& index ) const - { - size_t res; - if (sizeof(size_t) == 8) - { - res = ((uint64_t)index.major << 32) | index.minor; - } - else - { - // https://stackoverflow.com/a/17017281 - res = 17; - res = res * 31 + hash()(index.major); - res = res * 31 + hash()(index.minor); - } - return res; - } - }; -} - -BOOST_CLASS_VERSION(cryptonote::subaddress_index, 0) - -namespace boost -{ - namespace serialization - { - template - inline void serialize(Archive &a, cryptonote::subaddress_index &x, const boost::serialization::version_type ver) - { - a & x.major; - a & x.minor; - } - } -} diff --git a/src/Native/libcryptonote/cryptonote_basic/tx_extra.h b/src/Native/libcryptonote/cryptonote_basic/tx_extra.h deleted file mode 100644 index 009e35ebe..000000000 --- a/src/Native/libcryptonote/cryptonote_basic/tx_extra.h +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2014-2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - - -#define TX_EXTRA_PADDING_MAX_COUNT 255 -#define TX_EXTRA_NONCE_MAX_COUNT 255 - -#define TX_EXTRA_TAG_PADDING 0x00 -#define TX_EXTRA_TAG_PUBKEY 0x01 -#define TX_EXTRA_NONCE 0x02 -#define TX_EXTRA_MERGE_MINING_TAG 0x03 -#define TX_EXTRA_TAG_ADDITIONAL_PUBKEYS 0x04 -#define TX_EXTRA_MYSTERIOUS_MINERGATE_TAG 0xDE - -#define TX_EXTRA_NONCE_PAYMENT_ID 0x00 -#define TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID 0x01 - -namespace cryptonote -{ - struct tx_extra_padding - { - size_t size; - - // load - template