├── pre-compiled libs
└── libleveldb.dll
├── MedPoints
├── Storage.Core
│ ├── IScriptContainer.cs
│ ├── IVerifiable.cs
│ ├── Storage.Core.csproj
│ ├── Witness.cs
│ ├── UInt256.cs
│ ├── UInt160.cs
│ ├── CoreHelper.cs
│ ├── BigDecimal.cs
│ ├── UIntBase.cs
│ ├── Fixed8.cs
│ ├── Helper.cs
│ └── Transaction.cs
├── Storage
│ ├── Core
│ │ ├── Transactions
│ │ │ ├── TransactionType.cs
│ │ │ ├── ITransaction.cs
│ │ │ ├── DoctorVisitTransaction.cs
│ │ │ └── CoinTransaction.cs
│ │ ├── Chain.cs
│ │ ├── Block.cs
│ │ └── Wallet.cs
│ ├── Mempool
│ │ ├── MempoolTransaction.cs
│ │ └── Mempool.cs
│ ├── Storage.csproj
│ ├── Database
│ │ ├── BlockRepository.cs
│ │ ├── CoinTransactionRepository.cs
│ │ ├── MempoolRepository.cs
│ │ └── AppointmentToTheDoctorRepository.cs
│ └── Utils
│ │ ├── HashHelper.cs
│ │ └── RSAKeyExtensions.cs
├── Storage.Network
│ ├── InventoryType.cs
│ ├── IInventory.cs
│ ├── RPC
│ │ ├── RpcException.cs
│ │ └── RpcServer.cs
│ ├── Storage.Network.csproj
│ ├── InventoryReceivingEventArgs.cs
│ ├── Payloads
│ │ ├── FilterAddPayload.cs
│ │ ├── AddrPayload.cs
│ │ ├── HeadersPayload.cs
│ │ ├── GetBlocksPayload.cs
│ │ ├── InvPayload.cs
│ │ ├── FilterLoadPayload.cs
│ │ ├── NetworkAddressWithTime.cs
│ │ ├── MerkleBlockPayload.cs
│ │ ├── VersionPayload.cs
│ │ └── ConsensusPayload.cs
│ ├── WebSocketRemoteNode.cs
│ ├── TcpRemoteNode.cs
│ ├── Message.cs
│ └── UPnP.cs
├── Storage.Utils
│ ├── ISerializable.cs
│ ├── Storage.Utils.csproj
│ ├── Settings.cs
│ └── Helper.cs
├── Storage.Data
│ ├── LevelDB
│ │ ├── LevelDBException.cs
│ │ ├── WriteOptions.cs
│ │ ├── Snapshot.cs
│ │ ├── WriteBatch.cs
│ │ ├── ReadOptions.cs
│ │ ├── Options.cs
│ │ ├── Iterator.cs
│ │ ├── DatabaseContext.cs
│ │ ├── Slice.cs
│ │ └── NativeWrapper.cs
│ └── Storage.Data.csproj
├── Storage.Cli
│ ├── Storage.Cli.csproj
│ ├── Program.cs
│ └── TestChain.cs
└── MedPoints.sln
├── README.md
└── .gitignore
/pre-compiled libs/libleveldb.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MedPoints/storage/HEAD/pre-compiled libs/libleveldb.dll
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/IScriptContainer.cs:
--------------------------------------------------------------------------------
1 | namespace Storage.Core
2 | {
3 | public interface IScriptContainer
4 | {
5 | byte[] GetMessage();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Core/Transactions/TransactionType.cs:
--------------------------------------------------------------------------------
1 | namespace Storage.Core.Transactions
2 | {
3 | public enum TransactionType
4 | {
5 | Coins,
6 | VisitToTheDoctor
7 | }
8 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/InventoryType.cs:
--------------------------------------------------------------------------------
1 | // ReSharper disable InconsistentNaming
2 | namespace Storage.Network
3 | {
4 | public enum InventoryType : byte
5 | {
6 | TX = 0x01,
7 | Block = 0x02,
8 | Consensus = 0xe0
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # storage
2 |
3 | `Storage` is a project which is about prototype of blockchain.
4 |
5 | We are using `.NET Core` for creating/running it.
6 |
7 | # Run
8 |
9 | For running it you need to go to the folder with `Storage.csproj` and call `dotnet run`.
10 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Utils/ISerializable.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace Storage.Utils
4 | {
5 | public interface ISerializable
6 | {
7 | int Size { get; }
8 | void Serialize(BinaryWriter writer);
9 | void Deserialize(BinaryReader reader);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/IInventory.cs:
--------------------------------------------------------------------------------
1 | using Storage.Core;
2 |
3 | namespace Storage.Network
4 | {
5 | public interface IInventory : IVerifiable
6 | {
7 | UInt256 Hash { get; }
8 |
9 | InventoryType InventoryType { get; }
10 |
11 | bool Verify();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/RPC/RpcException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Neo.Network.RPC
4 | {
5 | public class RpcException : Exception
6 | {
7 | public RpcException(int code, string message) : base(message)
8 | {
9 | HResult = code;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Core/Transactions/ITransaction.cs:
--------------------------------------------------------------------------------
1 | namespace Storage.Core.Transactions
2 | {
3 | public interface ITransaction
4 | {
5 | string Id { get; set; }
6 | string Sender { get; set; }
7 | string Signature { get; set; }
8 | TransactionType Type { get; }
9 | }
10 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/LevelDBException.cs:
--------------------------------------------------------------------------------
1 | using System.Data.Common;
2 |
3 | namespace Storage.Data.LevelDB
4 | {
5 | internal class LevelDbException : DbException
6 | {
7 | internal LevelDbException(string message)
8 | : base(message)
9 | {
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Storage.Network.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Cli/Storage.Cli.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/Storage.Data.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.0
5 |
6 |
7 |
8 | true
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Mempool/MempoolTransaction.cs:
--------------------------------------------------------------------------------
1 | using Storage.Core.Transactions;
2 |
3 | namespace Storage.Mempool
4 | {
5 | public class MempoolTransaction
6 | {
7 | public string Id { get; set; }
8 | public string UserId { get; set; }
9 | public TransactionType Type { get; set; }
10 | public string Transaction { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/InventoryReceivingEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace Storage.Network
4 | {
5 | public class InventoryReceivingEventArgs : CancelEventArgs
6 | {
7 | public IInventory Inventory { get; }
8 |
9 | public InventoryReceivingEventArgs(IInventory inventory)
10 | {
11 | this.Inventory = inventory;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/IVerifiable.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Storage.Utils;
3 |
4 | namespace Storage.Core
5 | {
6 | public interface IVerifiable : ISerializable, IScriptContainer
7 | {
8 |
9 | Witness[] Scripts { get; set; }
10 | void DeserializeUnsigned(BinaryReader reader);
11 | UInt160[] GetScriptHashesForVerifying();
12 | void SerializeUnsigned(BinaryWriter writer);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Utils/Storage.Utils.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/Storage.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.0
5 |
6 |
7 |
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/FilterAddPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.IO;
2 | using System.IO;
3 |
4 | namespace Neo.Network.Payloads
5 | {
6 | public class FilterAddPayload : ISerializable
7 | {
8 | public byte[] Data;
9 |
10 | public int Size => Data.GetVarSize();
11 |
12 | void ISerializable.Deserialize(BinaryReader reader)
13 | {
14 | Data = reader.ReadVarBytes(520);
15 | }
16 |
17 | void ISerializable.Serialize(BinaryWriter writer)
18 | {
19 | writer.WriteVarBytes(Data);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/WriteOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Storage.Data.LevelDB
4 | {
5 | class WriteOptions
6 | {
7 | public static readonly WriteOptions Default = new WriteOptions();
8 | internal readonly IntPtr handle = NativeWrapper.leveldb_writeoptions_create();
9 |
10 | public bool Sync
11 | {
12 | set => NativeWrapper.leveldb_writeoptions_set_sync(handle, value);
13 | }
14 |
15 | ~WriteOptions()
16 | {
17 | NativeWrapper.leveldb_writeoptions_destroy(handle);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/Snapshot.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using static Storage.Data.LevelDB.NativeWrapper;
3 |
4 | namespace Storage.Data.LevelDB
5 | {
6 | public class Snapshot
7 | {
8 | public IntPtr Db, Handle;
9 |
10 | internal Snapshot(IntPtr db)
11 | {
12 | Db = db;
13 | Handle = leveldb_create_snapshot(db);
14 | }
15 |
16 | public void Dispose()
17 | {
18 | if (Handle == IntPtr.Zero) return;
19 |
20 | leveldb_release_snapshot(Db, Handle);
21 | Handle = IntPtr.Zero;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Core/Transactions/DoctorVisitTransaction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Storage.Core.Transactions
4 | {
5 | public class AppointmentToTheDoctorTransaction : ITransaction
6 | {
7 | public string Id { get; set; }
8 | public string Sender { get; set; }
9 | public string Signature { get; set; }
10 | public TransactionType Type => TransactionType.VisitToTheDoctor;
11 |
12 | public string DoctorId { get; set; }
13 | public string ClinicId { get; set; }
14 | public string ServiceId { get; set; }
15 |
16 | public string Description { get; set; }
17 |
18 | public DateTime Date { get; set; }
19 | }
20 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/AddrPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.IO;
2 | using System.IO;
3 |
4 | namespace Neo.Network.Payloads
5 | {
6 | public class AddrPayload : ISerializable
7 | {
8 | public NetworkAddressWithTime[] AddressList;
9 |
10 | public int Size => AddressList.GetVarSize();
11 |
12 | public static AddrPayload Create(params NetworkAddressWithTime[] addresses)
13 | {
14 | return new AddrPayload
15 | {
16 | AddressList = addresses
17 | };
18 | }
19 |
20 | void ISerializable.Deserialize(BinaryReader reader)
21 | {
22 | this.AddressList = reader.ReadSerializableArray(200);
23 | }
24 |
25 | void ISerializable.Serialize(BinaryWriter writer)
26 | {
27 | writer.Write(AddressList);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/WriteBatch.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using static Storage.Data.LevelDB.NativeWrapper;
3 |
4 | namespace Storage.Data.LevelDB
5 | {
6 | public class WriteBatch
7 | {
8 | internal readonly IntPtr Handle = leveldb_writebatch_create();
9 |
10 | ~WriteBatch()
11 | {
12 | leveldb_writebatch_destroy(Handle);
13 | }
14 |
15 | public void Clear()
16 | {
17 | leveldb_writebatch_clear(Handle);
18 | }
19 |
20 | public void Delete(Slice key)
21 | {
22 | leveldb_writebatch_delete(Handle, key.buffer, (UIntPtr)key.buffer.Length);
23 | }
24 |
25 | public void Put(Slice key, Slice value)
26 | {
27 | leveldb_writebatch_put(Handle, key.buffer, (UIntPtr)key.buffer.Length, value.buffer, (UIntPtr)value.buffer.Length);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/ReadOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using static Storage.Data.LevelDB.NativeWrapper;
3 |
4 | namespace Storage.Data.LevelDB
5 | {
6 | class ReadOptions
7 | {
8 | public static readonly ReadOptions Default = new ReadOptions();
9 | internal readonly IntPtr handle = leveldb_readoptions_create();
10 |
11 | public bool VerifyChecksums
12 | {
13 | set => leveldb_readoptions_set_verify_checksums(handle, value);
14 | }
15 |
16 | public bool FillCache
17 | {
18 | set => leveldb_readoptions_set_fill_cache(handle, value);
19 | }
20 |
21 | public Snapshot Snapshot
22 | {
23 | set => leveldb_readoptions_set_snapshot(handle, value.Handle);
24 | }
25 |
26 | ~ReadOptions()
27 | {
28 | leveldb_readoptions_destroy(handle);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/HeadersPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.Core;
2 | using Neo.IO;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 |
7 | namespace Neo.Network.Payloads
8 | {
9 | public class HeadersPayload : ISerializable
10 | {
11 | public Header[] Headers;
12 |
13 | public int Size => Headers.GetVarSize();
14 |
15 | public static HeadersPayload Create(IEnumerable headers)
16 | {
17 | return new HeadersPayload
18 | {
19 | Headers = headers.ToArray()
20 | };
21 | }
22 |
23 | void ISerializable.Deserialize(BinaryReader reader)
24 | {
25 | Headers = reader.ReadSerializableArray(2000);
26 | }
27 |
28 | void ISerializable.Serialize(BinaryWriter writer)
29 | {
30 | writer.Write(Headers);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Core/Chain.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Storage.Core
6 | {
7 | public class Chain
8 | {
9 | public static List Blockchain = new List();
10 |
11 | public static bool IsChainValid()
12 | {
13 | for (int i = 1; i < Blockchain.Count; i++)
14 | {
15 | var currentBlock = Blockchain[i];
16 | var previousBlock = Blockchain[i - 1];
17 | if (currentBlock.Hash != currentBlock.CalculateHash())
18 | {
19 | Console.WriteLine("Current Hashes not equal");
20 | return false;
21 | }
22 |
23 | if (previousBlock.Hash != currentBlock.PreviousHash)
24 | {
25 | Console.WriteLine("Previous Hashes not equal");
26 | return false;
27 | }
28 | }
29 | return true;
30 | }
31 |
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Cli/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Storage.Core;
4 | using Storage.Utils;
5 |
6 | namespace Storage.Cli
7 | {
8 | class Program
9 | {
10 | static void Main(string[] args)
11 | {
12 | var coinbase = new Wallet();
13 | //Console.WriteLine(coinbase.PrivateKey.);
14 |
15 | //TestChain.Test();
16 |
17 | /*var sender = new Wallet();
18 | var receipent = new Wallet();
19 |
20 | var transaction = new Transaction(sender.PublicKey, receipent.PublicKey, 20, null, null);
21 | transaction.Sign(sender);
22 | transaction.VerifySignature();*/
23 |
24 | /*var dataBase = DatabaseContext.Open("test", new Options { CreateIfMissing = true });
25 | dataBase.Put(WriteOptions.Default, block.Hash.ToSlice(), block.ToSlice());
26 | var data = dataBase.Get(ReadOptions.Default, block.Hash.ToSlice());
27 | var result = data.ToString();*/
28 |
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/GetBlocksPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.IO;
2 | using System.IO;
3 |
4 | namespace Neo.Network.Payloads
5 | {
6 | public class GetBlocksPayload : ISerializable
7 | {
8 | public UInt256[] HashStart;
9 | public UInt256 HashStop;
10 |
11 | public int Size => HashStart.GetVarSize() + HashStop.Size;
12 |
13 | public static GetBlocksPayload Create(UInt256 hash_start, UInt256 hash_stop = null)
14 | {
15 | return new GetBlocksPayload
16 | {
17 | HashStart = new[] { hash_start },
18 | HashStop = hash_stop ?? UInt256.Zero
19 | };
20 | }
21 |
22 | void ISerializable.Deserialize(BinaryReader reader)
23 | {
24 | HashStart = reader.ReadSerializableArray(16);
25 | HashStop = reader.ReadSerializable();
26 | }
27 |
28 | void ISerializable.Serialize(BinaryWriter writer)
29 | {
30 | writer.Write(HashStart);
31 | writer.Write(HashStop);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Storage.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netcoreapp2.0
4 | 7.2
5 |
6 |
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/InvPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.IO;
2 | using System;
3 | using System.IO;
4 |
5 | namespace Neo.Network.Payloads
6 | {
7 | public class InvPayload : ISerializable
8 | {
9 | public InventoryType Type;
10 | public UInt256[] Hashes;
11 |
12 | public int Size => sizeof(InventoryType) + Hashes.GetVarSize();
13 |
14 | public static InvPayload Create(InventoryType type, params UInt256[] hashes)
15 | {
16 | return new InvPayload
17 | {
18 | Type = type,
19 | Hashes = hashes
20 | };
21 | }
22 |
23 | void ISerializable.Deserialize(BinaryReader reader)
24 | {
25 | Type = (InventoryType)reader.ReadByte();
26 | if (!Enum.IsDefined(typeof(InventoryType), Type))
27 | throw new FormatException();
28 | Hashes = reader.ReadSerializableArray();
29 | }
30 |
31 | void ISerializable.Serialize(BinaryWriter writer)
32 | {
33 | writer.Write((byte)Type);
34 | writer.Write(Hashes);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Database/BlockRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using Dapper;
3 | using Npgsql;
4 | using Storage.Core;
5 | using Storage.Core.Transactions;
6 |
7 | namespace Storage.Database
8 | {
9 | public class BlockRepository
10 | {
11 | private string connectionString;
12 | private IDbConnection Connection => new NpgsqlConnection(connectionString);
13 |
14 | public string GetLastBlockHash(){
15 | using (IDbConnection dbConnection = Connection)
16 | {
17 | dbConnection.Open();
18 | return dbConnection.QueryFirst("SELECT hash FROM blocks ORDER BY id DESC LIMIT 1;");
19 | }
20 | }
21 |
22 | public void Add(Block block)
23 | {
24 | using (IDbConnection dbConnection = Connection)
25 | {
26 | dbConnection.Open();
27 | dbConnection.Execute(
28 | "INSERT INTO blocks (hash, data) VALUES(@Hash,@Data)",
29 | new {Hash = block.Hash, Data = block.Serialize()});
30 | }
31 | }
32 |
33 |
34 | }
35 |
36 |
37 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/FilterLoadPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.Cryptography;
2 | using Neo.IO;
3 | using System;
4 | using System.IO;
5 |
6 | namespace Neo.Network.Payloads
7 | {
8 | public class FilterLoadPayload : ISerializable
9 | {
10 | public byte[] Filter;
11 | public byte K;
12 | public uint Tweak;
13 |
14 | public int Size => Filter.GetVarSize() + sizeof(byte) + sizeof(uint);
15 |
16 | public static FilterLoadPayload Create(BloomFilter filter)
17 | {
18 | byte[] buffer = new byte[filter.M / 8];
19 | filter.GetBits(buffer);
20 | return new FilterLoadPayload
21 | {
22 | Filter = buffer,
23 | K = (byte)filter.K,
24 | Tweak = filter.Tweak
25 | };
26 | }
27 |
28 | void ISerializable.Deserialize(BinaryReader reader)
29 | {
30 | Filter = reader.ReadVarBytes(36000);
31 | K = reader.ReadByte();
32 | if (K > 50) throw new FormatException();
33 | Tweak = reader.ReadUInt32();
34 | }
35 |
36 | void ISerializable.Serialize(BinaryWriter writer)
37 | {
38 | writer.WriteVarBytes(Filter);
39 | writer.Write(K);
40 | writer.Write(Tweak);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/Witness.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Newtonsoft.Json.Linq;
3 | using Storage.Utils;
4 |
5 | namespace Storage.Core
6 | {
7 | public class Witness : ISerializable
8 | {
9 | public byte[] InvocationScript;
10 | public byte[] VerificationScript;
11 |
12 | private UInt160 _scriptHash;
13 | public virtual UInt160 ScriptHash
14 | {
15 | get
16 | {
17 | if (_scriptHash == null)
18 | {
19 | _scriptHash = VerificationScript.ToScriptHash();
20 | }
21 | return _scriptHash;
22 | }
23 | }
24 |
25 | public int Size => InvocationScript.GetVarSize() + VerificationScript.GetVarSize();
26 |
27 | void ISerializable.Deserialize(BinaryReader reader)
28 | {
29 | InvocationScript = reader.ReadVarBytes(65536);
30 | VerificationScript = reader.ReadVarBytes(65536);
31 | }
32 |
33 | void ISerializable.Serialize(BinaryWriter writer)
34 | {
35 | writer.WriteVarBytes(InvocationScript);
36 | writer.WriteVarBytes(VerificationScript);
37 | }
38 |
39 | public JObject ToJson()
40 | {
41 | JObject json = new JObject();
42 | json["invocation"] = InvocationScript.ToHexString();
43 | json["verification"] = VerificationScript.ToHexString();
44 | return json;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/MedPoints/MedPoints.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27428.2043
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Storage", "Storage\Storage.csproj", "{8513EC5C-2BB5-4310-B10D-8924624ABDAD}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Storage.Cli", "Storage.Cli\Storage.Cli.csproj", "{C9348D23-403E-451C-804E-6BC3D77C6FD8}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {8513EC5C-2BB5-4310-B10D-8924624ABDAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {8513EC5C-2BB5-4310-B10D-8924624ABDAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {8513EC5C-2BB5-4310-B10D-8924624ABDAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {8513EC5C-2BB5-4310-B10D-8924624ABDAD}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {C9348D23-403E-451C-804E-6BC3D77C6FD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {C9348D23-403E-451C-804E-6BC3D77C6FD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {C9348D23-403E-451C-804E-6BC3D77C6FD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {C9348D23-403E-451C-804E-6BC3D77C6FD8}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {73B319C4-5B5B-4AF3-A757-CA04666D525E}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/Options.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using static Storage.Data.LevelDB.NativeWrapper;
3 |
4 | namespace Storage.Data.LevelDB
5 | {
6 | public class Options
7 | {
8 | public static readonly Options Default = new Options();
9 | internal readonly IntPtr Handle = leveldb_options_create();
10 |
11 | public bool CreateIfMissing
12 | {
13 | set => leveldb_options_set_create_if_missing(Handle, value);
14 | }
15 |
16 | public bool ErrorIfExists
17 | {
18 | set => leveldb_options_set_error_if_exists(Handle, value);
19 | }
20 |
21 | public bool ParanoidChecks
22 | {
23 | set => leveldb_options_set_paranoid_checks(Handle, value);
24 | }
25 |
26 | public int WriteBufferSize
27 | {
28 | set => leveldb_options_set_write_buffer_size(Handle, (UIntPtr)value);
29 | }
30 |
31 | public int MaxOpenFiles
32 | {
33 | set => leveldb_options_set_max_open_files(Handle, value);
34 | }
35 |
36 | public int BlockSize
37 | {
38 | set => leveldb_options_set_block_size(Handle, (UIntPtr)value);
39 | }
40 |
41 | public int BlockRestartInterval
42 | {
43 | set => leveldb_options_set_block_restart_interval(Handle, value);
44 | }
45 |
46 | public CompressionType Compression
47 | {
48 | set => leveldb_options_set_compression(Handle, value);
49 | }
50 |
51 | public IntPtr FilterPolicy
52 | {
53 | set => leveldb_options_set_filter_policy(Handle, value);
54 | }
55 |
56 | ~Options()
57 | {
58 | leveldb_options_destroy(Handle);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Utils/HashHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Security.Cryptography;
4 | using System.Text;
5 | using Storage.Core;
6 | using Storage.Core.Transactions;
7 |
8 | namespace Storage.Utils
9 | {
10 | public static class HashHelper
11 | {
12 | public static string GetSha256Hash(this string value)
13 | {
14 | var sb = new StringBuilder();
15 |
16 | using (var hash = SHA256.Create())
17 | {
18 | Encoding enc = Encoding.UTF8;
19 | Byte[] result = hash.ComputeHash(enc.GetBytes(value));
20 |
21 | foreach (Byte b in result)
22 | sb.Append(b.ToString("x2"));
23 | }
24 |
25 | return sb.ToString();
26 | }
27 |
28 | public static string GenerateMerkleRoot(this List transactions)
29 | {
30 | int count = transactions.Count;
31 | var previousTreeLayer = new List();
32 | foreach (var transaction in transactions)
33 | {
34 | previousTreeLayer.Add(transaction.Id);
35 | }
36 | var treeLayer = previousTreeLayer;
37 | while (count > 1)
38 | {
39 | treeLayer = new List();
40 | for (int i = 1; i < previousTreeLayer.Count; i++)
41 | {
42 | var hash = $"{previousTreeLayer[i - 1]}{previousTreeLayer[i]}".GetSha256Hash();
43 | treeLayer.Add(hash);
44 | }
45 | count = treeLayer.Count;
46 | previousTreeLayer = treeLayer;
47 | }
48 |
49 | return treeLayer.Count == 1 ? treeLayer[0] : "";
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/NetworkAddressWithTime.cs:
--------------------------------------------------------------------------------
1 | using Neo.IO;
2 | using System;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Net;
6 |
7 | namespace Neo.Network.Payloads
8 | {
9 | public class NetworkAddressWithTime : ISerializable
10 | {
11 | public const ulong NODE_NETWORK = 1;
12 |
13 | public uint Timestamp;
14 | public ulong Services;
15 | public IPEndPoint EndPoint;
16 |
17 | public int Size => sizeof(uint) + sizeof(ulong) + 16 + sizeof(ushort);
18 |
19 | public static NetworkAddressWithTime Create(IPEndPoint endpoint, ulong services, uint timestamp)
20 | {
21 | return new NetworkAddressWithTime
22 | {
23 | Timestamp = timestamp,
24 | Services = services,
25 | EndPoint = endpoint
26 | };
27 | }
28 |
29 | void ISerializable.Deserialize(BinaryReader reader)
30 | {
31 | Timestamp = reader.ReadUInt32();
32 | Services = reader.ReadUInt64();
33 | byte[] data = reader.ReadBytes(16);
34 | if (data.Length != 16) throw new FormatException();
35 | IPAddress address = new IPAddress(data);
36 | data = reader.ReadBytes(2);
37 | if (data.Length != 2) throw new FormatException();
38 | ushort port = data.Reverse().ToArray().ToUInt16(0);
39 | EndPoint = new IPEndPoint(address, port);
40 | }
41 |
42 | void ISerializable.Serialize(BinaryWriter writer)
43 | {
44 | writer.Write(Timestamp);
45 | writer.Write(Services);
46 | writer.Write(EndPoint.Address.GetAddressBytes());
47 | writer.Write(BitConverter.GetBytes((ushort)EndPoint.Port).Reverse().ToArray());
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/MerkleBlockPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.Core;
2 | using Neo.Cryptography;
3 | using Neo.IO;
4 | using System.Collections;
5 | using System.IO;
6 | using System.Linq;
7 |
8 | namespace Neo.Network.Payloads
9 | {
10 | public class MerkleBlockPayload : BlockBase
11 | {
12 | public int TxCount;
13 | public UInt256[] Hashes;
14 | public byte[] Flags;
15 |
16 | public override int Size => base.Size + sizeof(int) + Hashes.GetVarSize() + Flags.GetVarSize();
17 |
18 | public static MerkleBlockPayload Create(Block block, BitArray flags)
19 | {
20 | MerkleTree tree = new MerkleTree(block.Transactions.Select(p => p.Hash).ToArray());
21 | tree.Trim(flags);
22 | byte[] buffer = new byte[(flags.Length + 7) / 8];
23 | flags.CopyTo(buffer, 0);
24 | return new MerkleBlockPayload
25 | {
26 | Version = block.Version,
27 | PrevHash = block.PrevHash,
28 | MerkleRoot = block.MerkleRoot,
29 | Timestamp = block.Timestamp,
30 | Index = block.Index,
31 | ConsensusData = block.ConsensusData,
32 | NextConsensus = block.NextConsensus,
33 | Script = block.Script,
34 | TxCount = block.Transactions.Length,
35 | Hashes = tree.ToHashArray(),
36 | Flags = buffer
37 | };
38 | }
39 |
40 | public override void Deserialize(BinaryReader reader)
41 | {
42 | base.Deserialize(reader);
43 | TxCount = (int)reader.ReadVarInt(int.MaxValue);
44 | Hashes = reader.ReadSerializableArray();
45 | Flags = reader.ReadVarBytes();
46 | }
47 |
48 | public override void Serialize(BinaryWriter writer)
49 | {
50 | base.Serialize(writer);
51 | writer.WriteVarInt(TxCount);
52 | writer.Write(Hashes);
53 | writer.WriteVarBytes(Flags);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Database/CoinTransactionRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Data;
3 | using System.Linq;
4 | using Dapper;
5 | using Microsoft.Extensions.Configuration;
6 | using Npgsql;
7 | using Storage.Core;
8 | using Storage.Core.Transactions;
9 |
10 | namespace Storage.Database
11 | {
12 | public class CoinTransactionRepository
13 | {
14 | private class TxInternal
15 | {
16 | public string UserId { get; set; }
17 | public TransactionType Type { get; set; }
18 | public string Transaction { get; set; }
19 | }
20 |
21 | private string connectionString;
22 | private IDbConnection Connection => new NpgsqlConnection(connectionString);
23 |
24 | public CoinTransactionRepository(IConfiguration configuration)
25 | {
26 | connectionString = configuration.GetValue("DBInfo:ConnectionString");
27 | }
28 |
29 |
30 | public void Add(string userId, CoinTransaction tx)
31 | {
32 | using (IDbConnection dbConnection = Connection)
33 | {
34 | dbConnection.Open();
35 | dbConnection.Execute(
36 | "INSERT INTO transactions (user_id, type, transaction) VALUES(@UserId,@Type,@Transaction)",
37 | new TxInternal{UserId = userId, Type = tx.Type, Transaction = tx.Serialize()});
38 | }
39 |
40 | }
41 |
42 |
43 | public List GetByUserId(string userId)
44 | {
45 | using (IDbConnection dbConnection = Connection)
46 | {
47 | dbConnection.Open();
48 | return dbConnection
49 | .Query("SELECT * FROM transactions where user_id=@UserId and type=@Type",
50 | new TxInternal {UserId = userId, Type = TransactionType.Coins})
51 | .Select(tx => TransactionExtensions.Deserialize(tx.Transaction)).ToList();
52 | }
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Utils/Settings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Microsoft.Extensions.Configuration;
4 |
5 | namespace Storage.Utils
6 | {
7 | public class Settings
8 | {
9 | public uint Magic { get; }
10 | public byte AddressVersion { get; }
11 | public int MaxTransactionsPerBlock { get; }
12 | public string[] StandbyValidators { get; }
13 | public string[] SeedList { get; }
14 | //public IReadOnlyDictionary SystemFee { get; private set; }
15 | public uint SecondsPerBlock { get; }
16 |
17 | public static Settings Default { get; }
18 |
19 | static Settings()
20 | {
21 | IConfigurationSection section = new ConfigurationBuilder().AddJsonFile("protocol.json").Build().GetSection("ProtocolConfiguration");
22 | Default = new Settings(section);
23 | }
24 |
25 | public Settings(IConfigurationSection section)
26 | {
27 | this.Magic = uint.Parse(section.GetSection("Magic").Value);
28 | this.AddressVersion = byte.Parse(section.GetSection("AddressVersion").Value);
29 | this.MaxTransactionsPerBlock = GetValueOrDefault(section.GetSection("MaxTransactionsPerBlock"), 500, p => int.Parse(p));
30 | this.StandbyValidators = section.GetSection("StandbyValidators").GetChildren().Select(p => p.Value).ToArray();
31 | this.SeedList = section.GetSection("SeedList").GetChildren().Select(p => p.Value).ToArray();
32 | //this.SystemFee = section.GetSection("SystemFee").GetChildren().ToDictionary(p => (TransactionType)Enum.Parse(typeof(TransactionType), p.Key, true), p => Fixed8.Parse(p.Value));
33 | this.SecondsPerBlock = GetValueOrDefault(section.GetSection("SecondsPerBlock"), 15u, p => uint.Parse(p));
34 | }
35 |
36 | public T GetValueOrDefault(IConfigurationSection section, T defaultValue, Func selector)
37 | {
38 | if (section.Value == null) return defaultValue;
39 | return selector(section.Value);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/Iterator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using static Storage.Data.LevelDB.NativeWrapper;
3 |
4 | namespace Storage.Data.LevelDB
5 | {
6 | public class Iterator : IDisposable
7 | {
8 | private IntPtr handle;
9 |
10 | internal Iterator(IntPtr handle)
11 | {
12 | this.handle = handle;
13 | }
14 |
15 | private void CheckError()
16 | {
17 | IntPtr error;
18 | leveldb_iter_get_error(handle, out error);
19 | NativeHelper.CheckError(error);
20 | }
21 |
22 | public void Dispose()
23 | {
24 | if (handle != IntPtr.Zero)
25 | {
26 | leveldb_iter_destroy(handle);
27 | handle = IntPtr.Zero;
28 | }
29 | }
30 |
31 | public Slice Key()
32 | {
33 | UIntPtr length;
34 | IntPtr key = leveldb_iter_key(handle, out length);
35 | CheckError();
36 | return new Slice(key, length);
37 | }
38 |
39 | public void Next()
40 | {
41 | leveldb_iter_next(handle);
42 | CheckError();
43 | }
44 |
45 | public void Prev()
46 | {
47 | leveldb_iter_prev(handle);
48 | CheckError();
49 | }
50 |
51 | public void Seek(Slice target)
52 | {
53 | leveldb_iter_seek(handle, target.buffer, (UIntPtr)target.buffer.Length);
54 | }
55 |
56 | public void SeekToFirst()
57 | {
58 | leveldb_iter_seek_to_first(handle);
59 | }
60 |
61 | public void SeekToLast()
62 | {
63 | leveldb_iter_seek_to_last(handle);
64 | }
65 |
66 | public bool Valid()
67 | {
68 | return leveldb_iter_valid(handle);
69 | }
70 |
71 | public Slice Value()
72 | {
73 | UIntPtr length;
74 | IntPtr value = leveldb_iter_value(handle, out length);
75 | CheckError();
76 | return new Slice(value, length);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Core/Block.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Storage.Core.Transactions;
5 | using Storage.Utils;
6 |
7 | namespace Storage.Core
8 | {
9 | public class Block
10 | {
11 | public string Hash { get; private set; }
12 | public string PreviousHash { get; private set; }
13 | public DateTime Time { get; private set; }
14 | public int Nonce { get; private set; }
15 | public string MerkleRoot { get; private set; }
16 | public List CoinTransactions { get;} = new List();
17 | public List OtherTransactions { get;} = new List();
18 |
19 | public Block( string previousHash)
20 | {
21 | PreviousHash = previousHash;
22 | Time = DateTime.UtcNow;
23 | Hash = CalculateHash();
24 | }
25 |
26 | public string CalculateHash()
27 | {
28 | var hash = $"{PreviousHash}{Time}{Nonce}{MerkleRoot}".GetSha256Hash();
29 | return hash;
30 | }
31 |
32 | public void MineBlock(int difficulty)
33 | {
34 | MerkleRoot = CoinTransactions.GenerateMerkleRoot();
35 | var target = string.Empty.PadLeft(difficulty, '0');
36 | while (Hash.Substring(0, difficulty) != target)
37 | {
38 | Nonce++;
39 | Hash = CalculateHash();
40 | }
41 | Console.WriteLine($"Block Mined - {Hash}");
42 | }
43 |
44 | public void AddTransaction(Dictionary utxos, CoinTransaction coinTransaction)
45 | {
46 | if (PreviousHash != "0")
47 | {
48 | if(!coinTransaction.ProcessTransaction(utxos))
49 | throw new Exception();
50 | }
51 | CoinTransactions.Add(coinTransaction);
52 | }
53 |
54 | public void AddTransaction(ITransaction transaction)
55 | {
56 | OtherTransactions.Add(transaction);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Database/MempoolRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using Dapper;
5 | using Microsoft.Extensions.Configuration;
6 | using Npgsql;
7 | using Storage.Mempool;
8 |
9 | namespace Storage.Database
10 | {
11 | public class MempoolRepository
12 | {
13 | private string connectionString;
14 | private IDbConnection Connection => new NpgsqlConnection(connectionString);
15 |
16 | public MempoolRepository(IConfiguration configuration)
17 | {
18 | connectionString = configuration.GetValue("DBInfo:ConnectionString");
19 | }
20 |
21 |
22 | public void Add(MempoolTransaction tx)
23 | {
24 | tx.Id = Guid.NewGuid().ToString();
25 | using (IDbConnection dbConnection = Connection)
26 | {
27 | dbConnection.Open();
28 | dbConnection.Execute(
29 | "INSERT INTO mempool (id, user_id, type, transaction) VALUES(@Id, @UserId, @Type, @Transaction)",
30 | tx);
31 | }
32 | }
33 |
34 | public MempoolTransaction GetNext()
35 | {
36 | using (IDbConnection dbConnection = Connection)
37 | {
38 | dbConnection.Open();
39 | return dbConnection
40 | .QueryFirst("SELECT * FROM mempool LIMIT 1");
41 | }
42 | }
43 |
44 | public List GetNextList()
45 | {
46 | using (IDbConnection dbConnection = Connection)
47 | {
48 | dbConnection.Open();
49 | return dbConnection
50 | .QueryFirst("SELECT * FROM mempool LIMIT 10");
51 | }
52 | }
53 |
54 |
55 | public void Delete(string txId)
56 | {
57 | using (IDbConnection dbConnection = Connection)
58 | {
59 | dbConnection.Open();
60 | dbConnection.Execute("DELETE FROM mempool WHERE id = @TxId", new {TxId = txId});
61 | }
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/VersionPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.Core;
2 | using Neo.IO;
3 | using System;
4 | using System.IO;
5 |
6 | namespace Neo.Network.Payloads
7 | {
8 | public class VersionPayload : ISerializable
9 | {
10 | public uint Version;
11 | public ulong Services;
12 | public uint Timestamp;
13 | public ushort Port;
14 | public uint Nonce;
15 | public string UserAgent;
16 | public uint StartHeight;
17 | public bool Relay;
18 |
19 | public int Size => sizeof(uint) + sizeof(ulong) + sizeof(uint) + sizeof(ushort) + sizeof(uint) + UserAgent.GetVarSize() + sizeof(uint) + sizeof(bool);
20 |
21 | public static VersionPayload Create(int port, uint nonce, string userAgent)
22 | {
23 | return new VersionPayload
24 | {
25 | Version = LocalNode.ProtocolVersion,
26 | Services = NetworkAddressWithTime.NODE_NETWORK,
27 | Timestamp = DateTime.Now.ToTimestamp(),
28 | Port = (ushort)port,
29 | Nonce = nonce,
30 | UserAgent = userAgent,
31 | StartHeight = Blockchain.Default?.Height ?? 0,
32 | Relay = true
33 | };
34 | }
35 |
36 | void ISerializable.Deserialize(BinaryReader reader)
37 | {
38 | Version = reader.ReadUInt32();
39 | Services = reader.ReadUInt64();
40 | Timestamp = reader.ReadUInt32();
41 | Port = reader.ReadUInt16();
42 | Nonce = reader.ReadUInt32();
43 | UserAgent = reader.ReadVarString(1024);
44 | StartHeight = reader.ReadUInt32();
45 | Relay = reader.ReadBoolean();
46 | }
47 |
48 | void ISerializable.Serialize(BinaryWriter writer)
49 | {
50 | writer.Write(Version);
51 | writer.Write(Services);
52 | writer.Write(Timestamp);
53 | writer.Write(Port);
54 | writer.Write(Nonce);
55 | writer.WriteVarString(UserAgent);
56 | writer.Write(StartHeight);
57 | writer.Write(Relay);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Cli/TestChain.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Storage.Core;
5 | using Storage.Core.Transactions;
6 |
7 | namespace Storage.Cli
8 | {
9 | public class TestChain
10 | {
11 | private static List Blocks = new List();
12 | private static Dictionary UTXOs = new Dictionary();
13 |
14 | private static int Difficulty = 3;
15 | private static Wallet WalletA;
16 | private static Wallet WalletB;
17 | private static CoinTransaction _genesisCoinTransaction;
18 |
19 | public static void Test()
20 | {
21 | WalletA = new Wallet();
22 | WalletB = new Wallet();
23 | var coinBase = new Wallet();
24 |
25 | _genesisCoinTransaction = new CoinTransaction(coinBase.PublicKey, WalletA.PublicKey, 100, null);
26 | _genesisCoinTransaction.Sign(coinBase);
27 | _genesisCoinTransaction.Id = "0";
28 | _genesisCoinTransaction.Outputs.Add(
29 | new TransactionOutput(_genesisCoinTransaction.Reciepient, _genesisCoinTransaction.Amount, _genesisCoinTransaction.Id)
30 | );
31 | UTXOs[_genesisCoinTransaction.Outputs[0].Id] = _genesisCoinTransaction.Outputs[0];
32 |
33 | var genesis = new Block("0");
34 | genesis.AddTransaction(UTXOs, _genesisCoinTransaction);
35 | AddBlock(genesis);
36 |
37 | var balance = WalletA.GetBalance(UTXOs);
38 | var block1 = new Block(genesis.Hash);
39 | block1.AddTransaction(UTXOs, WalletA.Send(UTXOs, WalletB.PublicKey, 40));
40 | AddBlock(block1);
41 |
42 | balance = WalletA.GetBalance(UTXOs);
43 | var block2 = new Block(block1.Hash);
44 | block2.AddTransaction(UTXOs, WalletA.Send(UTXOs, WalletB.PublicKey, 1000));
45 | AddBlock(block2);
46 |
47 | balance = WalletA.GetBalance(UTXOs);
48 | var block3 = new Block(block2.Hash);
49 | block3.AddTransaction(UTXOs, WalletB.Send(UTXOs, WalletA.PublicKey,20));
50 | AddBlock(block3);
51 |
52 | balance = WalletA.GetBalance(UTXOs);
53 | }
54 |
55 | public static void AddBlock(Block newBlock)
56 | {
57 | newBlock.MineBlock(Difficulty);
58 | Blocks.Add(newBlock);
59 | }
60 |
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Database/AppointmentToTheDoctorRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Data;
3 | using System.Linq;
4 | using Dapper;
5 | using Microsoft.Extensions.Configuration;
6 | using Npgsql;
7 | using Storage.Core.Transactions;
8 |
9 | namespace Storage.Database
10 | {
11 | public class AppointmentToTheDoctorRepository
12 | {
13 | private class TxInternal
14 | {
15 | public string UserId { get; set; }
16 | public TransactionType Type { get; set; }
17 | public string Transaction { get; set; }
18 | }
19 |
20 | private string connectionString;
21 | private IDbConnection Connection => new NpgsqlConnection(connectionString);
22 |
23 | public AppointmentToTheDoctorRepository(IConfiguration configuration)
24 | {
25 | connectionString = configuration.GetValue("DBInfo:ConnectionString");
26 | }
27 |
28 |
29 | public void Add(string userId, AppointmentToTheDoctorTransaction tx)
30 | {
31 | using (IDbConnection dbConnection = Connection)
32 | {
33 | dbConnection.Open();
34 | dbConnection.Execute(
35 | "INSERT INTO transactions (user_id, type, transaction) VALUES(@UserId,@Type,@Transaction)",
36 | new TxInternal{UserId = userId, Type = tx.Type, Transaction = tx.Serialize()});
37 | }
38 |
39 | }
40 |
41 | public List GetByDoctorId(string doctorId)
42 | {
43 | using (IDbConnection dbConnection = Connection)
44 | {
45 | dbConnection.Open();
46 | return dbConnection
47 | .Query("SELECT * FROM transactions where type == @Type and transaction->>'doctorId' = '@DoctorId';",
48 | new {DoctorId = doctorId, Type = TransactionType.VisitToTheDoctor})
49 | .Select(tx => TransactionExtensions.Deserialize(tx.Transaction)).ToList();
50 | }
51 | }
52 |
53 |
54 | public List GetByUserId(string userId)
55 | {
56 | using (IDbConnection dbConnection = Connection)
57 | {
58 | dbConnection.Open();
59 | return dbConnection
60 | .Query("SELECT * FROM transactions where user_id=@UserId and type=@Type",
61 | new TxInternal {UserId = userId, Type = TransactionType.VisitToTheDoctor})
62 | .Select(tx => TransactionExtensions.Deserialize(tx.Transaction)).ToList();
63 | }
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/WebSocketRemoteNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Net.WebSockets;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Neo.Network;
8 | using Storage.Utils;
9 |
10 | namespace Storage.Network
11 | {
12 | internal class WebSocketRemoteNode : RemoteNode
13 | {
14 | private readonly WebSocket _socket;
15 | private readonly bool _connected;
16 | private int _disposed;
17 |
18 | public WebSocketRemoteNode(LocalNode localNode, WebSocket socket, IPEndPoint remoteEndpoint)
19 | : base(localNode)
20 | {
21 | _socket = socket;
22 | RemoteEndpoint = new IPEndPoint(remoteEndpoint.Address.MapToIPv6(), remoteEndpoint.Port);
23 | _connected = true;
24 | }
25 |
26 | public override void Disconnect(bool error)
27 | {
28 | if (Interlocked.Exchange(ref _disposed, 1) == 0)
29 | {
30 | _socket.Dispose();
31 | base.Disconnect(error);
32 | }
33 | }
34 |
35 | protected override async Task ReceiveMessageAsync(TimeSpan timeout)
36 | {
37 | CancellationTokenSource source = new CancellationTokenSource(timeout);
38 | try
39 | {
40 | return await Message.DeserializeFromAsync(_socket, source.Token);
41 | }
42 | catch (ArgumentException) { }
43 | catch (ObjectDisposedException) { }
44 | catch (Exception ex) when (ex is FormatException || ex is IOException || ex is WebSocketException || ex is OperationCanceledException)
45 | {
46 | Disconnect(false);
47 | }
48 | finally
49 | {
50 | source.Dispose();
51 | }
52 | return null;
53 | }
54 |
55 | protected override async Task SendMessageAsync(Message message)
56 | {
57 | if (!_connected) throw new InvalidOperationException();
58 | if (_disposed > 0) return false;
59 | ArraySegment segment = new ArraySegment(message.ToArray());
60 | CancellationTokenSource source = new CancellationTokenSource(10000);
61 | try
62 | {
63 | await _socket.SendAsync(segment, WebSocketMessageType.Binary, true, source.Token);
64 | return true;
65 | }
66 | catch (ObjectDisposedException) { }
67 | catch (Exception ex) when (ex is WebSocketException || ex is OperationCanceledException)
68 | {
69 | Disconnect(false);
70 | }
71 | finally
72 | {
73 | source.Dispose();
74 | }
75 | return false;
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/UInt256.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Linq;
4 |
5 | namespace Storage.Core
6 | {
7 | public class UInt256 : UIntBase, IComparable, IEquatable
8 | {
9 | public static readonly UInt256 Zero = new UInt256();
10 |
11 | public UInt256()
12 | : this(null)
13 | {
14 | }
15 |
16 | public UInt256(byte[] value)
17 | : base(32, value)
18 | {
19 | }
20 |
21 | public int CompareTo(UInt256 other)
22 | {
23 | byte[] x = ToArray();
24 | byte[] y = other.ToArray();
25 | for (int i = x.Length - 1; i >= 0; i--)
26 | {
27 | if (x[i] > y[i])
28 | return 1;
29 | if (x[i] < y[i])
30 | return -1;
31 | }
32 | return 0;
33 | }
34 |
35 | bool IEquatable.Equals(UInt256 other)
36 | {
37 | return Equals(other);
38 | }
39 |
40 | public static new UInt256 Parse(string s)
41 | {
42 | if (s == null)
43 | throw new ArgumentNullException();
44 | if (s.StartsWith("0x"))
45 | s = s.Substring(2);
46 | if (s.Length != 64)
47 | throw new FormatException();
48 | return new UInt256(s.HexToBytes().Reverse().ToArray());
49 | }
50 |
51 | public static bool TryParse(string s, out UInt256 result)
52 | {
53 | if (s == null)
54 | {
55 | result = null;
56 | return false;
57 | }
58 | if (s.StartsWith("0x"))
59 | s = s.Substring(2);
60 | if (s.Length != 64)
61 | {
62 | result = null;
63 | return false;
64 | }
65 | byte[] data = new byte[32];
66 | for (int i = 0; i < 32; i++)
67 | if (!byte.TryParse(s.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier, null, out data[i]))
68 | {
69 | result = null;
70 | return false;
71 | }
72 | result = new UInt256(data.Reverse().ToArray());
73 | return true;
74 | }
75 |
76 | public static bool operator >(UInt256 left, UInt256 right)
77 | {
78 | return left.CompareTo(right) > 0;
79 | }
80 |
81 | public static bool operator >=(UInt256 left, UInt256 right)
82 | {
83 | return left.CompareTo(right) >= 0;
84 | }
85 |
86 | public static bool operator <(UInt256 left, UInt256 right)
87 | {
88 | return left.CompareTo(right) < 0;
89 | }
90 |
91 | public static bool operator <=(UInt256 left, UInt256 right)
92 | {
93 | return left.CompareTo(right) <= 0;
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/UInt160.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Linq;
4 |
5 | namespace Storage.Core
6 | {
7 | public class UInt160 : UIntBase, IComparable, IEquatable
8 | {
9 | public static readonly UInt160 Zero = new UInt160();
10 |
11 | public UInt160()
12 | : this(null)
13 | {
14 | }
15 |
16 | public UInt160(byte[] value)
17 | : base(20, value)
18 | {
19 | }
20 |
21 | public int CompareTo(UInt160 other)
22 | {
23 | byte[] x = ToArray();
24 | byte[] y = other.ToArray();
25 | for (int i = x.Length - 1; i >= 0; i--)
26 | {
27 | if (x[i] > y[i])
28 | return 1;
29 | if (x[i] < y[i])
30 | return -1;
31 | }
32 | return 0;
33 | }
34 |
35 | bool IEquatable.Equals(UInt160 other)
36 | {
37 | return Equals(other);
38 | }
39 |
40 | public static new UInt160 Parse(string value)
41 | {
42 | if (value == null)
43 | throw new ArgumentNullException();
44 | if (value.StartsWith("0x"))
45 | value = value.Substring(2);
46 | if (value.Length != 40)
47 | throw new FormatException();
48 | return new UInt160(value.HexToBytes().Reverse().ToArray());
49 | }
50 |
51 | public static bool TryParse(string s, out UInt160 result)
52 | {
53 | if (s == null)
54 | {
55 | result = null;
56 | return false;
57 | }
58 | if (s.StartsWith("0x"))
59 | s = s.Substring(2);
60 | if (s.Length != 40)
61 | {
62 | result = null;
63 | return false;
64 | }
65 | byte[] data = new byte[20];
66 | for (int i = 0; i < 20; i++)
67 | if (!byte.TryParse(s.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier, null, out data[i]))
68 | {
69 | result = null;
70 | return false;
71 | }
72 | result = new UInt160(data.Reverse().ToArray());
73 | return true;
74 | }
75 |
76 | public static bool operator >(UInt160 left, UInt160 right)
77 | {
78 | return left.CompareTo(right) > 0;
79 | }
80 |
81 | public static bool operator >=(UInt160 left, UInt160 right)
82 | {
83 | return left.CompareTo(right) >= 0;
84 | }
85 |
86 | public static bool operator <(UInt160 left, UInt160 right)
87 | {
88 | return left.CompareTo(right) < 0;
89 | }
90 |
91 | public static bool operator <=(UInt160 left, UInt160 right)
92 | {
93 | return left.CompareTo(right) <= 0;
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/CoreHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Text;
5 |
6 | namespace Storage.Core
7 | {
8 | public static class CoreHelper
9 | {
10 | public static byte[] GetHashData(this IVerifiable verifiable)
11 | {
12 | using (MemoryStream ms = new MemoryStream())
13 | using (BinaryWriter writer = new BinaryWriter(ms))
14 | {
15 | verifiable.SerializeUnsigned(writer);
16 | writer.Flush();
17 | return ms.ToArray();
18 | }
19 | }
20 |
21 | //public static byte[] Sign(this IVerifiable verifiable, KeyPair key)
22 | //{
23 | // throw new NotImplementedException();
24 | // //using (key.Decrypt())
25 | // //{
26 | // // return Crypto.Default.Sign(verifiable.GetHashData(), key.PrivateKey, key.PublicKey.EncodePoint(false).Skip(1).ToArray());
27 | // //}
28 | //}
29 |
30 | public static UInt160 ToScriptHash(this byte[] script)
31 | {
32 | throw new NotImplementedException();
33 | //return new UInt160(Crypto.Default.Hash160(script));
34 | }
35 |
36 | internal static bool VerifyScripts(this IVerifiable verifiable)
37 | {
38 | throw new NotImplementedException();
39 | //UInt160[] hashes;
40 | //try
41 | //{
42 | // hashes = verifiable.GetScriptHashesForVerifying();
43 | //}
44 | //catch (InvalidOperationException)
45 | //{
46 | // return false;
47 | //}
48 | //if (hashes.Length != verifiable.Scripts.Length) return false;
49 | //for (int i = 0; i < hashes.Length; i++)
50 | //{
51 | // byte[] verification = verifiable.Scripts[i].VerificationScript;
52 | // if (verification.Length == 0)
53 | // {
54 | // using (ScriptBuilder sb = new ScriptBuilder())
55 | // {
56 | // sb.EmitAppCall(hashes[i].ToArray());
57 | // verification = sb.ToArray();
58 | // }
59 | // }
60 | // else
61 | // {
62 | // if (hashes[i] != verifiable.Scripts[i].ScriptHash) return false;
63 | // }
64 | // using (StateReader service = new StateReader())
65 | // {
66 | // ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, verifiable, Blockchain.Default, service, Fixed8.Zero);
67 | // engine.LoadScript(verification, false);
68 | // engine.LoadScript(verifiable.Scripts[i].InvocationScript, true);
69 | // if (!engine.Execute()) return false;
70 | // if (engine.EvaluationStack.Count != 1 || !engine.EvaluationStack.Pop().GetBoolean()) return false;
71 | // }
72 | //}
73 | //return true;
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Mempool/Mempool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Storage.Core;
4 | using Storage.Core.Transactions;
5 | using Storage.Database;
6 |
7 | namespace Storage.Mempool
8 | {
9 | public class Mempool
10 | {
11 | private readonly MempoolRepository _mempoolRepository;
12 | private readonly BlockRepository _blockRepository;
13 | private static Dictionary UTXOs = new Dictionary();
14 |
15 | public Mempool(MempoolRepository mempoolRepository, BlockRepository blockRepository)
16 | {
17 | _mempoolRepository = mempoolRepository;
18 | _blockRepository = blockRepository;
19 | }
20 |
21 |
22 | public void AddToMempool(string data, string userId, TransactionType type)
23 | {
24 | _mempoolRepository.Add(new MempoolTransaction()
25 | {
26 | Transaction = data,
27 | UserId = userId,
28 | Type = type
29 | });
30 | }
31 |
32 | public void Mine(Wallet wallet)
33 | {
34 | var txs = _mempoolRepository.GetNextList();
35 | var lastBlockHash = _blockRepository.GetLastBlockHash();
36 | if (lastBlockHash == null)
37 | lastBlockHash = InsertGenesis(wallet);
38 |
39 | var newBlock = new Block(lastBlockHash);
40 | foreach (var tx in txs)
41 | {
42 | switch (tx.Type)
43 | {
44 | case TransactionType.Coins:
45 | break;
46 | case TransactionType.VisitToTheDoctor:
47 | break;
48 | default:
49 | throw new ArgumentOutOfRangeException();
50 | }
51 | }
52 |
53 |
54 | var coinBase = new Wallet();
55 | var mainedBlockMoney = new CoinTransaction(coinBase.PublicKey, wallet.PublicKey, 100, null);
56 | mainedBlockMoney.Sign(coinBase);
57 | mainedBlockMoney.Id = Guid.NewGuid().ToString();
58 | mainedBlockMoney.Outputs.Add(
59 | new TransactionOutput(mainedBlockMoney.Reciepient, mainedBlockMoney.Amount, mainedBlockMoney.Id)
60 | );
61 | UTXOs[mainedBlockMoney.Outputs[0].Id] = mainedBlockMoney.Outputs[0];
62 |
63 | newBlock.AddTransaction(UTXOs, mainedBlockMoney);
64 |
65 | newBlock.MineBlock(new Random().Next(0, 5));
66 |
67 |
68 | _blockRepository.Add(newBlock);
69 | }
70 |
71 | private string InsertGenesis(Wallet wallet)
72 | {
73 | var coinBase = new Wallet();
74 | var genesisCoinTransaction = new CoinTransaction(coinBase.PublicKey, wallet.PublicKey, 100, null);
75 | genesisCoinTransaction.Sign(coinBase);
76 | genesisCoinTransaction.Id = "0";
77 | genesisCoinTransaction.Outputs.Add(
78 | new TransactionOutput(genesisCoinTransaction.Reciepient, genesisCoinTransaction.Amount, genesisCoinTransaction.Id)
79 | );
80 | UTXOs[genesisCoinTransaction.Outputs[0].Id] = genesisCoinTransaction.Outputs[0];
81 |
82 | var genesis = new Block("0");
83 | genesis.AddTransaction(UTXOs, genesisCoinTransaction);
84 |
85 | _blockRepository.Add(genesis);
86 | return _blockRepository.GetLastBlockHash();
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/BigDecimal.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 |
4 | namespace Storage.Core
5 | {
6 | public struct BigDecimal
7 | {
8 | private readonly BigInteger _value;
9 | private readonly byte _decimals;
10 |
11 | public BigInteger Value => _value;
12 | public byte Decimals => _decimals;
13 | public int Sign => _value.Sign;
14 |
15 | public BigDecimal(BigInteger value, byte decimals)
16 | {
17 | this._value = value;
18 | this._decimals = decimals;
19 | }
20 |
21 | public BigDecimal ChangeDecimals(byte decimals)
22 | {
23 | if (_decimals == decimals) return this;
24 | BigInteger value;
25 | if (_decimals < decimals)
26 | {
27 | value = this._value * BigInteger.Pow(10, decimals - this._decimals);
28 | }
29 | else
30 | {
31 | BigInteger divisor = BigInteger.Pow(10, this._decimals - decimals);
32 | value = BigInteger.DivRem(this._value, divisor, out BigInteger remainder);
33 | if (remainder > BigInteger.Zero)
34 | throw new ArgumentOutOfRangeException();
35 | }
36 | return new BigDecimal(value, decimals);
37 | }
38 |
39 | public static BigDecimal Parse(string s, byte decimals)
40 | {
41 | if (!TryParse(s, decimals, out BigDecimal result))
42 | throw new FormatException();
43 | return result;
44 | }
45 |
46 | public Fixed8 ToFixed8()
47 | {
48 | try
49 | {
50 | return new Fixed8((long)ChangeDecimals(8)._value);
51 | }
52 | catch (Exception ex)
53 | {
54 | throw new InvalidCastException(ex.Message, ex);
55 | }
56 | }
57 |
58 | public override string ToString()
59 | {
60 | BigInteger divisor = BigInteger.Pow(10, _decimals);
61 | BigInteger result = BigInteger.DivRem(_value, divisor, out BigInteger remainder);
62 | if (remainder == 0) return result.ToString();
63 | return $"{result}.{remainder.ToString("d" + _decimals)}".TrimEnd('0');
64 | }
65 |
66 | public static bool TryParse(string s, byte decimals, out BigDecimal result)
67 | {
68 | int e = 0;
69 | int index = s.IndexOfAny(new[] { 'e', 'E' });
70 | if (index >= 0)
71 | {
72 | if (!sbyte.TryParse(s.Substring(index + 1), out sbyte e_temp))
73 | {
74 | result = default(BigDecimal);
75 | return false;
76 | }
77 | e = e_temp;
78 | s = s.Substring(0, index);
79 | }
80 | index = s.IndexOf('.');
81 | if (index >= 0)
82 | {
83 | s = s.TrimEnd('0');
84 | e -= s.Length - index - 1;
85 | s = s.Remove(index, 1);
86 | }
87 | int ds = e + decimals;
88 | if (ds < 0)
89 | {
90 | result = default(BigDecimal);
91 | return false;
92 | }
93 | if (ds > 0)
94 | s += new string('0', ds);
95 | if (!BigInteger.TryParse(s, out BigInteger value))
96 | {
97 | result = default(BigDecimal);
98 | return false;
99 | }
100 | result = new BigDecimal(value, decimals);
101 | return true;
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Utils/RSAKeyExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Security.Cryptography;
4 | using System.Text;
5 | using System.Xml;
6 | using Newtonsoft.Json;
7 |
8 | namespace Storage.Utils
9 | {
10 | public class RSAParametersJson
11 | {
12 | public string Modulus { get; set; }
13 | public string Exponent { get; set; }
14 | public string P { get; set; }
15 | public string Q { get; set; }
16 | public string DP { get; set; }
17 | public string DQ { get; set; }
18 | public string InverseQ { get; set; }
19 | public string D { get; set; }
20 | }
21 |
22 |
23 | public static class RsaKeyExtensions
24 | {
25 | public static void FromJsonString(this RSA rsa, string jsonString)
26 | {
27 | try
28 | {
29 | var paramsJson = JsonConvert.DeserializeObject(jsonString);
30 |
31 | var parameters = new RSAParameters
32 | {
33 | Modulus = paramsJson.Modulus != null ? Convert.FromBase64String(paramsJson.Modulus) : null,
34 | Exponent = paramsJson.Exponent != null ? Convert.FromBase64String(paramsJson.Exponent) : null,
35 | P = paramsJson.P != null ? Convert.FromBase64String(paramsJson.P) : null,
36 | Q = paramsJson.Q != null ? Convert.FromBase64String(paramsJson.Q) : null,
37 | DP = paramsJson.DP != null ? Convert.FromBase64String(paramsJson.DP) : null,
38 | DQ = paramsJson.DQ != null ? Convert.FromBase64String(paramsJson.DQ) : null,
39 | InverseQ = paramsJson.InverseQ != null ? Convert.FromBase64String(paramsJson.InverseQ) : null,
40 | D = paramsJson.D != null ? Convert.FromBase64String(paramsJson.D) : null
41 | };
42 |
43 | rsa.ImportParameters(parameters);
44 | }
45 | catch
46 | {
47 | throw new Exception("Invalid JSON RSA key.");
48 | }
49 | }
50 |
51 | public static string ToJsonString(this RSA rsa, bool includePrivateParameters)
52 | {
53 | var parameters = rsa.ExportParameters(includePrivateParameters);
54 |
55 | var parasJson = new RSAParametersJson()
56 | {
57 | Modulus = parameters.Modulus != null ? Convert.ToBase64String(parameters.Modulus) : null,
58 | Exponent = parameters.Exponent != null ? Convert.ToBase64String(parameters.Exponent) : null,
59 | P = parameters.P != null ? Convert.ToBase64String(parameters.P) : null,
60 | Q = parameters.Q != null ? Convert.ToBase64String(parameters.Q) : null,
61 | DP = parameters.DP != null ? Convert.ToBase64String(parameters.DP) : null,
62 | DQ = parameters.DQ != null ? Convert.ToBase64String(parameters.DQ) : null,
63 | InverseQ = parameters.InverseQ != null ? Convert.ToBase64String(parameters.InverseQ) : null,
64 | D = parameters.D != null ? Convert.ToBase64String(parameters.D) : null
65 | };
66 |
67 | return JsonConvert.SerializeObject(parasJson);
68 | }
69 |
70 | public static string Base64Encode(this string plainText) {
71 | var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
72 | return Convert.ToBase64String(plainTextBytes);
73 | }
74 |
75 | public static string Base64Decode(this string base64EncodedData) {
76 | var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
77 | return Encoding.UTF8.GetString(base64EncodedBytes);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Payloads/ConsensusPayload.cs:
--------------------------------------------------------------------------------
1 | using Neo.Core;
2 | using Neo.Cryptography;
3 | using Neo.Cryptography.ECC;
4 | using Neo.IO;
5 | using Neo.SmartContract;
6 | using Neo.VM;
7 | using System;
8 | using System.IO;
9 | using Storage.Network;
10 |
11 | namespace Neo.Network.Payloads
12 | {
13 | public class ConsensusPayload : IInventory
14 | {
15 | public uint Version;
16 | public UInt256 PrevHash;
17 | public uint BlockIndex;
18 | public ushort ValidatorIndex;
19 | public uint Timestamp;
20 | public byte[] Data;
21 | public Witness Script;
22 |
23 | private UInt256 _hash = null;
24 | UInt256 IInventory.Hash
25 | {
26 | get
27 | {
28 | if (_hash == null)
29 | {
30 | _hash = new UInt256(Crypto.Default.Hash256(this.GetHashData()));
31 | }
32 | return _hash;
33 | }
34 | }
35 |
36 | InventoryType IInventory.InventoryType => InventoryType.Consensus;
37 |
38 | Witness[] IVerifiable.Scripts
39 | {
40 | get
41 | {
42 | return new[] { Script };
43 | }
44 | set
45 | {
46 | if (value.Length != 1) throw new ArgumentException();
47 | Script = value[0];
48 | }
49 | }
50 |
51 | public int Size => sizeof(uint) + PrevHash.Size + sizeof(uint) + sizeof(ushort) + sizeof(uint) + Data.GetVarSize() + 1 + Script.Size;
52 |
53 | void ISerializable.Deserialize(BinaryReader reader)
54 | {
55 | ((IVerifiable)this).DeserializeUnsigned(reader);
56 | if (reader.ReadByte() != 1) throw new FormatException();
57 | Script = reader.ReadSerializable();
58 | }
59 |
60 | void IVerifiable.DeserializeUnsigned(BinaryReader reader)
61 | {
62 | Version = reader.ReadUInt32();
63 | PrevHash = reader.ReadSerializable();
64 | BlockIndex = reader.ReadUInt32();
65 | ValidatorIndex = reader.ReadUInt16();
66 | Timestamp = reader.ReadUInt32();
67 | Data = reader.ReadVarBytes();
68 | }
69 |
70 | byte[] IScriptContainer.GetMessage()
71 | {
72 | return this.GetHashData();
73 | }
74 |
75 | UInt160[] IVerifiable.GetScriptHashesForVerifying()
76 | {
77 | if (Blockchain.Default == null)
78 | throw new InvalidOperationException();
79 | ECPoint[] validators = Blockchain.Default.GetValidators();
80 | if (validators.Length <= ValidatorIndex)
81 | throw new InvalidOperationException();
82 | return new[] { Contract.CreateSignatureRedeemScript(validators[ValidatorIndex]).ToScriptHash() };
83 | }
84 |
85 | void ISerializable.Serialize(BinaryWriter writer)
86 | {
87 | ((IVerifiable)this).SerializeUnsigned(writer);
88 | writer.Write((byte)1); writer.Write(Script);
89 | }
90 |
91 | void IVerifiable.SerializeUnsigned(BinaryWriter writer)
92 | {
93 | writer.Write(Version);
94 | writer.Write(PrevHash);
95 | writer.Write(BlockIndex);
96 | writer.Write(ValidatorIndex);
97 | writer.Write(Timestamp);
98 | writer.WriteVarBytes(Data);
99 | }
100 |
101 | public bool Verify()
102 | {
103 | if (Blockchain.Default == null) return false;
104 | if (BlockIndex <= Blockchain.Default.Height)
105 | return false;
106 | return this.VerifyScripts();
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/UIntBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using Storage.Utils;
5 |
6 | namespace Storage.Core
7 | {
8 | public abstract class UIntBase : IEquatable, ISerializable
9 | {
10 | private byte[] data_bytes;
11 |
12 | public int Size => data_bytes.Length;
13 |
14 | protected UIntBase(int bytes, byte[] value)
15 | {
16 | if (value == null)
17 | {
18 | this.data_bytes = new byte[bytes];
19 | return;
20 | }
21 | if (value.Length != bytes)
22 | throw new ArgumentException();
23 | this.data_bytes = value;
24 | }
25 |
26 | void ISerializable.Deserialize(BinaryReader reader)
27 | {
28 | reader.Read(data_bytes, 0, data_bytes.Length);
29 | }
30 |
31 | public bool Equals(UIntBase other)
32 | {
33 | if (ReferenceEquals(other, null))
34 | return false;
35 | if (ReferenceEquals(this, other))
36 | return true;
37 | if (data_bytes.Length != other.data_bytes.Length)
38 | return false;
39 | return data_bytes.SequenceEqual(other.data_bytes);
40 | }
41 |
42 | public override bool Equals(object obj)
43 | {
44 | if (ReferenceEquals(obj, null))
45 | return false;
46 | if (!(obj is UIntBase))
47 | return false;
48 | return this.Equals((UIntBase)obj);
49 | }
50 |
51 | public override int GetHashCode()
52 | {
53 | return data_bytes.ToInt32(0);
54 | }
55 |
56 | public static UIntBase Parse(string s)
57 | {
58 | if (s.Length == 40 || s.Length == 42)
59 | return UInt160.Parse(s);
60 | else if (s.Length == 64 || s.Length == 66)
61 | return UInt256.Parse(s);
62 | else
63 | throw new FormatException();
64 | }
65 |
66 | void ISerializable.Serialize(BinaryWriter writer)
67 | {
68 | writer.Write(data_bytes);
69 | }
70 |
71 | public byte[] ToArray()
72 | {
73 | return data_bytes;
74 | }
75 |
76 | public override string ToString()
77 | {
78 | return "0x" + data_bytes.Reverse().ToHexString();
79 | }
80 |
81 | public static bool TryParse(string s, out T result) where T : UIntBase
82 | {
83 | int size;
84 | if (typeof(T) == typeof(UInt160))
85 | size = 20;
86 | else if (typeof(T) == typeof(UInt256))
87 | size = 32;
88 | else if (s.Length == 40 || s.Length == 42)
89 | size = 20;
90 | else if (s.Length == 64 || s.Length == 66)
91 | size = 32;
92 | else
93 | size = 0;
94 | if (size == 20)
95 | {
96 | if (UInt160.TryParse(s, out UInt160 r))
97 | {
98 | result = (T)(UIntBase)r;
99 | return true;
100 | }
101 | }
102 | else if (size == 32)
103 | {
104 | if (UInt256.TryParse(s, out UInt256 r))
105 | {
106 | result = (T)(UIntBase)r;
107 | return true;
108 | }
109 | }
110 | result = null;
111 | return false;
112 | }
113 |
114 | public static bool operator ==(UIntBase left, UIntBase right)
115 | {
116 | if (ReferenceEquals(left, right))
117 | return true;
118 | if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
119 | return false;
120 | return left.Equals(right);
121 | }
122 |
123 | public static bool operator !=(UIntBase left, UIntBase right)
124 | {
125 | return !(left == right);
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/TcpRemoteNode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Net.Sockets;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Storage.Network;
8 | using Storage.Utils;
9 |
10 | namespace Neo.Network
11 | {
12 | internal class TcpRemoteNode : RemoteNode
13 | {
14 | private readonly Socket _socket;
15 | private NetworkStream _stream;
16 | private bool _connected;
17 | private int _disposed;
18 |
19 | public TcpRemoteNode(LocalNode localNode, IPEndPoint remoteEndpoint)
20 | : base(localNode)
21 | {
22 | this._socket = new Socket(remoteEndpoint.Address.IsIPv4MappedToIPv6 ? AddressFamily.InterNetwork : remoteEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
23 | this.ListenerEndpoint = remoteEndpoint;
24 | }
25 |
26 | public TcpRemoteNode(LocalNode localNode, Socket socket)
27 | : base(localNode)
28 | {
29 | _socket = socket;
30 | OnConnected();
31 | }
32 |
33 | public async Task ConnectAsync()
34 | {
35 | IPAddress address = ListenerEndpoint.Address;
36 | if (address.IsIPv4MappedToIPv6)
37 | address = address.MapToIPv4();
38 | try
39 | {
40 | await _socket.ConnectAsync(address, ListenerEndpoint.Port);
41 | OnConnected();
42 | }
43 | catch (SocketException)
44 | {
45 | Disconnect(false);
46 | return false;
47 | }
48 | return true;
49 | }
50 |
51 | public override void Disconnect(bool error)
52 | {
53 | if (Interlocked.Exchange(ref _disposed, 1) == 0)
54 | {
55 | if (_stream != null) _stream.Dispose();
56 | _socket.Dispose();
57 | base.Disconnect(error);
58 | }
59 | }
60 |
61 | private void OnConnected()
62 | {
63 | IPEndPoint remoteEndpoint = (IPEndPoint)_socket.RemoteEndPoint;
64 | RemoteEndpoint = new IPEndPoint(remoteEndpoint.Address.MapToIPv6(), remoteEndpoint.Port);
65 | _stream = new NetworkStream(_socket);
66 | _connected = true;
67 | }
68 |
69 | protected override async Task ReceiveMessageAsync(TimeSpan timeout)
70 | {
71 | CancellationTokenSource source = new CancellationTokenSource(timeout);
72 | //Stream.ReadAsync doesn't support CancellationToken
73 | //see: https://stackoverflow.com/questions/20131434/cancel-networkstream-readasync-using-tcplistener
74 | source.Token.Register(() => Disconnect(false));
75 | try
76 | {
77 | return await Message.DeserializeFromAsync(_stream, source.Token);
78 | }
79 | catch (ArgumentException) { }
80 | catch (ObjectDisposedException) { }
81 | catch (Exception ex) when (ex is FormatException || ex is IOException || ex is OperationCanceledException)
82 | {
83 | Disconnect(false);
84 | }
85 | finally
86 | {
87 | source.Dispose();
88 | }
89 | return null;
90 | }
91 |
92 | protected override async Task SendMessageAsync(Message message)
93 | {
94 | if (!_connected) throw new InvalidOperationException();
95 | if (_disposed > 0) return false;
96 | byte[] buffer = message.ToArray();
97 | CancellationTokenSource source = new CancellationTokenSource(30000);
98 | //Stream.WriteAsync doesn't support CancellationToken
99 | //see: https://stackoverflow.com/questions/20131434/cancel-networkstream-readasync-using-tcplistener
100 | source.Token.Register(() => Disconnect(false));
101 | try
102 | {
103 | await _stream.WriteAsync(buffer, 0, buffer.Length, source.Token);
104 | return true;
105 | }
106 | catch (ObjectDisposedException) { }
107 | catch (Exception ex) when (ex is IOException || ex is OperationCanceledException)
108 | {
109 | Disconnect(false);
110 | }
111 | finally
112 | {
113 | source.Dispose();
114 | }
115 | return false;
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/DatabaseContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using static Storage.Data.LevelDB.NativeWrapper;
5 |
6 | namespace Storage.Data.LevelDB
7 | {
8 | class DatabaseContext : IDisposable
9 | {
10 | private IntPtr handle;
11 |
12 | ///
13 | /// Return true if haven't got valid handle
14 | ///
15 | public bool IsDisposed => handle == IntPtr.Zero;
16 |
17 | private DatabaseContext(IntPtr handle)
18 | {
19 | this.handle = handle;
20 | }
21 |
22 | public void Dispose()
23 | {
24 | if (handle != IntPtr.Zero)
25 | {
26 | leveldb_close(handle);
27 | handle = IntPtr.Zero;
28 | }
29 | }
30 |
31 | public void Delete(WriteOptions options, Slice key)
32 | {
33 | IntPtr error;
34 | leveldb_delete(handle, options.handle, key.buffer, (UIntPtr)key.buffer.Length, out error);
35 | NativeHelper.CheckError(error);
36 | }
37 |
38 | public Slice Get(ReadOptions options, Slice key)
39 | {
40 | UIntPtr length;
41 | IntPtr error;
42 | IntPtr value = leveldb_get(handle, options.handle, key.buffer, (UIntPtr)key.buffer.Length, out length, out error);
43 | try
44 | {
45 | NativeHelper.CheckError(error);
46 | if (value == IntPtr.Zero)
47 | throw new LevelDbException("not found");
48 | return new Slice(value, length);
49 | }
50 | finally
51 | {
52 | if (value != IntPtr.Zero) leveldb_free(value);
53 | }
54 | }
55 |
56 | public Snapshot GetSnapshot()
57 | {
58 | return new Snapshot(handle);
59 | }
60 |
61 | public Iterator NewIterator(ReadOptions options)
62 | {
63 | return new Iterator(leveldb_create_iterator(handle, options.handle));
64 | }
65 |
66 | public static DatabaseContext Open(string name)
67 | {
68 | return Open(name, Options.Default);
69 | }
70 |
71 | public static DatabaseContext Open(string name, Options options)
72 | {
73 | IntPtr error;
74 | IntPtr handle = leveldb_open(options.Handle, name, out error);
75 | NativeHelper.CheckError(error);
76 | return new DatabaseContext(handle);
77 | }
78 |
79 | public void Put(WriteOptions options, Slice key, Slice value)
80 | {
81 | IntPtr error;
82 | leveldb_put(handle, options.handle, key.buffer, (UIntPtr)key.buffer.Length, value.buffer, (UIntPtr)value.buffer.Length, out error);
83 | NativeHelper.CheckError(error);
84 | }
85 |
86 | public bool TryGet(ReadOptions options, Slice key, out Slice value)
87 | {
88 | UIntPtr length;
89 | IntPtr error;
90 | IntPtr v = leveldb_get(handle, options.handle, key.buffer, (UIntPtr)key.buffer.Length, out length, out error);
91 | if (error != IntPtr.Zero)
92 | {
93 | leveldb_free(error);
94 | value = default(Slice);
95 | return false;
96 | }
97 | if (v == IntPtr.Zero)
98 | {
99 | value = default(Slice);
100 | return false;
101 | }
102 | value = new Slice(v, length);
103 | leveldb_free(v);
104 | return true;
105 | }
106 |
107 | public void Write(WriteOptions options, WriteBatch write_batch)
108 | {
109 | // There's a bug in .Net Core.
110 | // When calling DB.Write(), it will throw LevelDbException sometimes.
111 | // But when you try to catch the exception, the bug disappears.
112 | // We shall remove the "try...catch" clause when Microsoft fix the bug.
113 | byte retry = 0;
114 | while (true)
115 | {
116 | try
117 | {
118 | IntPtr error;
119 | leveldb_write(handle, options.handle, write_batch.Handle, out error);
120 | NativeHelper.CheckError(error);
121 | break;
122 | }
123 | catch (LevelDbException ex)
124 | {
125 | if (++retry >= 4) throw;
126 | System.IO.File.AppendAllText("leveldb.log", ex.Message + "\r\n");
127 | }
128 | }
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/MedPoints/Storage/Core/Transactions/CoinTransaction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Serialization;
5 | using Storage.Utils;
6 |
7 | namespace Storage.Core.Transactions
8 | {
9 | public class CoinTransaction : ITransaction
10 | {
11 | public string Reciepient { get; private set; }
12 | public decimal Amount { get; private set; }
13 | public string Id { get; set; }
14 | public string Sender { get; set; }
15 | public string Signature { get; set; }
16 | public TransactionType Type => TransactionType.Coins;
17 |
18 | private List Inputs { get; }
19 | public List Outputs { get; } = new List();
20 |
21 | private static int Sequence { get; set; }
22 |
23 | public CoinTransaction(
24 | string from,
25 | string to,
26 | decimal amount,
27 | List inputs
28 | )
29 | {
30 | Sender = from;
31 | Reciepient = to;
32 | Amount = amount;
33 | Inputs = inputs;
34 | }
35 |
36 | private string CalculateHash()
37 | {
38 | Sequence++;
39 | return $"{Sender}{Reciepient}{Amount}{Sequence}".GetSha256Hash();
40 | }
41 |
42 | public void Sign(Wallet wallet)
43 | {
44 | var data = $"{Sender}{Reciepient}{Amount}";
45 | Signature = wallet.SignMessage(data);
46 | }
47 |
48 | public bool VerifySignature()
49 | {
50 | var data = $"{Sender}{Reciepient}{Amount}";
51 | return Wallet.VerifyMessage(data, Signature, Sender);
52 | }
53 |
54 | public bool ProcessTransaction(Dictionary utxos)
55 | {
56 | if (!VerifySignature())
57 | return false;
58 |
59 | foreach (var input in Inputs)
60 | {
61 | input.UTXO = utxos[input.TransactionOutputId];
62 | }
63 |
64 | var leftOver = GetInputsValue() - Amount;
65 | Id = CalculateHash();
66 |
67 | Outputs.Add(new TransactionOutput(reciepient: Reciepient, amount: Amount, parentTransactionId: Id));
68 | Outputs.Add(new TransactionOutput(reciepient: Sender, amount: leftOver, parentTransactionId: Id));
69 |
70 | foreach (var transactionOutput in Outputs)
71 | {
72 | utxos[transactionOutput.Id] = transactionOutput;
73 | }
74 |
75 |
76 | foreach (var transactionInput in Inputs)
77 | {
78 | if(transactionInput.UTXO == null)continue;
79 | utxos.Remove(transactionInput.UTXO.Id);
80 | }
81 |
82 | return true;
83 | }
84 |
85 | private decimal GetInputsValue()
86 | {
87 | decimal sum = 0;
88 | foreach (var transactionInput in Inputs)
89 | {
90 | if (transactionInput.UTXO == null) continue;
91 | sum += transactionInput.UTXO.Amount;
92 | }
93 | return sum;
94 | }
95 |
96 | public decimal GetOutputsValue()
97 | {
98 | decimal total = 0;
99 | foreach (var output in Outputs)
100 | {
101 | total += output.Amount;
102 | }
103 | return total;
104 | }
105 |
106 |
107 | }
108 |
109 | public class TransactionOutput
110 | {
111 | public string Id { get; }
112 | public string Reciepient { get; }
113 | public decimal Amount { get; }
114 | public string ParentTransactionId { get; }
115 |
116 | public TransactionOutput(string reciepient, decimal amount, string parentTransactionId)
117 | {
118 | Reciepient = reciepient;
119 | Amount = amount;
120 | ParentTransactionId = parentTransactionId;
121 | Id = $"{Reciepient}{Amount}{ParentTransactionId}".GetSha256Hash();
122 | }
123 |
124 |
125 | public bool IsMine(string publicKey)
126 | {
127 | return publicKey == Reciepient;
128 | }
129 | }
130 |
131 | public class TransactionInput
132 | {
133 | public string TransactionOutputId { get; set; }
134 |
135 | // ReSharper disable once InconsistentNaming
136 | public TransactionOutput UTXO { get; set; }
137 | }
138 |
139 | public static class TransactionExtensions
140 | {
141 | public static string Serialize(this Block block)
142 | {
143 | var serializerSettings =
144 | new JsonSerializerSettings {ContractResolver = new CamelCasePropertyNamesContractResolver()};
145 | return JsonConvert.SerializeObject(block, serializerSettings);
146 | }
147 |
148 | public static string Serialize(this ITransaction tx)
149 | {
150 | var serializerSettings =
151 | new JsonSerializerSettings {ContractResolver = new CamelCasePropertyNamesContractResolver()};
152 | return JsonConvert.SerializeObject(tx, serializerSettings);
153 | }
154 |
155 | public static T Deserialize(string data)
156 | {
157 | return JsonConvert.DeserializeObject(data);
158 | }
159 | }
160 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
--------------------------------------------------------------------------------
/MedPoints/Storage/Core/Wallet.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using Storage.Core.Transactions;
7 | using Storage.Utils;
8 |
9 | namespace Storage.Core
10 | {
11 | public class Wallet
12 | {
13 | public string PrivateKey { get; }
14 | public string PublicKey { get; }
15 |
16 | private readonly UnicodeEncoding _encoder = new UnicodeEncoding();
17 | // ReSharper disable once InconsistentNaming
18 | public Dictionary UTXOs { get; set; } = new Dictionary();
19 |
20 | public Wallet()
21 | {
22 | using (var rsa = RSA.Create())
23 | {
24 | PrivateKey = rsa.ToJsonString(true);
25 | PublicKey = rsa.ToJsonString(false);
26 | }
27 | }
28 |
29 | public Wallet(string privateKey)
30 | {
31 | PrivateKey = privateKey;
32 | var rsa = new RSACryptoServiceProvider();
33 | rsa.FromJsonString(privateKey);
34 | PublicKey = rsa.ToJsonString(false);
35 | rsa.Dispose();
36 | }
37 |
38 | public decimal GetBalance(Dictionary chainUtxos)
39 | {
40 | decimal sum = 0;
41 | foreach (var utxo in chainUtxos)
42 | {
43 | var item = utxo.Value;
44 | if (item.IsMine(PublicKey))
45 | {
46 | UTXOs[item.Id] = item;
47 | sum += item.Amount;
48 | }
49 | }
50 | return sum;
51 | }
52 |
53 | public CoinTransaction Send(Dictionary chainUtxos, string recipient, decimal amount)
54 | {
55 | if (GetBalance(chainUtxos) < amount)
56 | return null;
57 |
58 | var inputs = new List();
59 | decimal sum = 0;
60 | foreach (var utxoItem in UTXOs)
61 | {
62 | var utxo = utxoItem.Value;
63 | sum += utxo.Amount;
64 | inputs.Add(new TransactionInput(){TransactionOutputId = utxo.Id});
65 | if(sum > amount) break;
66 | }
67 |
68 | var tx = new CoinTransaction(PublicKey, recipient, amount, inputs);
69 | tx.Sign(this);
70 |
71 | foreach (var transactionInput in inputs)
72 | {
73 | UTXOs.Remove(transactionInput.TransactionOutputId);
74 | }
75 |
76 | return tx;
77 | }
78 |
79 | public string Decrypt(string data)
80 | {
81 | var rsa = new RSACryptoServiceProvider();
82 | var dataArray = data.Split(new char[] { ',' });
83 | byte[] dataByte = new byte[dataArray.Length];
84 | for (int i = 0; i < dataArray.Length; i++)
85 | {
86 | dataByte[i] = Convert.ToByte(dataArray[i]);
87 | }
88 |
89 | rsa.FromJsonString(PrivateKey);
90 | var decryptedByte = rsa.Decrypt(dataByte, false);
91 | return _encoder.GetString(decryptedByte);
92 | }
93 |
94 | public string Encrypt(string data)
95 | {
96 | var rsa = new RSACryptoServiceProvider();
97 | rsa.FromJsonString(PublicKey);
98 | var dataToEncrypt = _encoder.GetBytes(data);
99 | var encryptedByteArray = rsa.Encrypt(dataToEncrypt, false).ToArray();
100 | var length = encryptedByteArray.Count();
101 | var item = 0;
102 | var sb = new StringBuilder();
103 | foreach (var x in encryptedByteArray)
104 | {
105 | item++;
106 | sb.Append(x);
107 |
108 | if (item < length)
109 | sb.Append(",");
110 | }
111 |
112 | return sb.ToString();
113 | }
114 |
115 | public string SignMessage(string message)
116 | {
117 | string signedMessage;
118 | try
119 | {
120 | RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048);
121 | //Initiate a new instanse with 2048 bit key size
122 |
123 | rsa.FromJsonString(PrivateKey);
124 | // Load private key
125 |
126 | signedMessage = Convert.ToBase64String(rsa.SignData(Encoding.UTF8.GetBytes(message), CryptoConfig.MapNameToOID("SHA512")));
127 | //rsa.SignData( buffer, hash algorithm) - For signed data. Here I used SHA512 for hash.
128 | //Encoding.UTF8.GetBytes(string) - convert string to byte messafe
129 | //Convert.ToBase64String(string) - convert back to a string.
130 | }
131 | catch (Exception)
132 | {
133 | signedMessage = String.Empty;
134 | }
135 |
136 | return signedMessage;
137 | }
138 |
139 | public byte[] SignMessageInBytes(string message)
140 | {
141 | byte[] signedMessage;
142 | try
143 | {
144 | RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048);
145 | rsa.FromJsonString(PrivateKey);
146 | signedMessage = rsa.SignData(Encoding.UTF8.GetBytes(message), CryptoConfig.MapNameToOID("SHA512"));
147 | }
148 | catch (Exception)
149 | {
150 | signedMessage = default(byte[]);
151 | }
152 |
153 | return signedMessage;
154 | }
155 |
156 | public static bool VerifyMessage(string originalMessage, string signedMessage, string publicKey)
157 | {
158 | bool verified;
159 | try
160 | {
161 | RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048);
162 | rsa.FromJsonString(publicKey);
163 | // load public key
164 | verified = rsa.VerifyData(Encoding.UTF8.GetBytes(originalMessage), CryptoConfig.MapNameToOID("SHA512"), Convert.FromBase64String(signedMessage));
165 | }
166 | catch (Exception)
167 | {
168 | verified = false;
169 | }
170 |
171 | return verified;
172 | }
173 |
174 |
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/Message.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net.WebSockets;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Storage.Utils;
8 |
9 | namespace Storage.Network
10 | {
11 | public class Message : ISerializable
12 | {
13 | private const int PayloadMaxSize = 0x02000000;
14 |
15 | public static readonly uint Magic = Settings.Default.Magic;
16 | public string Command;
17 | public uint Checksum;
18 | public byte[] Payload;
19 |
20 | public int Size => sizeof(uint) + 12 + sizeof(int) + sizeof(uint) + Payload.Length;
21 |
22 | public static Message Create(string command, ISerializable payload = null)
23 | {
24 | return Create(command, payload == null ? new byte[0] : payload.ToArray());
25 | }
26 |
27 | public static Message Create(string command, byte[] payload)
28 | {
29 | return new Message
30 | {
31 | Command = command,
32 | Checksum = GetChecksum(payload),
33 | Payload = payload
34 | };
35 | }
36 |
37 | void ISerializable.Deserialize(BinaryReader reader)
38 | {
39 | if (reader.ReadUInt32() != Magic)
40 | throw new FormatException();
41 | this.Command = reader.ReadFixedString(12);
42 | uint length = reader.ReadUInt32();
43 | if (length > PayloadMaxSize)
44 | throw new FormatException();
45 | this.Checksum = reader.ReadUInt32();
46 | this.Payload = reader.ReadBytes((int)length);
47 | if (GetChecksum(Payload) != Checksum)
48 | throw new FormatException();
49 | }
50 |
51 | public static async Task DeserializeFromAsync(Stream stream, CancellationToken cancellationToken)
52 | {
53 | uint payloadLength;
54 | byte[] buffer = await FillBufferAsync(stream, 24, cancellationToken);
55 | Message message = new Message();
56 | using (MemoryStream ms = new MemoryStream(buffer, false))
57 | using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
58 | {
59 | if (reader.ReadUInt32() != Magic)
60 | throw new FormatException();
61 | message.Command = reader.ReadFixedString(12);
62 | payloadLength = reader.ReadUInt32();
63 | if (payloadLength > PayloadMaxSize)
64 | throw new FormatException();
65 | message.Checksum = reader.ReadUInt32();
66 | }
67 | if (payloadLength > 0)
68 | message.Payload = await FillBufferAsync(stream, (int)payloadLength, cancellationToken);
69 | else
70 | message.Payload = new byte[0];
71 | if (GetChecksum(message.Payload) != message.Checksum)
72 | throw new FormatException();
73 | return message;
74 | }
75 |
76 | public static async Task DeserializeFromAsync(WebSocket socket, CancellationToken cancellationToken)
77 | {
78 | uint payloadLength;
79 | byte[] buffer = await FillBufferAsync(socket, 24, cancellationToken);
80 | Message message = new Message();
81 | using (MemoryStream ms = new MemoryStream(buffer, false))
82 | using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
83 | {
84 | if (reader.ReadUInt32() != Magic)
85 | throw new FormatException();
86 | message.Command = reader.ReadFixedString(12);
87 | payloadLength = reader.ReadUInt32();
88 | if (payloadLength > PayloadMaxSize)
89 | throw new FormatException();
90 | message.Checksum = reader.ReadUInt32();
91 | }
92 | if (payloadLength > 0)
93 | message.Payload = await FillBufferAsync(socket, (int)payloadLength, cancellationToken);
94 | else
95 | message.Payload = new byte[0];
96 | if (GetChecksum(message.Payload) != message.Checksum)
97 | throw new FormatException();
98 | return message;
99 | }
100 |
101 | private static async Task FillBufferAsync(Stream stream, int buffer_size, CancellationToken cancellationToken)
102 | {
103 | var maxSize = 1024;
104 | byte[] buffer = new byte[buffer_size < maxSize ? buffer_size : maxSize];
105 | using (MemoryStream ms = new MemoryStream())
106 | {
107 | while (buffer_size > 0)
108 | {
109 | int count = buffer_size < maxSize ? buffer_size : maxSize;
110 | count = await stream.ReadAsync(buffer, 0, count, cancellationToken);
111 | if (count <= 0) throw new IOException();
112 | ms.Write(buffer, 0, count);
113 | buffer_size -= count;
114 | }
115 | return ms.ToArray();
116 | }
117 | }
118 |
119 | private static async Task FillBufferAsync(WebSocket socket, int buffer_size, CancellationToken cancellationToken)
120 | {
121 | var maxSize = 1024;
122 | byte[] buffer = new byte[buffer_size < maxSize ? buffer_size : maxSize];
123 | using (MemoryStream ms = new MemoryStream())
124 | {
125 | while (buffer_size > 0)
126 | {
127 | int count = buffer_size < maxSize ? buffer_size : maxSize;
128 | ArraySegment segment = new ArraySegment(buffer, 0, count);
129 | WebSocketReceiveResult result = await socket.ReceiveAsync(segment, cancellationToken);
130 | if (result.Count <= 0 || result.MessageType != WebSocketMessageType.Binary)
131 | throw new IOException();
132 | ms.Write(buffer, 0, result.Count);
133 | buffer_size -= result.Count;
134 | }
135 | return ms.ToArray();
136 | }
137 | }
138 |
139 | private static uint GetChecksum(byte[] value)
140 | {
141 | //return Crypto.Default.Hash256(value).ToUInt32(0);
142 | throw new NotImplementedException();
143 | }
144 |
145 | void ISerializable.Serialize(BinaryWriter writer)
146 | {
147 | writer.Write(Magic);
148 | writer.WriteFixedString(Command, 12);
149 | writer.Write(Payload.Length);
150 | writer.Write(Checksum);
151 | writer.Write(Payload);
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Network/UPnP.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Net.Sockets;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Xml;
9 |
10 | namespace Storage.Network
11 | {
12 | // ReSharper disable once InconsistentNaming
13 | public class UPnP
14 | {
15 | private static string _serviceUrl;
16 |
17 | public static TimeSpan TimeOut { get; set; } = TimeSpan.FromSeconds(3);
18 |
19 | public static async Task DiscoverAsync()
20 | {
21 | Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
22 | s.ReceiveTimeout = (int)TimeOut.TotalMilliseconds;
23 | s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
24 | string req = "M-SEARCH * HTTP/1.1\r\n" +
25 | "HOST: 239.255.255.250:1900\r\n" +
26 | "ST:upnp:rootdevice\r\n" +
27 | "MAN:\"ssdp:discover\"\r\n" +
28 | "MX:3\r\n\r\n";
29 | byte[] data = Encoding.ASCII.GetBytes(req);
30 | IPEndPoint ipe = new IPEndPoint(IPAddress.Broadcast, 1900);
31 |
32 | DateTime start = DateTime.Now;
33 |
34 | s.SendTo(data, ipe);
35 | s.SendTo(data, ipe);
36 | s.SendTo(data, ipe);
37 |
38 | byte[] buffer = new byte[0x1000];
39 | do
40 | {
41 | int length;
42 | try
43 | {
44 | length = s.Receive(buffer);
45 | }
46 | catch (SocketException)
47 | {
48 | continue;
49 | }
50 | string resp = Encoding.ASCII.GetString(buffer, 0, length).ToLower();
51 | if (resp.Contains("upnp:rootdevice"))
52 | {
53 | resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
54 | resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
55 | if (!string.IsNullOrEmpty(_serviceUrl = await GetServiceUrlAsync(resp)))
56 | {
57 | return true;
58 | }
59 | }
60 | } while (DateTime.Now - start < TimeOut);
61 | return false;
62 | }
63 |
64 | private static async Task GetServiceUrlAsync(string resp)
65 | {
66 | try
67 | {
68 | XmlDocument desc = new XmlDocument();
69 | HttpWebRequest request = WebRequest.CreateHttp(resp);
70 | WebResponse response = await request.GetResponseAsync();
71 | desc.Load(response.GetResponseStream());
72 | XmlNamespaceManager nsMgr = new XmlNamespaceManager(desc.NameTable);
73 | nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0");
74 | XmlNode typen = desc.SelectSingleNode("//tns:device/tns:deviceType/text()", nsMgr);
75 | if (!typen.Value.Contains("InternetGatewayDevice"))
76 | return null;
77 | XmlNode node = desc.SelectSingleNode("//tns:service[contains(tns:serviceType,\"WANIPConnection\")]/tns:controlURL/text()", nsMgr);
78 | if (node == null)
79 | return null;
80 | XmlNode eventnode = desc.SelectSingleNode("//tns:service[contains(tns:serviceType,\"WANIPConnection\")]/tns:eventSubURL/text()", nsMgr);
81 | return CombineUrls(resp, node.Value);
82 | }
83 | catch { return null; }
84 | }
85 |
86 | private static string CombineUrls(string resp, string p)
87 | {
88 | int n = resp.IndexOf("://");
89 | n = resp.IndexOf('/', n + 3);
90 | return resp.Substring(0, n) + p;
91 | }
92 |
93 | public static async Task ForwardPortAsync(int port, ProtocolType protocol, string description)
94 | {
95 | if (string.IsNullOrEmpty(_serviceUrl))
96 | throw new Exception("No UPnP service available or Discover() has not been called");
97 | XmlDocument xdoc = await SOAPRequestAsync(_serviceUrl, "" +
98 | "" + port.ToString() + "" + protocol.ToString().ToUpper() + "" +
99 | "" + port.ToString() + "" + (await Dns.GetHostAddressesAsync(Dns.GetHostName())).First(p => p.AddressFamily == AddressFamily.InterNetwork).ToString() +
100 | "1" + description +
101 | "0", "AddPortMapping");
102 | }
103 |
104 | public static async Task DeleteForwardingRuleAsync(int port, ProtocolType protocol)
105 | {
106 | if (string.IsNullOrEmpty(_serviceUrl))
107 | throw new Exception("No UPnP service available or Discover() has not been called");
108 | XmlDocument xdoc = await SOAPRequestAsync(_serviceUrl,
109 | "" +
110 | "" +
111 | "" +
112 | "" + port + "" +
113 | "" + protocol.ToString().ToUpper() + "" +
114 | "", "DeletePortMapping");
115 | }
116 |
117 | public static async Task GetExternalIPAsync()
118 | {
119 | if (string.IsNullOrEmpty(_serviceUrl))
120 | throw new Exception("No UPnP service available or Discover() has not been called");
121 | XmlDocument xdoc = await SOAPRequestAsync(_serviceUrl, "" +
122 | "", "GetExternalIPAddress");
123 | XmlNamespaceManager nsMgr = new XmlNamespaceManager(xdoc.NameTable);
124 | nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0");
125 | string IP = xdoc.SelectSingleNode("//NewExternalIPAddress/text()", nsMgr).Value;
126 | return IPAddress.Parse(IP);
127 | }
128 |
129 | private static async Task SOAPRequestAsync(string url, string soap, string function)
130 | {
131 | string req = "" +
132 | "" +
133 | "" +
134 | soap +
135 | "" +
136 | "";
137 | HttpWebRequest r = WebRequest.CreateHttp(url);
138 | r.Method = "POST";
139 | byte[] b = Encoding.UTF8.GetBytes(req);
140 | r.Headers["SOAPACTION"] = "\"urn:schemas-upnp-org:service:WANIPConnection:1#" + function + "\"";
141 | r.ContentType = "text/xml; charset=\"utf-8\"";
142 | Stream reqs = await r.GetRequestStreamAsync();
143 | reqs.Write(b, 0, b.Length);
144 | XmlDocument resp = new XmlDocument();
145 | WebResponse wres = await r.GetResponseAsync();
146 | Stream ress = wres.GetResponseStream();
147 | resp.Load(ress);
148 | return resp;
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/Slice.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 |
6 | namespace Storage.Data.LevelDB
7 | {
8 | public struct Slice : IComparable, IEquatable
9 | {
10 | internal byte[] buffer;
11 |
12 | internal Slice(IntPtr data, UIntPtr length)
13 | {
14 | buffer = new byte[(int)length];
15 | Marshal.Copy(data, buffer, 0, (int)length);
16 | }
17 |
18 | public int CompareTo(Slice other)
19 | {
20 | for (int i = 0; i < buffer.Length && i < other.buffer.Length; i++)
21 | {
22 | int r = buffer[i].CompareTo(other.buffer[i]);
23 | if (r != 0) return r;
24 | }
25 | return buffer.Length.CompareTo(other.buffer.Length);
26 | }
27 |
28 | public bool Equals(Slice other)
29 | {
30 | if (buffer.Length != other.buffer.Length) return false;
31 | return buffer.SequenceEqual(other.buffer);
32 | }
33 |
34 | public override bool Equals(object obj)
35 | {
36 | if (ReferenceEquals(null, obj)) return false;
37 | if (!(obj is Slice)) return false;
38 | return Equals((Slice)obj);
39 | }
40 |
41 | public override int GetHashCode()
42 | {
43 | throw new NotImplementedException();
44 | }
45 |
46 | public byte[] ToArray()
47 | {
48 | return buffer ?? new byte[0];
49 | }
50 |
51 | public unsafe bool ToBoolean()
52 | {
53 | if (buffer.Length != sizeof(bool))
54 | throw new InvalidCastException();
55 | fixed (byte* pbyte = &buffer[0])
56 | {
57 | return *((bool*)pbyte);
58 | }
59 | }
60 |
61 | public byte ToByte()
62 | {
63 | if (buffer.Length != sizeof(byte))
64 | throw new InvalidCastException();
65 | return buffer[0];
66 | }
67 |
68 | public unsafe double ToDouble()
69 | {
70 | if (buffer.Length != sizeof(double))
71 | throw new InvalidCastException();
72 | fixed (byte* pbyte = &buffer[0])
73 | {
74 | return *((double*)pbyte);
75 | }
76 | }
77 |
78 | public unsafe short ToInt16()
79 | {
80 | if (buffer.Length != sizeof(short))
81 | throw new InvalidCastException();
82 | fixed (byte* pbyte = &buffer[0])
83 | {
84 | return *((short*)pbyte);
85 | }
86 | }
87 |
88 | public unsafe int ToInt32()
89 | {
90 | if (buffer.Length != sizeof(int))
91 | throw new InvalidCastException();
92 | fixed (byte* pbyte = &buffer[0])
93 | {
94 | return *((int*)pbyte);
95 | }
96 | }
97 |
98 | public unsafe long ToInt64()
99 | {
100 | if (buffer.Length != sizeof(long))
101 | throw new InvalidCastException();
102 | fixed (byte* pbyte = &buffer[0])
103 | {
104 | return *((long*)pbyte);
105 | }
106 | }
107 |
108 | public unsafe float ToSingle()
109 | {
110 | if (buffer.Length != sizeof(float))
111 | throw new InvalidCastException();
112 | fixed (byte* pbyte = &buffer[0])
113 | {
114 | return *((float*)pbyte);
115 | }
116 | }
117 |
118 | public override string ToString()
119 | {
120 | return Encoding.UTF8.GetString(buffer);
121 | }
122 |
123 | public unsafe ushort ToUInt16()
124 | {
125 | if (buffer.Length != sizeof(ushort))
126 | throw new InvalidCastException();
127 | fixed (byte* pbyte = &buffer[0])
128 | {
129 | return *((ushort*)pbyte);
130 | }
131 | }
132 |
133 | public unsafe uint ToUInt32(int index = 0)
134 | {
135 | if (buffer.Length != sizeof(uint) + index)
136 | throw new InvalidCastException();
137 | fixed (byte* pbyte = &buffer[index])
138 | {
139 | return *((uint*)pbyte);
140 | }
141 | }
142 |
143 | public unsafe
144 | ulong ToUInt64()
145 | {
146 | if (buffer.Length != sizeof(ulong))
147 | throw new InvalidCastException();
148 | fixed (byte* pbyte = &buffer[0])
149 | {
150 | return *((ulong*)pbyte);
151 | }
152 | }
153 |
154 | public static implicit operator Slice(byte[] data)
155 | {
156 | return new Slice { buffer = data };
157 | }
158 |
159 | public static implicit operator Slice(bool data)
160 | {
161 | return new Slice { buffer = BitConverter.GetBytes(data) };
162 | }
163 |
164 | public static implicit operator Slice(byte data)
165 | {
166 | return new Slice { buffer = new[] { data } };
167 | }
168 |
169 | public static implicit operator Slice(double data)
170 | {
171 | return new Slice { buffer = BitConverter.GetBytes(data) };
172 | }
173 |
174 | public static implicit operator Slice(short data)
175 | {
176 | return new Slice { buffer = BitConverter.GetBytes(data) };
177 | }
178 |
179 | public static implicit operator Slice(int data)
180 | {
181 | return new Slice { buffer = BitConverter.GetBytes(data) };
182 | }
183 |
184 | public static implicit operator Slice(long data)
185 | {
186 | return new Slice { buffer = BitConverter.GetBytes(data) };
187 | }
188 |
189 | public static implicit operator Slice(float data)
190 | {
191 | return new Slice { buffer = BitConverter.GetBytes(data) };
192 | }
193 |
194 | public static implicit operator Slice(string data)
195 | {
196 | return new Slice { buffer = Encoding.UTF8.GetBytes(data) };
197 | }
198 |
199 | public static implicit operator Slice(ushort data)
200 | {
201 | return new Slice { buffer = BitConverter.GetBytes(data) };
202 | }
203 |
204 | public static implicit operator Slice(uint data)
205 | {
206 | return new Slice { buffer = BitConverter.GetBytes(data) };
207 | }
208 |
209 | public static implicit operator Slice(ulong data)
210 | {
211 | return new Slice { buffer = BitConverter.GetBytes(data) };
212 | }
213 |
214 | public static bool operator <(Slice x, Slice y)
215 | {
216 | return x.CompareTo(y) < 0;
217 | }
218 |
219 | public static bool operator <=(Slice x, Slice y)
220 | {
221 | return x.CompareTo(y) <= 0;
222 | }
223 |
224 | public static bool operator >(Slice x, Slice y)
225 | {
226 | return x.CompareTo(y) > 0;
227 | }
228 |
229 | public static bool operator >=(Slice x, Slice y)
230 | {
231 | return x.CompareTo(y) >= 0;
232 | }
233 |
234 | public static bool operator ==(Slice x, Slice y)
235 | {
236 | return x.Equals(y);
237 | }
238 |
239 | public static bool operator !=(Slice x, Slice y)
240 | {
241 | return !x.Equals(y);
242 | }
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/Fixed8.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.IO;
4 | using Storage.Utils;
5 |
6 | namespace Storage.Core
7 | {
8 | ///
9 | /// Accurate to 10^-8 64-bit fixed-point numbers minimize rounding errors.
10 | /// By controlling the accuracy of the multiplier, rounding errors can be completely eliminated.
11 | ///
12 | public struct Fixed8 : IComparable, IEquatable, IFormattable, ISerializable
13 | {
14 | private const long D = 100_000_000;
15 | internal long Value;
16 |
17 | public static readonly Fixed8 MaxValue = new Fixed8 { Value = long.MaxValue };
18 |
19 | public static readonly Fixed8 MinValue = new Fixed8 { Value = long.MinValue };
20 |
21 | public static readonly Fixed8 One = new Fixed8 { Value = D };
22 |
23 | public static readonly Fixed8 Satoshi = new Fixed8 { Value = 1 };
24 |
25 | public static readonly Fixed8 Zero = default(Fixed8);
26 |
27 | public int Size => sizeof(long);
28 |
29 | public Fixed8(long data)
30 | {
31 | this.Value = data;
32 | }
33 |
34 | public Fixed8 Abs()
35 | {
36 | if (Value >= 0) return this;
37 | return new Fixed8
38 | {
39 | Value = -Value
40 | };
41 | }
42 |
43 | public Fixed8 Ceiling()
44 | {
45 | long remainder = Value % D;
46 | if (remainder == 0) return this;
47 | if (remainder > 0)
48 | return new Fixed8
49 | {
50 | Value = Value - remainder + D
51 | };
52 | else
53 | return new Fixed8
54 | {
55 | Value = Value - remainder
56 | };
57 | }
58 |
59 | public int CompareTo(Fixed8 other)
60 | {
61 | return Value.CompareTo(other.Value);
62 | }
63 |
64 | void ISerializable.Deserialize(BinaryReader reader)
65 | {
66 | Value = reader.ReadInt64();
67 | }
68 |
69 | public bool Equals(Fixed8 other)
70 | {
71 | return Value.Equals(other.Value);
72 | }
73 |
74 | public override bool Equals(object obj)
75 | {
76 | if (!(obj is Fixed8)) return false;
77 | return Equals((Fixed8)obj);
78 | }
79 |
80 | public static Fixed8 FromDecimal(decimal value)
81 | {
82 | value *= D;
83 | if (value < long.MinValue || value > long.MaxValue)
84 | throw new OverflowException();
85 | return new Fixed8
86 | {
87 | Value = (long)value
88 | };
89 | }
90 |
91 | public long GetData() => Value;
92 |
93 | public override int GetHashCode()
94 | {
95 | return Value.GetHashCode();
96 | }
97 |
98 | public static Fixed8 Max(Fixed8 first, params Fixed8[] others)
99 | {
100 | foreach (Fixed8 other in others)
101 | {
102 | if (first.CompareTo(other) < 0)
103 | first = other;
104 | }
105 | return first;
106 | }
107 |
108 | public static Fixed8 Min(Fixed8 first, params Fixed8[] others)
109 | {
110 | foreach (Fixed8 other in others)
111 | {
112 | if (first.CompareTo(other) > 0)
113 | first = other;
114 | }
115 | return first;
116 | }
117 |
118 | public static Fixed8 Parse(string s)
119 | {
120 | return FromDecimal(decimal.Parse(s, NumberStyles.Float, CultureInfo.InvariantCulture));
121 | }
122 |
123 | void ISerializable.Serialize(BinaryWriter writer)
124 | {
125 | writer.Write(Value);
126 | }
127 |
128 | public override string ToString()
129 | {
130 | return ((decimal)this).ToString(CultureInfo.InvariantCulture);
131 | }
132 |
133 | public string ToString(string format)
134 | {
135 | return ((decimal)this).ToString(format);
136 | }
137 |
138 | public string ToString(string format, IFormatProvider formatProvider)
139 | {
140 | return ((decimal)this).ToString(format, formatProvider);
141 | }
142 |
143 | public static bool TryParse(string s, out Fixed8 result)
144 | {
145 | decimal d;
146 | if (!decimal.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out d))
147 | {
148 | result = default(Fixed8);
149 | return false;
150 | }
151 | d *= D;
152 | if (d < long.MinValue || d > long.MaxValue)
153 | {
154 | result = default(Fixed8);
155 | return false;
156 | }
157 | result = new Fixed8
158 | {
159 | Value = (long)d
160 | };
161 | return true;
162 | }
163 |
164 | public static explicit operator decimal(Fixed8 value)
165 | {
166 | return value.Value / (decimal)D;
167 | }
168 |
169 | public static explicit operator long(Fixed8 value)
170 | {
171 | return value.Value / D;
172 | }
173 |
174 | public static bool operator ==(Fixed8 x, Fixed8 y)
175 | {
176 | return x.Equals(y);
177 | }
178 |
179 | public static bool operator !=(Fixed8 x, Fixed8 y)
180 | {
181 | return !x.Equals(y);
182 | }
183 |
184 | public static bool operator >(Fixed8 x, Fixed8 y)
185 | {
186 | return x.CompareTo(y) > 0;
187 | }
188 |
189 | public static bool operator <(Fixed8 x, Fixed8 y)
190 | {
191 | return x.CompareTo(y) < 0;
192 | }
193 |
194 | public static bool operator >=(Fixed8 x, Fixed8 y)
195 | {
196 | return x.CompareTo(y) >= 0;
197 | }
198 |
199 | public static bool operator <=(Fixed8 x, Fixed8 y)
200 | {
201 | return x.CompareTo(y) <= 0;
202 | }
203 |
204 | public static Fixed8 operator *(Fixed8 x, Fixed8 y)
205 | {
206 | const ulong QUO = (1ul << 63) / (D >> 1);
207 | const ulong REM = ((1ul << 63) % (D >> 1)) << 1;
208 | int sign = Math.Sign(x.Value) * Math.Sign(y.Value);
209 | ulong ux = (ulong)Math.Abs(x.Value);
210 | ulong uy = (ulong)Math.Abs(y.Value);
211 | ulong xh = ux >> 32;
212 | ulong xl = ux & 0x00000000fffffffful;
213 | ulong yh = uy >> 32;
214 | ulong yl = uy & 0x00000000fffffffful;
215 | ulong rh = xh * yh;
216 | ulong rm = xh * yl + xl * yh;
217 | ulong rl = xl * yl;
218 | ulong rmh = rm >> 32;
219 | ulong rml = rm << 32;
220 | rh += rmh;
221 | rl += rml;
222 | if (rl < rml)
223 | ++rh;
224 | if (rh >= D)
225 | throw new OverflowException();
226 | ulong rd = rh * REM + rl;
227 | if (rd < rl)
228 | ++rh;
229 | ulong r = rh * QUO + rd / D;
230 | x.Value = (long)r * sign;
231 | return x;
232 | }
233 |
234 | public static Fixed8 operator *(Fixed8 x, long y)
235 | {
236 | x.Value *= y;
237 | return x;
238 | }
239 |
240 | public static Fixed8 operator /(Fixed8 x, long y)
241 | {
242 | x.Value /= y;
243 | return x;
244 | }
245 |
246 | public static Fixed8 operator +(Fixed8 x, Fixed8 y)
247 | {
248 | x.Value = checked(x.Value + y.Value);
249 | return x;
250 | }
251 |
252 | public static Fixed8 operator -(Fixed8 x, Fixed8 y)
253 | {
254 | x.Value = checked(x.Value - y.Value);
255 | return x;
256 | }
257 |
258 | public static Fixed8 operator -(Fixed8 value)
259 | {
260 | value.Value = -value.Value;
261 | return value;
262 | }
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Utils/Helper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Runtime.Serialization;
8 | using System.Text;
9 |
10 | namespace Storage.Utils
11 | {
12 | public static class Helper
13 | {
14 | public static T AsSerializable(this byte[] value, int start = 0) where T : ISerializable, new()
15 | {
16 | using (MemoryStream ms = new MemoryStream(value, start, value.Length - start, false))
17 | using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
18 | {
19 | return reader.ReadSerializable();
20 | }
21 | }
22 |
23 | public static ISerializable AsSerializable(this byte[] value, Type type)
24 | {
25 | if (!typeof(ISerializable).GetTypeInfo().IsAssignableFrom(type))
26 | throw new InvalidCastException();
27 | ISerializable serializable = (ISerializable)Activator.CreateInstance(type);
28 | using (MemoryStream ms = new MemoryStream(value, false))
29 | using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
30 | {
31 | serializable.Deserialize(reader);
32 | }
33 | return serializable;
34 | }
35 |
36 | public static T[] AsSerializableArray(this byte[] value, int max = 0x10000000) where T : ISerializable, new()
37 | {
38 | using (MemoryStream ms = new MemoryStream(value, false))
39 | using (BinaryReader reader = new BinaryReader(ms, Encoding.UTF8))
40 | {
41 | return reader.ReadSerializableArray(max);
42 | }
43 | }
44 |
45 | public static int GetVarSize(int value)
46 | {
47 | if (value < 0xFD)
48 | return sizeof(byte);
49 | else if (value <= 0xFFFF)
50 | return sizeof(byte) + sizeof(ushort);
51 | else
52 | return sizeof(byte) + sizeof(uint);
53 | }
54 |
55 | public static int GetVarSize(this T[] value)
56 | {
57 | int value_size;
58 | Type t = typeof(T);
59 | if (typeof(ISerializable).IsAssignableFrom(t))
60 | {
61 | value_size = value.OfType().Sum(p => p.Size);
62 | }
63 | else if (t.GetTypeInfo().IsEnum)
64 | {
65 | int element_size;
66 | Type u = t.GetTypeInfo().GetEnumUnderlyingType();
67 | if (u == typeof(sbyte) || u == typeof(byte))
68 | element_size = 1;
69 | else if (u == typeof(short) || u == typeof(ushort))
70 | element_size = 2;
71 | else if (u == typeof(int) || u == typeof(uint))
72 | element_size = 4;
73 | else //if (u == typeof(long) || u == typeof(ulong))
74 | element_size = 8;
75 | value_size = value.Length * element_size;
76 | }
77 | else
78 | {
79 | value_size = value.Length * Marshal.SizeOf();
80 | }
81 | return GetVarSize(value.Length) + value_size;
82 | }
83 |
84 | internal static int GetVarSize(this string value)
85 | {
86 | int size = Encoding.UTF8.GetByteCount(value);
87 | return GetVarSize(size) + size;
88 | }
89 |
90 | public static byte[] ReadBytesWithGrouping(this BinaryReader reader)
91 | {
92 | const int GROUP_SIZE = 16;
93 | using (MemoryStream ms = new MemoryStream())
94 | {
95 | int padding = 0;
96 | do
97 | {
98 | byte[] group = reader.ReadBytes(GROUP_SIZE);
99 | padding = reader.ReadByte();
100 | if (padding > GROUP_SIZE)
101 | throw new FormatException();
102 | int count = GROUP_SIZE - padding;
103 | if (count > 0)
104 | ms.Write(group, 0, count);
105 | } while (padding == 0);
106 | return ms.ToArray();
107 | }
108 | }
109 |
110 | public static string ReadFixedString(this BinaryReader reader, int length)
111 | {
112 | byte[] data = reader.ReadBytes(length);
113 | return Encoding.UTF8.GetString(data.TakeWhile(p => p != 0).ToArray());
114 | }
115 |
116 | public static T ReadSerializable(this BinaryReader reader) where T : ISerializable, new()
117 | {
118 | T obj = new T();
119 | obj.Deserialize(reader);
120 | return obj;
121 | }
122 |
123 | public static T[] ReadSerializableArray(this BinaryReader reader, int max = 0x10000000) where T : ISerializable, new()
124 | {
125 | T[] array = new T[reader.ReadVarInt((ulong)max)];
126 | for (int i = 0; i < array.Length; i++)
127 | {
128 | array[i] = new T();
129 | array[i].Deserialize(reader);
130 | }
131 | return array;
132 | }
133 |
134 | public static byte[] ReadVarBytes(this BinaryReader reader, int max = 0X7fffffc7)
135 | {
136 | return reader.ReadBytes((int)reader.ReadVarInt((ulong)max));
137 | }
138 |
139 | public static ulong ReadVarInt(this BinaryReader reader, ulong max = ulong.MaxValue)
140 | {
141 | byte fb = reader.ReadByte();
142 | ulong value;
143 | if (fb == 0xFD)
144 | value = reader.ReadUInt16();
145 | else if (fb == 0xFE)
146 | value = reader.ReadUInt32();
147 | else if (fb == 0xFF)
148 | value = reader.ReadUInt64();
149 | else
150 | value = fb;
151 | if (value > max) throw new FormatException();
152 | return value;
153 | }
154 |
155 | public static string ReadVarString(this BinaryReader reader, int max = 0X7fffffc7)
156 | {
157 | return Encoding.UTF8.GetString(reader.ReadVarBytes(max));
158 | }
159 |
160 | public static byte[] ToArray(this ISerializable value)
161 | {
162 | using (MemoryStream ms = new MemoryStream())
163 | using (BinaryWriter writer = new BinaryWriter(ms, Encoding.UTF8))
164 | {
165 | value.Serialize(writer);
166 | writer.Flush();
167 | return ms.ToArray();
168 | }
169 | }
170 |
171 | public static byte[] ToByteArray(this T[] value) where T : ISerializable
172 | {
173 | using (MemoryStream ms = new MemoryStream())
174 | using (BinaryWriter writer = new BinaryWriter(ms, Encoding.UTF8))
175 | {
176 | writer.Write(value);
177 | writer.Flush();
178 | return ms.ToArray();
179 | }
180 | }
181 |
182 | public static void Write(this BinaryWriter writer, ISerializable value)
183 | {
184 | value.Serialize(writer);
185 | }
186 |
187 | public static void Write(this BinaryWriter writer, T[] value) where T : ISerializable
188 | {
189 | writer.WriteVarInt(value.Length);
190 | for (int i = 0; i < value.Length; i++)
191 | {
192 | value[i].Serialize(writer);
193 | }
194 | }
195 |
196 | public static void WriteBytesWithGrouping(this BinaryWriter writer, byte[] value)
197 | {
198 | const int GROUP_SIZE = 16;
199 | int index = 0;
200 | int remain = value.Length;
201 | while (remain >= GROUP_SIZE)
202 | {
203 | writer.Write(value, index, GROUP_SIZE);
204 | writer.Write((byte)0);
205 | index += GROUP_SIZE;
206 | remain -= GROUP_SIZE;
207 | }
208 | if (remain > 0)
209 | writer.Write(value, index, remain);
210 | int padding = GROUP_SIZE - remain;
211 | for (int i = 0; i < padding; i++)
212 | writer.Write((byte)0);
213 | writer.Write((byte)padding);
214 | }
215 |
216 | public static void WriteFixedString(this BinaryWriter writer, string value, int length)
217 | {
218 | if (value == null)
219 | throw new ArgumentNullException(nameof(value));
220 | if (value.Length > length)
221 | throw new ArgumentException();
222 | byte[] bytes = Encoding.UTF8.GetBytes(value);
223 | if (bytes.Length > length)
224 | throw new ArgumentException();
225 | writer.Write(bytes);
226 | if (bytes.Length < length)
227 | writer.Write(new byte[length - bytes.Length]);
228 | }
229 |
230 | public static void WriteVarBytes(this BinaryWriter writer, byte[] value)
231 | {
232 | writer.WriteVarInt(value.Length);
233 | writer.Write(value);
234 | }
235 |
236 | public static void WriteVarInt(this BinaryWriter writer, long value)
237 | {
238 | if (value < 0)
239 | throw new ArgumentOutOfRangeException();
240 | if (value < 0xFD)
241 | {
242 | writer.Write((byte)value);
243 | }
244 | else if (value <= 0xFFFF)
245 | {
246 | writer.Write((byte)0xFD);
247 | writer.Write((ushort)value);
248 | }
249 | else if (value <= 0xFFFFFFFF)
250 | {
251 | writer.Write((byte)0xFE);
252 | writer.Write((uint)value);
253 | }
254 | else
255 | {
256 | writer.Write((byte)0xFF);
257 | writer.Write(value);
258 | }
259 | }
260 |
261 | public static void WriteVarString(this BinaryWriter writer, string value)
262 | {
263 | writer.WriteVarBytes(Encoding.UTF8.GetBytes(value));
264 | }
265 | }
266 | }
267 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Core/Helper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Numerics;
6 | using System.Runtime.CompilerServices;
7 | using System.Security.Cryptography;
8 | using System.Text;
9 |
10 | namespace Storage.Core
11 | {
12 | public static class Helper
13 | {
14 | private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
15 |
16 | private static int BitLen(int w)
17 | {
18 | return (w < 1 << 15 ? (w < 1 << 7
19 | ? (w < 1 << 3 ? (w < 1 << 1
20 | ? (w < 1 << 0 ? (w < 0 ? 32 : 0) : 1)
21 | : (w < 1 << 2 ? 2 : 3)) : (w < 1 << 5
22 | ? (w < 1 << 4 ? 4 : 5)
23 | : (w < 1 << 6 ? 6 : 7)))
24 | : (w < 1 << 11
25 | ? (w < 1 << 9 ? (w < 1 << 8 ? 8 : 9) : (w < 1 << 10 ? 10 : 11))
26 | : (w < 1 << 13 ? (w < 1 << 12 ? 12 : 13) : (w < 1 << 14 ? 14 : 15)))) : (w < 1 << 23 ? (w < 1 << 19
27 | ? (w < 1 << 17 ? (w < 1 << 16 ? 16 : 17) : (w < 1 << 18 ? 18 : 19))
28 | : (w < 1 << 21 ? (w < 1 << 20 ? 20 : 21) : (w < 1 << 22 ? 22 : 23))) : (w < 1 << 27
29 | ? (w < 1 << 25 ? (w < 1 << 24 ? 24 : 25) : (w < 1 << 26 ? 26 : 27))
30 | : (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31)))));
31 | }
32 |
33 | internal static int GetBitLength(this BigInteger i)
34 | {
35 | byte[] b = i.ToByteArray();
36 | return (b.Length - 1) * 8 + BitLen(i.Sign > 0 ? b[b.Length - 1] : 255 - b[b.Length - 1]);
37 | }
38 |
39 | internal static int GetLowestSetBit(this BigInteger i)
40 | {
41 | if (i.Sign == 0)
42 | return -1;
43 | byte[] b = i.ToByteArray();
44 | int w = 0;
45 | while (b[w] == 0)
46 | w++;
47 | for (int x = 0; x < 8; x++)
48 | if ((b[w] & 1 << x) > 0)
49 | return x + w * 8;
50 | throw new Exception();
51 | }
52 |
53 | public static byte[] HexToBytes(this string value)
54 | {
55 | if (string.IsNullOrEmpty(value))
56 | return new byte[0];
57 | if (value.Length % 2 == 1)
58 | throw new FormatException();
59 | byte[] result = new byte[value.Length / 2];
60 | for (int i = 0; i < result.Length; i++)
61 | result[i] = byte.Parse(value.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier);
62 | return result;
63 | }
64 |
65 | internal static BigInteger Mod(this BigInteger x, BigInteger y)
66 | {
67 | x %= y;
68 | if (x.Sign < 0)
69 | x += y;
70 | return x;
71 | }
72 |
73 | internal static BigInteger ModInverse(this BigInteger a, BigInteger n)
74 | {
75 | BigInteger i = n, v = 0, d = 1;
76 | while (a > 0)
77 | {
78 | BigInteger t = i / a, x = a;
79 | a = i % x;
80 | i = x;
81 | x = d;
82 | d = v - t * x;
83 | v = x;
84 | }
85 | v %= n;
86 | if (v < 0) v = (v + n) % n;
87 | return v;
88 | }
89 |
90 | internal static BigInteger NextBigInteger(this Random rand, int sizeInBits)
91 | {
92 | if (sizeInBits < 0)
93 | throw new ArgumentException("sizeInBits must be non-negative");
94 | if (sizeInBits == 0)
95 | return 0;
96 | byte[] b = new byte[sizeInBits / 8 + 1];
97 | rand.NextBytes(b);
98 | if (sizeInBits % 8 == 0)
99 | b[b.Length - 1] = 0;
100 | else
101 | b[b.Length - 1] &= (byte)((1 << sizeInBits % 8) - 1);
102 | return new BigInteger(b);
103 | }
104 |
105 | internal static BigInteger NextBigInteger(this RandomNumberGenerator rng, int sizeInBits)
106 | {
107 | if (sizeInBits < 0)
108 | throw new ArgumentException("sizeInBits must be non-negative");
109 | if (sizeInBits == 0)
110 | return 0;
111 | byte[] b = new byte[sizeInBits / 8 + 1];
112 | rng.GetBytes(b);
113 | if (sizeInBits % 8 == 0)
114 | b[b.Length - 1] = 0;
115 | else
116 | b[b.Length - 1] &= (byte)((1 << sizeInBits % 8) - 1);
117 | return new BigInteger(b);
118 | }
119 |
120 | public static Fixed8 Sum(this IEnumerable source)
121 | {
122 | long sum = 0;
123 | checked
124 | {
125 | foreach (Fixed8 item in source)
126 | {
127 | sum += item.Value;
128 | }
129 | }
130 | return new Fixed8(sum);
131 | }
132 |
133 | public static Fixed8 Sum(this IEnumerable source, Func selector)
134 | {
135 | return source.Select(selector).Sum();
136 | }
137 |
138 | internal static bool TestBit(this BigInteger i, int index)
139 | {
140 | return (i & (BigInteger.One << index)) > BigInteger.Zero;
141 | }
142 |
143 | public static DateTime ToDateTime(this uint timestamp)
144 | {
145 | return UnixEpoch.AddSeconds(timestamp).ToLocalTime();
146 | }
147 |
148 | public static DateTime ToDateTime(this ulong timestamp)
149 | {
150 | return UnixEpoch.AddSeconds(timestamp).ToLocalTime();
151 | }
152 |
153 | public static string ToHexString(this IEnumerable value)
154 | {
155 | StringBuilder sb = new StringBuilder();
156 | foreach (byte b in value)
157 | sb.AppendFormat("{0:x2}", b);
158 | return sb.ToString();
159 | }
160 |
161 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
162 | internal static unsafe int ToInt32(this byte[] value, int startIndex)
163 | {
164 | fixed (byte* pbyte = &value[startIndex])
165 | {
166 | return *((int*)pbyte);
167 | }
168 | }
169 |
170 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
171 | internal static unsafe long ToInt64(this byte[] value, int startIndex)
172 | {
173 | fixed (byte* pbyte = &value[startIndex])
174 | {
175 | return *((long*)pbyte);
176 | }
177 | }
178 |
179 | public static uint ToTimestamp(this DateTime time)
180 | {
181 | return (uint)(time.ToUniversalTime() - UnixEpoch).TotalSeconds;
182 | }
183 |
184 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
185 | unsafe internal static ushort ToUInt16(this byte[] value, int startIndex)
186 | {
187 | fixed (byte* pbyte = &value[startIndex])
188 | {
189 | return *((ushort*)pbyte);
190 | }
191 | }
192 |
193 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
194 | internal static unsafe uint ToUInt32(this byte[] value, int startIndex)
195 | {
196 | fixed (byte* pbyte = &value[startIndex])
197 | {
198 | return *((uint*)pbyte);
199 | }
200 | }
201 |
202 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
203 | internal static unsafe ulong ToUInt64(this byte[] value, int startIndex)
204 | {
205 | fixed (byte* pbyte = &value[startIndex])
206 | {
207 | return *((ulong*)pbyte);
208 | }
209 | }
210 |
211 | internal static long WeightedAverage(this IEnumerable source, Func valueSelector, Func weightSelector)
212 | {
213 | long sum_weight = 0;
214 | long sum_value = 0;
215 | foreach (T item in source)
216 | {
217 | long weight = weightSelector(item);
218 | sum_weight += weight;
219 | sum_value += valueSelector(item) * weight;
220 | }
221 | if (sum_value == 0) return 0;
222 | return sum_value / sum_weight;
223 | }
224 |
225 | internal static IEnumerable WeightedFilter(this IList source, double start, double end, Func weightSelector, Func resultSelector)
226 | {
227 | if (source == null) throw new ArgumentNullException(nameof(source));
228 | if (start < 0 || start > 1) throw new ArgumentOutOfRangeException(nameof(start));
229 | if (end < start || start + end > 1) throw new ArgumentOutOfRangeException(nameof(end));
230 | if (weightSelector == null) throw new ArgumentNullException(nameof(weightSelector));
231 | if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector));
232 | if (source.Count == 0 || start == end) yield break;
233 | double amount = source.Sum(weightSelector);
234 | long sum = 0;
235 | double current = 0;
236 | foreach (T item in source)
237 | {
238 | if (current >= end) break;
239 | long weight = weightSelector(item);
240 | sum += weight;
241 | double old = current;
242 | current = sum / amount;
243 | if (current <= start) continue;
244 | if (old < start)
245 | {
246 | if (current > end)
247 | {
248 | weight = (long)((end - start) * amount);
249 | }
250 | else
251 | {
252 | weight = (long)((current - start) * amount);
253 | }
254 | }
255 | else if (current > end)
256 | {
257 | weight = (long)((end - old) * amount);
258 | }
259 | yield return resultSelector(item, weight);
260 | }
261 | }
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/MedPoints/Storage.Data/LevelDB/NativeWrapper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace Storage.Data.LevelDB
5 | {
6 | public enum CompressionType : byte
7 | {
8 | kNoCompression = 0x0,
9 | kSnappyCompression = 0x1
10 | }
11 |
12 | public static class NativeWrapper
13 | {
14 | #region Logger
15 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
16 | public static extern IntPtr leveldb_logger_create(IntPtr /* Action */ logger);
17 |
18 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
19 | public static extern void leveldb_logger_destroy(IntPtr /* logger*/ option);
20 | #endregion
21 |
22 | #region DB
23 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
24 | public static extern IntPtr leveldb_open(IntPtr /* Options*/ options, string name, out IntPtr error);
25 |
26 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
27 | public static extern void leveldb_close(IntPtr /*DB */ db);
28 |
29 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
30 | public static extern void leveldb_put(IntPtr /* DB */ db, IntPtr /* WriteOptions*/ options, byte[] key, UIntPtr keylen, byte[] val, UIntPtr vallen, out IntPtr errptr);
31 |
32 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
33 | public static extern void leveldb_delete(IntPtr /* DB */ db, IntPtr /* WriteOptions*/ options, byte[] key, UIntPtr keylen, out IntPtr errptr);
34 |
35 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
36 | public static extern void leveldb_write(IntPtr /* DB */ db, IntPtr /* WriteOptions*/ options, IntPtr /* WriteBatch */ batch, out IntPtr errptr);
37 |
38 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
39 | public static extern IntPtr leveldb_get(IntPtr /* DB */ db, IntPtr /* ReadOptions*/ options, byte[] key, UIntPtr keylen, out UIntPtr vallen, out IntPtr errptr);
40 |
41 | //[DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
42 | //static extern void leveldb_approximate_sizes(IntPtr /* DB */ db, int num_ranges, byte[] range_start_key, long range_start_key_len, byte[] range_limit_key, long range_limit_key_len, out long sizes);
43 |
44 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
45 | public static extern IntPtr leveldb_create_iterator(IntPtr /* DB */ db, IntPtr /* ReadOption */ options);
46 |
47 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
48 | public static extern IntPtr leveldb_create_snapshot(IntPtr /* DB */ db);
49 |
50 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
51 | public static extern void leveldb_release_snapshot(IntPtr /* DB */ db, IntPtr /* SnapShot*/ snapshot);
52 |
53 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
54 | public static extern IntPtr leveldb_property_value(IntPtr /* DB */ db, string propname);
55 |
56 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
57 | public static extern void leveldb_repair_db(IntPtr /* Options*/ options, string name, out IntPtr error);
58 |
59 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
60 | public static extern void leveldb_destroy_db(IntPtr /* Options*/ options, string name, out IntPtr error);
61 |
62 | #region extensions
63 |
64 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
65 | public static extern void leveldb_free(IntPtr /* void */ ptr);
66 |
67 | #endregion
68 |
69 |
70 | #endregion
71 |
72 | #region Env
73 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
74 | public static extern IntPtr leveldb_create_default_env();
75 |
76 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
77 | public static extern void leveldb_env_destroy(IntPtr /*Env*/ cache);
78 | #endregion
79 |
80 | #region Iterator
81 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
82 | public static extern void leveldb_iter_destroy(IntPtr /*Iterator*/ iterator);
83 |
84 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
85 | [return: MarshalAs(UnmanagedType.U1)]
86 | public static extern bool leveldb_iter_valid(IntPtr /*Iterator*/ iterator);
87 |
88 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
89 | public static extern void leveldb_iter_seek_to_first(IntPtr /*Iterator*/ iterator);
90 |
91 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
92 | public static extern void leveldb_iter_seek_to_last(IntPtr /*Iterator*/ iterator);
93 |
94 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
95 | public static extern void leveldb_iter_seek(IntPtr /*Iterator*/ iterator, byte[] key, UIntPtr length);
96 |
97 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
98 | public static extern void leveldb_iter_next(IntPtr /*Iterator*/ iterator);
99 |
100 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
101 | public static extern void leveldb_iter_prev(IntPtr /*Iterator*/ iterator);
102 |
103 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
104 | public static extern IntPtr leveldb_iter_key(IntPtr /*Iterator*/ iterator, out UIntPtr length);
105 |
106 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
107 | public static extern IntPtr leveldb_iter_value(IntPtr /*Iterator*/ iterator, out UIntPtr length);
108 |
109 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
110 | public static extern void leveldb_iter_get_error(IntPtr /*Iterator*/ iterator, out IntPtr error);
111 | #endregion
112 |
113 | #region Options
114 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
115 | public static extern IntPtr leveldb_options_create();
116 |
117 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
118 | public static extern void leveldb_options_destroy(IntPtr /*Options*/ options);
119 |
120 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
121 | public static extern void leveldb_options_set_create_if_missing(IntPtr /*Options*/ options, [MarshalAs(UnmanagedType.U1)] bool o);
122 |
123 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
124 | public static extern void leveldb_options_set_error_if_exists(IntPtr /*Options*/ options, [MarshalAs(UnmanagedType.U1)] bool o);
125 |
126 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
127 | public static extern void leveldb_options_set_info_log(IntPtr /*Options*/ options, IntPtr /* Logger */ logger);
128 |
129 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
130 | public static extern void leveldb_options_set_paranoid_checks(IntPtr /*Options*/ options, [MarshalAs(UnmanagedType.U1)] bool o);
131 |
132 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
133 | public static extern void leveldb_options_set_env(IntPtr /*Options*/ options, IntPtr /*Env*/ env);
134 |
135 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
136 | public static extern void leveldb_options_set_write_buffer_size(IntPtr /*Options*/ options, UIntPtr size);
137 |
138 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
139 | public static extern void leveldb_options_set_max_open_files(IntPtr /*Options*/ options, int max);
140 |
141 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
142 | public static extern void leveldb_options_set_cache(IntPtr /*Options*/ options, IntPtr /*Cache*/ cache);
143 |
144 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
145 | public static extern void leveldb_options_set_block_size(IntPtr /*Options*/ options, UIntPtr size);
146 |
147 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
148 | public static extern void leveldb_options_set_block_restart_interval(IntPtr /*Options*/ options, int interval);
149 |
150 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
151 | public static extern void leveldb_options_set_compression(IntPtr /*Options*/ options, CompressionType level);
152 |
153 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
154 | public static extern void leveldb_options_set_comparator(IntPtr /*Options*/ options, IntPtr /*Comparator*/ comparer);
155 |
156 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
157 | public static extern void leveldb_options_set_filter_policy(IntPtr /*Options*/ options, IntPtr /*FilterPolicy*/ policy);
158 | #endregion
159 |
160 | #region ReadOptions
161 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
162 | public static extern IntPtr leveldb_readoptions_create();
163 |
164 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
165 | public static extern void leveldb_readoptions_destroy(IntPtr /*ReadOptions*/ options);
166 |
167 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
168 | public static extern void leveldb_readoptions_set_verify_checksums(IntPtr /*ReadOptions*/ options, [MarshalAs(UnmanagedType.U1)] bool o);
169 |
170 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
171 | public static extern void leveldb_readoptions_set_fill_cache(IntPtr /*ReadOptions*/ options, [MarshalAs(UnmanagedType.U1)] bool o);
172 |
173 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
174 | public static extern void leveldb_readoptions_set_snapshot(IntPtr /*ReadOptions*/ options, IntPtr /*SnapShot*/ snapshot);
175 | #endregion
176 |
177 | #region WriteBatch
178 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
179 | public static extern IntPtr leveldb_writebatch_create();
180 |
181 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
182 | public static extern void leveldb_writebatch_destroy(IntPtr /* WriteBatch */ batch);
183 |
184 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
185 | public static extern void leveldb_writebatch_clear(IntPtr /* WriteBatch */ batch);
186 |
187 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
188 | public static extern void leveldb_writebatch_put(IntPtr /* WriteBatch */ batch, byte[] key, UIntPtr keylen, byte[] val, UIntPtr vallen);
189 |
190 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
191 | public static extern void leveldb_writebatch_delete(IntPtr /* WriteBatch */ batch, byte[] key, UIntPtr keylen);
192 |
193 | [DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
194 | public static extern void leveldb_writebatch_iterate(IntPtr /* WriteBatch */ batch, object state, Action