├── .tfignore ├── README.md ├── Ethereum ├── Wire │ ├── NAT.cs │ ├── NATPMP.cs │ ├── NATUPnP.cs │ └── MessageType.cs ├── Core │ ├── Block.cs │ ├── Error.cs │ ├── Fees.cs │ ├── Stack.cs │ ├── Contract.cs │ ├── Dagger.cs │ ├── Genesis.cs │ ├── BlockChain.cs │ ├── DaggerTest.cs │ ├── BlockManager.cs │ ├── Transaction.cs │ ├── TransactionPool.cs │ ├── TransactionTest.cs │ ├── BlockManagerTest.cs │ └── Address.cs ├── Utilities │ ├── Big.cs │ ├── Bytes.cs │ ├── Config.cs │ ├── Random.cs │ ├── Value.cs │ ├── Database.cs │ ├── Helpers.cs │ ├── Parsing.cs │ ├── Trie.cs │ ├── DecodeResult.cs │ ├── RLPEncoder.cs │ ├── Encoder.cs │ ├── CompactEncoder.cs │ ├── Converter.cs │ ├── Extensions.cs │ └── RLPDecoder.cs ├── Database │ ├── Database.cs │ └── DatabaseTest.cs ├── Caps.cs ├── Peer.cs ├── DiscReason.cs ├── Properties │ └── AssemblyInfo.cs └── Ethereum.csproj ├── Ethereum.Test ├── DiscReasonTest.cs ├── Properties │ └── AssemblyInfo.cs ├── Converter.cs ├── CompactEncoderTest.cs ├── Ethereum.Test.csproj ├── RLPEncoderTest.cs └── RLPDecoderTest.cs ├── LICENSE ├── Ethereum.sln └── .gitignore /.tfignore: -------------------------------------------------------------------------------- 1 | \.git -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cs-ethereum 2 | =========== 3 | 4 | C# implementation of the Ethereum whitepaper. http://www.ethereum.org 5 | -------------------------------------------------------------------------------- /Ethereum/Wire/NAT.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Wire 8 | { 9 | } 10 | -------------------------------------------------------------------------------- /Ethereum/Core/Block.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class Block 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/Error.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class Error 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/Fees.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class Fees 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/Stack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class Stack 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Wire/NATPMP.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Wire 8 | { 9 | class NATPMP 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/Contract.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class Contract 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/Dagger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class Dagger 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/Genesis.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class Genesis 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Big.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | class Big 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Wire/NATUPnP.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Wire 8 | { 9 | class NATUPnP 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/BlockChain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class BlockChain 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/DaggerTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class DaggerTest 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Bytes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | class Bytes 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Config.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | class Config 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Random.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | class Random 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Value.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | class Value 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/BlockManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class BlockManager 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/Transaction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class Transaction 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Database/Database.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Database 8 | { 9 | class Database 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Database.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | class Database 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | class Helpers 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Parsing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | class Parsing 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/TransactionPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class TransactionPool 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/TransactionTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class TransactionTest 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Database/DatabaseTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Database 8 | { 9 | class DatabaseTest 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Core/BlockManagerTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Chain 8 | { 9 | class BlockManagerTest 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Trie.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using LevelDB; 7 | 8 | namespace Ethereum.Utilities 9 | { 10 | public class Trie 11 | { 12 | 13 | } 14 | 15 | public class Node 16 | { 17 | byte[] Value; 18 | byte[] Key; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Ethereum/Utilities/DecodeResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | public class DecodeResult 10 | { 11 | private UInt64 Position; 12 | private Object Decoded; 13 | 14 | public DecodeResult(UInt64 position, Object decoded) { 15 | this.Position = position; 16 | this.Decoded = decoded; 17 | } 18 | 19 | public UInt64 GetPosition() { 20 | return Position; 21 | } 22 | public Object GetDecoded() 23 | { 24 | return Decoded; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Ethereum/Caps.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum 8 | { 9 | public class Caps 10 | { 11 | private const int CapPeerDiscTy = 0x01; 12 | private const int CapTxTy = 0x02; 13 | private const int CapChainTy = 0x04; 14 | 15 | private string[] CapsToString = 16 | { 17 | "Peer discovery", 18 | "Transaction relaying", 19 | "Block chain relaying" 20 | }; 21 | 22 | public bool IsCap(byte capOne, byte capTwo) 23 | { 24 | return (capOne & capTwo) > 0; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Ethereum.Test/DiscReasonTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Ethereum; 4 | 5 | namespace Ethereum.Test 6 | { 7 | [TestClass] 8 | public class DiscReasonTest 9 | { 10 | [TestMethod] 11 | public void TestGetDiscReason() 12 | { 13 | Assert.AreEqual(DiscReason.GetDiscReason(0),"Disconnect requested"); 14 | Assert.AreEqual(DiscReason.GetDiscReason(1), "Disconnect TCP sys error"); 15 | Assert.AreEqual(DiscReason.GetDiscReason(6), "Disconnect wrong genesis block"); 16 | Assert.AreEqual(DiscReason.GetDiscReason(7), "Disconnect incompatible network"); 17 | Assert.AreEqual(DiscReason.GetDiscReason(8), "Unknown"); 18 | Assert.AreEqual(DiscReason.GetDiscReason(9), "Unknown"); 19 | Assert.AreEqual(DiscReason.GetDiscReason(100), "Unknown"); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Ethereum/Wire/MessageType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Wire 8 | { 9 | class MessageType 10 | { 11 | private readonly byte[] MagicToken = { 34, 64, 8, 145 }; 12 | 13 | public Dictionary MessageTypeToString = new Dictionary 14 | { 15 | { "MessageHandshakeTy", "Handshake" }, 16 | { "MessageDiscTy", "Disconnect" }, 17 | { "MessagePingTy", "Ping" }, 18 | { "MessagePongTy", "Pong" }, 19 | { "MessageGetPeersTy", "Get peers" }, 20 | { "MessagePeersTy", "Peers" }, 21 | { "MessageTxTy", "Transactions" }, 22 | { "MessageBlockTy", "Blocks" }, 23 | { "MessageGetChainTy", "Get chain" }, 24 | { "MessageNotInChainTy", "Not in chain" } 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Ethereum/Core/Address.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Numerics; 7 | 8 | namespace Ethereum.Core 9 | { 10 | class Address 11 | { 12 | public BigInteger Amount; 13 | public UInt64 Nonce; 14 | 15 | public Address(BigInteger amount) 16 | { 17 | this.Amount = amount; 18 | } 19 | 20 | public Address(BigInteger amount, UInt64 nonce) 21 | { 22 | this.Amount = amount; 23 | this.Nonce = nonce; 24 | } 25 | 26 | public Address(byte[] data) 27 | { 28 | this.RlpDecode(data); 29 | } 30 | 31 | public void AddFee(BigInteger fee) 32 | { 33 | this.Amount += fee; 34 | } 35 | 36 | //public byte[] RlpEncode() 37 | //{ 38 | // return RlpEncoder.Encode(); 39 | //} 40 | 41 | public void RlpDecode(byte[] data) 42 | { 43 | 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Etherchain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Ethereum/Peer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Net; 7 | 8 | namespace Ethereum 9 | { 10 | public class Peer 11 | { 12 | /*private const int OutputBufferSize = 50; 13 | private WebClient Connection; 14 | // outputQueue chan *ethwire.Msg 15 | private bool Inbound; 16 | private Int32 Connected; 17 | private Int32 Disconnect; 18 | private DateTime LastSend; 19 | private bool VersionKnown; 20 | private Int64 LastPong; 21 | private bool RequestedPeerList; 22 | private UInt16 Port; 23 | private Caps PeerCaps; 24 | private bool CatchingUp; 25 | private string Version; 26 | 27 | public Peer(WebClient connection, bool inbound) 28 | { 29 | // outputQueue: make(chan *ethwire.Msg, outputBufferSize) 30 | this.Connection = connection; 31 | this.Inbound = true; 32 | this.Disconnect = 0; 33 | this.Connected = 1; 34 | this.Port = 30303; 35 | // this.PubKey = pubkey; 36 | }*/ 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Ethereum/DiscReason.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum 8 | { 9 | public static class DiscReason 10 | { 11 | private const int DiscReRequested = 0x00; 12 | private const int DiscReTcpSysErr = 0x01; 13 | private const int DiscBadProto = 0x02; 14 | private const int DiscBadPeer = 0x03; 15 | private const int DiscTooManyPeers = 0x04; 16 | private const int DiscConnDup = 0x05; 17 | private const int DiscGenesisErr = 0x06; 18 | private const int DiscProtoErr = 0x07; 19 | 20 | private static string[] DiscReasonToString = 21 | { 22 | "Disconnect requested", 23 | "Disconnect TCP sys error", 24 | "Disconnect bad protocol", 25 | "Disconnect useless peer", 26 | "Disconnect too many peers", 27 | "Disconnect already connected", 28 | "Disconnect wrong genesis block", 29 | "Disconnect incompatible network" 30 | }; 31 | 32 | public static string GetDiscReason(uint discReason) 33 | { 34 | if (discReason >= DiscReasonToString.Length) 35 | { 36 | return "Unknown"; 37 | } 38 | return DiscReasonToString[discReason]; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Ethereum.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ethereum", "Ethereum\Ethereum.csproj", "{F3A3E82E-0148-46CF-A7B1-0661C95AD657}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ethereum.Test", "Ethereum.Test\Ethereum.Test.csproj", "{D1DEF511-2E33-47E9-A49F-E059840040C6}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {F3A3E82E-0148-46CF-A7B1-0661C95AD657}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {F3A3E82E-0148-46CF-A7B1-0661C95AD657}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {F3A3E82E-0148-46CF-A7B1-0661C95AD657}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {F3A3E82E-0148-46CF-A7B1-0661C95AD657}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {D1DEF511-2E33-47E9-A49F-E059840040C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {D1DEF511-2E33-47E9-A49F-E059840040C6}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {D1DEF511-2E33-47E9-A49F-E059840040C6}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {D1DEF511-2E33-47E9-A49F-E059840040C6}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /Ethereum/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Ethereum")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Ethereum")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a4e80767-3da7-4012-a855-2599d1ef0783")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Ethereum.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Ethereum.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Ethereum.Test")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3d1e1ebf-648a-4048-8647-977aab8c277d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Rr]elease/ 19 | x64/ 20 | *_i.c 21 | *_p.c 22 | *.ilk 23 | *.meta 24 | *.obj 25 | *.pch 26 | *.pdb 27 | *.pgc 28 | *.pgd 29 | *.rsp 30 | *.sbr 31 | *.tlb 32 | *.tli 33 | *.tlh 34 | *.tmp 35 | *.log 36 | *.vspscc 37 | *.vssscc 38 | .builds 39 | 40 | # Visual C++ cache files 41 | ipch/ 42 | *.aps 43 | *.ncb 44 | *.opensdf 45 | *.sdf 46 | 47 | # Visual Studio profiler 48 | *.psess 49 | *.vsp 50 | *.vspx 51 | 52 | # Guidance Automation Toolkit 53 | *.gpState 54 | 55 | # ReSharper is a .NET coding add-in 56 | _ReSharper* 57 | 58 | # NCrunch 59 | *.ncrunch* 60 | .*crunch*.local.xml 61 | 62 | # Installshield output folder 63 | [Ee]xpress 64 | 65 | # DocProject is a documentation generator add-in 66 | DocProject/buildhelp/ 67 | DocProject/Help/*.HxT 68 | DocProject/Help/*.HxC 69 | DocProject/Help/*.hhc 70 | DocProject/Help/*.hhk 71 | DocProject/Help/*.hhp 72 | DocProject/Help/Html2 73 | DocProject/Help/html 74 | 75 | # Click-Once directory 76 | publish 77 | 78 | # Publish Web Output 79 | *.Publish.xml 80 | 81 | # NuGet Packages Directory 82 | packages 83 | 84 | # Windows Azure Build Output 85 | csx 86 | *.build.csdef 87 | 88 | # Windows Store app package directory 89 | AppPackages/ 90 | 91 | # Others 92 | [Bb]in 93 | [Oo]bj 94 | sql 95 | TestResults 96 | [Tt]est[Rr]esult* 97 | *.Cache 98 | ClientBin 99 | [Ss]tyle[Cc]op.* 100 | ~$* 101 | *.dbmdl 102 | Generated_Code #added for RIA/Silverlight projects 103 | 104 | # Backup & report files from converting an old project file to a newer 105 | # Visual Studio version. Backup files are not needed, because we have git ;-) 106 | _UpgradeReport_Files/ 107 | Backup*/ 108 | UpgradeLog*.XML 109 | -------------------------------------------------------------------------------- /Ethereum/Utilities/RLPEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ethereum.Utilities 9 | { 10 | public static class RLPEncoder 11 | { 12 | private static readonly UInt64 MaxItemLength = UInt64.MaxValue; 13 | private static readonly int SizeThreshold = 56; 14 | private static readonly int OffsetShortItem = 0x80; 15 | private static readonly int OffsetShortList = 0xc0; 16 | 17 | public static byte[] Encode(Object input) 18 | { 19 | if (input is Array) 20 | { 21 | Object[] inputArray = (Object[])input; 22 | if (inputArray.Length == 0) 23 | { 24 | return EncodeLength(inputArray.Length, OffsetShortList); 25 | } 26 | byte[] output = new byte[0]; 27 | foreach (Object arrayObject in inputArray) 28 | { 29 | output = Encoder.ConcatenateByteArrays(output, Encode(arrayObject)); 30 | } 31 | byte[] prefix = EncodeLength(output.Length, OffsetShortList); 32 | return Encoder.ConcatenateByteArrays(prefix, output); 33 | } 34 | else 35 | { 36 | if (input == null) 37 | { 38 | throw new ArgumentNullException("The input is null"); 39 | } 40 | byte[] inputAsHex = Encoder.ToHex(input); 41 | if (inputAsHex.Length == 1) 42 | { 43 | return inputAsHex; 44 | } 45 | else 46 | { 47 | byte[] firstByte = EncodeLength(inputAsHex.Length, OffsetShortItem); 48 | return Encoder.ConcatenateByteArrays(firstByte, inputAsHex); 49 | } 50 | } 51 | } 52 | 53 | public static byte[] EncodeLength(int length, int offset) 54 | { 55 | if (length < SizeThreshold) 56 | { 57 | byte firstByte = (byte)(length + offset); 58 | return new byte[] { firstByte }; 59 | } 60 | else if ((UInt64)length < MaxItemLength) 61 | { 62 | byte[] binaryLength = Encoder.ConvertUInt64ToByteArray((UInt64)length); 63 | byte firstByte = (byte)(binaryLength.Length + offset + SizeThreshold - 1); 64 | return Encoder.ConcatenateByteArrays(new byte[] { firstByte }, binaryLength); 65 | } 66 | throw new Exception("Input too long"); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Encoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | public static class Encoder 10 | { 11 | public static byte[] ToHex(Object input) 12 | { 13 | UInt64 inputInt; 14 | bool isNum = UInt64.TryParse(input.ToString(), out inputInt); 15 | if (isNum) 16 | { 17 | return (inputInt == 0) ? new byte[0] : ConvertUInt64ToByteArray(inputInt); 18 | } 19 | else if (input is string) 20 | { 21 | string inputString = (string)input; 22 | return Encoding.ASCII.GetBytes(inputString.ToCharArray()); 23 | } 24 | throw new Exception("Unsupported type: Only accepting String, Integer and BigInteger for now"); 25 | } 26 | 27 | public static byte[] ConvertUInt64ToByteArray(UInt64 input) 28 | { 29 | byte[] uInt64AsByteArray = BitConverter.GetBytes(input); 30 | Array.Reverse(uInt64AsByteArray); 31 | var i = 0; 32 | while (uInt64AsByteArray[i] == 0) 33 | { 34 | ++i; 35 | } 36 | byte[] result = new byte[uInt64AsByteArray.Length - i]; 37 | Array.Copy(uInt64AsByteArray, i, result, 0, uInt64AsByteArray.Length - i); 38 | return result; 39 | } 40 | 41 | public static byte[] ConcatenateByteArrays(byte[] inputArrayOne, byte[] inputArrayTwo) 42 | { 43 | byte[] result = new byte[inputArrayOne.Length + inputArrayTwo.Length]; 44 | Array.Copy(inputArrayOne, 0, result, 0, inputArrayOne.Length); 45 | Array.Copy(inputArrayTwo, 0, result, inputArrayOne.Length, inputArrayTwo.Length); 46 | return result; 47 | } 48 | 49 | public static byte[] AppendByteToArray(byte[] inputArray, byte inputByte) 50 | { 51 | byte[] result = new byte[inputArray.Length + 1]; 52 | Array.Copy(inputArray, 0, result, 0, inputArray.Length); 53 | result[result.Length - 1] = inputByte; 54 | return result; 55 | } 56 | 57 | public static byte[] RemoveLastXBytes(byte[] inputArray, int amountOfBytes) 58 | { 59 | byte[] result = new byte[inputArray.Length - amountOfBytes]; 60 | Array.Copy(inputArray, 0, result, 0, inputArray.Length - amountOfBytes); 61 | return result; 62 | } 63 | 64 | public static byte[] RemoveFirstXBytes(byte[] inputArray, int amountOfBytes) 65 | { 66 | byte[] result = new byte[inputArray.Length - amountOfBytes]; 67 | Array.Copy(inputArray, amountOfBytes, result, 0, inputArray.Length - amountOfBytes); 68 | return result; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Ethereum/Utilities/CompactEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.IO; 7 | 8 | namespace Ethereum.Utilities 9 | { 10 | public static class CompactEncoder 11 | { 12 | private static byte TERMINATOR = 16; 13 | 14 | public static byte[] CompactEncode(byte[] hexSlice) 15 | { 16 | byte terminator = 0; 17 | 18 | if (hexSlice[hexSlice.Length - 1] == TERMINATOR) 19 | { 20 | terminator = 1; 21 | hexSlice = Encoder.RemoveLastXBytes(hexSlice, 1); 22 | } 23 | 24 | int oddlen = hexSlice.Length % 2; 25 | int flag = 2 * terminator + oddlen; 26 | if (oddlen != 0) 27 | { 28 | byte[] flags = new byte[] { (byte)flag }; 29 | hexSlice = Encoder.ConcatenateByteArrays(flags, hexSlice); 30 | } 31 | else 32 | { 33 | byte[] flags = new byte[] { (byte)flag, 0 }; 34 | hexSlice = Encoder.ConcatenateByteArrays(flags, hexSlice); 35 | } 36 | 37 | MemoryStream buffer = new MemoryStream(); 38 | for (int i = 0; i < hexSlice.Length; i += 2) 39 | { 40 | buffer.WriteByte((byte)(16 * hexSlice[i] + hexSlice[i + 1])); 41 | } 42 | return buffer.ToArray(); 43 | } 44 | 45 | public static byte[] CompactDecode(byte[] str) 46 | { 47 | byte[] result = CompactHexDecode(str); 48 | result = Encoder.RemoveLastXBytes(result, 1); 49 | if (result[0] >= 2) 50 | { 51 | result = Encoder.AppendByteToArray(result, TERMINATOR); 52 | } 53 | if (result[0] % 2 == 1) 54 | { 55 | result = Encoder.RemoveFirstXBytes(result, 1); 56 | } 57 | else 58 | { 59 | result = Encoder.RemoveFirstXBytes(result, 2); 60 | } 61 | return result; 62 | } 63 | 64 | public static byte[] CompactHexDecode(byte[] hexEncoded) 65 | { 66 | char[] charArray = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 67 | byte[] hexSlice = new byte[0]; 68 | foreach (byte number in hexEncoded) 69 | { 70 | string hexValue = number.ToHex(); 71 | char[] hexValueSplitted = hexValue.ToCharArray(); 72 | hexSlice = Encoder.AppendByteToArray(hexSlice, (byte)Array.IndexOf(charArray, hexValueSplitted[0])); 73 | hexSlice = Encoder.AppendByteToArray(hexSlice, (byte)Array.IndexOf(charArray, hexValueSplitted[1])); 74 | } 75 | hexSlice = Encoder.AppendByteToArray(hexSlice, TERMINATOR); 76 | return hexSlice; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Ethereum.Test/Converter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Test 8 | { 9 | public static class Converter 10 | { 11 | public static UInt64 ConvertByteArrayToUInt64(byte[] input) 12 | { 13 | if (input.Length < 8) 14 | { 15 | byte[] tempArray = new byte[8]; 16 | Array.Copy(input, 0, tempArray, (tempArray.Length - input.Length), input.Length); 17 | Array.Reverse(tempArray); 18 | return BitConverter.ToUInt64(tempArray, 0); 19 | } 20 | return BitConverter.ToUInt64(input, 0); 21 | } 22 | 23 | /// Code from http://blogs.msdn.com/b/blambert/archive/2009/02/22/blambert-codesnip-fast-byte-array-to-hex-string-conversion.aspx 24 | 25 | private static readonly string[] HexStringTable = new string[] 26 | { 27 | "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 28 | "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 29 | "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 30 | "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 31 | "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 32 | "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 33 | "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 34 | "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 35 | "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 36 | "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 37 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 38 | "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 39 | "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 40 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", 41 | "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 42 | "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" 43 | }; 44 | 45 | public static string ToHex(this byte[] value) 46 | { 47 | StringBuilder stringBuilder = new StringBuilder(); 48 | if (value != null) 49 | { 50 | foreach (byte b in value) 51 | { 52 | stringBuilder.Append(HexStringTable[b]); 53 | } 54 | } 55 | return stringBuilder.ToString(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Converter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum 8 | { 9 | public static class Converter 10 | { 11 | public static UInt64 ConvertByteArrayToUInt64(byte[] input) 12 | { 13 | if (input.Length < 8) 14 | { 15 | byte[] tempArray = new byte[8]; 16 | Array.Copy(input, 0, tempArray, (tempArray.Length - input.Length), input.Length); 17 | Array.Reverse(tempArray); 18 | return BitConverter.ToUInt64(tempArray, 0); 19 | } 20 | return BitConverter.ToUInt64(input, 0); 21 | } 22 | 23 | /// Code from http://blogs.msdn.com/b/blambert/archive/2009/02/22/blambert-codesnip-fast-byte-array-to-hex-string-conversion.aspx 24 | 25 | private static readonly string[] HexStringTable = new string[] 26 | { 27 | "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 28 | "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 29 | "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 30 | "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 31 | "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 32 | "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 33 | "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 34 | "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 35 | "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 36 | "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 37 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 38 | "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 39 | "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 40 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", 41 | "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 42 | "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" 43 | }; 44 | 45 | public static string ToHex(this byte[] value) 46 | { 47 | StringBuilder stringBuilder = new StringBuilder(); 48 | if (value != null) 49 | { 50 | foreach (byte b in value) 51 | { 52 | stringBuilder.Append(HexStringTable[b]); 53 | } 54 | } 55 | return stringBuilder.ToString(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Ethereum/Utilities/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Ethereum.Utilities 8 | { 9 | public static class Extensions 10 | { 11 | // Code from: http://www.dotnetperls.com/array-slice 12 | /// 13 | /// Get the array slice between the two indexes. 14 | /// ... Inclusive for start index, exclusive for end index. 15 | /// 16 | public static T[] Slice(this T[] source, UInt64 start, UInt64 end) 17 | { 18 | // Handles negative ends. 19 | if (end < 0) 20 | { 21 | end = BitConverter.ToUInt64(BitConverter.GetBytes(source.LongLength), 0) + end; 22 | } 23 | UInt64 len = end - start; 24 | 25 | // Return new array. 26 | T[] res = new T[len]; 27 | for (UInt64 i = 0; i < len; i++) 28 | { 29 | res[i] = source[i + start]; 30 | } 31 | return res; 32 | } 33 | 34 | // Code from: http://stackoverflow.com/questions/11290390/checking-if-a-typed-object-array-is-not-empty 35 | public static bool ContainsOnlyEmpty(this IEnumerable source) 36 | { 37 | return source.All(t => t == null); 38 | } 39 | 40 | /// Code from http://blogs.msdn.com/b/blambert/archive/2009/02/22/blambert-codesnip-fast-byte-array-to-hex-string-conversion.aspx 41 | 42 | private static readonly string[] HexStringTable = new string[] 43 | { 44 | "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 45 | "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 46 | "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 47 | "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 48 | "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 49 | "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 50 | "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 51 | "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 52 | "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 53 | "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 54 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 55 | "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 56 | "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 57 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", 58 | "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 59 | "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" 60 | }; 61 | 62 | public static string ToHex(this byte value) 63 | { 64 | return HexStringTable[value]; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Ethereum.Test/CompactEncoderTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Ethereum.Utilities; 4 | using System.Text; 5 | 6 | namespace Ethereum.Test 7 | { 8 | [TestClass] 9 | public class CompactEncoderTest 10 | { 11 | private readonly static byte T = 16; // terminator 12 | 13 | [TestMethod] 14 | public void TestCompactEncodeOne() 15 | { 16 | byte[] test = new byte[] { 1, 2, 3, 4, 5 }; 17 | byte[] expected = new byte[] { 0x11, 0x23, 0x45 }; 18 | byte[] result = CompactEncoder.CompactEncode(test); 19 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 20 | } 21 | 22 | [TestMethod] 23 | public void TestCompactEncodeTwo() 24 | { 25 | byte[] test = new byte[] { 0, 1, 2, 3, 4, 5 }; 26 | byte[] expected = new byte[] { 0x00, 0x01, 0x23, 0x45 }; 27 | byte[] result = CompactEncoder.CompactEncode(test); 28 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 29 | } 30 | 31 | [TestMethod] 32 | public void TestCompactEncodeThree() 33 | { 34 | byte[] test = new byte[] { 0, 15, 1, 12, 11, 8, T }; 35 | byte[] expected = new byte[] { 0x20, 0x0f, 0x1c, 0xb8 }; 36 | byte[] result = CompactEncoder.CompactEncode(test); 37 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 38 | } 39 | 40 | [TestMethod] 41 | public void TestCompactEncodeFour() 42 | { 43 | byte[] test = new byte[] { 15, 1, 12, 11, 8, T }; 44 | byte[] expected = new byte[] { 0x3f, 0x1c, 0xb8 }; 45 | byte[] result = CompactEncoder.CompactEncode(test); 46 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 47 | } 48 | 49 | [TestMethod] 50 | public void TestCompactHexDecode() 51 | { 52 | byte[] test = Encoding.ASCII.GetBytes("verb"); 53 | byte[] expected = new byte[] { 7, 6, 6, 5, 7, 2, 6, 2, 16 }; 54 | byte[] result = CompactEncoder.CompactHexDecode(test); 55 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 56 | } 57 | 58 | [TestMethod] 59 | public void TestCompactDecodeOne() 60 | { 61 | byte[] test = new byte[] { 0x11, 0x23, 0x45 }; 62 | byte[] expected = new byte[] { 1, 2, 3, 4, 5 }; 63 | byte[] result = CompactEncoder.CompactDecode(test); 64 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 65 | } 66 | 67 | [TestMethod] 68 | public void TestCompactDecodeTwo() 69 | { 70 | byte[] test = new byte[] { 0x00, 0x01, 0x23, 0x45 }; 71 | byte[] expected = new byte[] { 0, 1, 2, 3, 4, 5 }; 72 | byte[] result = CompactEncoder.CompactDecode(test); 73 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 74 | } 75 | 76 | [TestMethod] 77 | public void TestCompactDecodeThree() 78 | { 79 | byte[] test = new byte[] { 0x20, 0x0f, 0x1c, 0xb8 }; 80 | byte[] expected = new byte[] { 0, 15, 1, 12, 11, 8, T }; 81 | byte[] result = CompactEncoder.CompactDecode(test); 82 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 83 | } 84 | 85 | [TestMethod] 86 | public void TestCompactDecodeFour() 87 | { 88 | byte[] test = new byte[] { 0x3f, 0x1c, 0xb8 }; 89 | byte[] expected = new byte[] { 15, 1, 12, 11, 8, T }; 90 | byte[] result = CompactEncoder.CompactDecode(test); 91 | Assert.AreEqual(Encoding.ASCII.GetString(result), Encoding.ASCII.GetString(expected)); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Ethereum/Ethereum.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F3A3E82E-0148-46CF-A7B1-0661C95AD657} 8 | Library 9 | Properties 10 | Ethereum 11 | Ethereum 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\..\leveldb-sharp-1.9.1\bin\Release\leveldb-sharp.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 97 | -------------------------------------------------------------------------------- /Ethereum.Test/Ethereum.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {D1DEF511-2E33-47E9-A49F-E059840040C6} 7 | Library 8 | Properties 9 | Ethereum.Test 10 | Ethereum.Test 11 | v4.5 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | {f3a3e82e-0148-46cf-a7b1-0661c95ad657} 63 | Ethereum 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | False 72 | 73 | 74 | False 75 | 76 | 77 | False 78 | 79 | 80 | False 81 | 82 | 83 | 84 | 85 | 86 | 87 | 94 | -------------------------------------------------------------------------------- /Ethereum/Utilities/RLPDecoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Ethereum.Utilities 9 | { 10 | public static class RLPDecoder 11 | { 12 | /** RLP encoding rules are defined as follows: */ 13 | 14 | /* 15 | * For a single byte whose value is in the [0x00, 0x7f] range, that byte is 16 | * its own RLP encoding. 17 | */ 18 | 19 | /* 20 | * If a string is 0-55 bytes long, the RLP encoding consists of a single 21 | * byte with value 0x80 plus the length of the string followed by the 22 | * string. The range of the first byte is thus [0x80, 0xb7]. 23 | */ 24 | private static readonly UInt64 OffsetShortItem = 0x80; 25 | 26 | /* 27 | * If a string is more than 55 bytes long, the RLP encoding consists of a 28 | * single byte with value 0xb7 plus the length of the length of the string 29 | * in binary form, followed by the length of the string, followed by the 30 | * string. For example, a length-1024 string would be encoded as 31 | * \xb9\x04\x00 followed by the string. The range of the first byte is thus 32 | * [0xb8, 0xbf]. 33 | */ 34 | private static readonly UInt64 OffsetLongItem = 0xb8; 35 | 36 | /* 37 | * If the total payload of a list (i.e. the combined length of all its 38 | * items) is 0-55 bytes long, the RLP encoding consists of a single byte 39 | * with value 0xc0 plus the length of the list followed by the concatenation 40 | * of the RLP encodings of the items. The range of the first byte is thus 41 | * [0xc0, 0xf7]. 42 | */ 43 | private static readonly UInt64 OffsetShortList = 0xc0; 44 | 45 | /* 46 | * If the total payload of a list is more than 55 bytes long, the RLP 47 | * encoding consists of a single byte with value 0xf7 plus the length of the 48 | * length of the list in binary form, followed by the length of the list, 49 | * followed by the concatenation of the RLP encodings of the items. The 50 | * range of the first byte is thus [0xf8, 0xff]. 51 | */ 52 | private static readonly UInt64 OffsetLongList = 0xf8; 53 | private static readonly UInt64 MaxPrefix = 0xff; 54 | 55 | public static DecodeResult Decode(byte[] data, UInt64 pos) 56 | { 57 | if (data == null || data.Length < 1) 58 | { 59 | return null; 60 | } 61 | 62 | UInt64 prefix = data[pos] & MaxPrefix; 63 | if (prefix == OffsetShortItem) 64 | { 65 | return new DecodeResult(pos + 1, new byte[0]); // means no length or 0 66 | } 67 | else if (prefix < OffsetShortItem) 68 | { 69 | return new DecodeResult(pos + 1, new byte[] { data[pos] }); // byte is its own RLP encoding 70 | } 71 | else if (prefix < OffsetLongItem) 72 | { 73 | UInt64 len = prefix - OffsetShortItem; // length of the encoded bytes 74 | return new DecodeResult(pos + 1 + len, data.Slice(pos + 1, pos + 1 + len)); 75 | } 76 | else if (prefix < OffsetShortList) 77 | { 78 | UInt64 lenlen = prefix - OffsetLongItem + 1; // length of length the encoded bytes 79 | UInt64 lenbytes = Converter.ConvertByteArrayToUInt64(data.Slice(pos + 1, pos + 1 + lenlen)); // length of encoded bytes 80 | return new DecodeResult(pos + 1 + lenlen + lenbytes, data.Slice(pos + 1 + lenlen, pos + 1 + lenlen + lenbytes)); 81 | } 82 | else if (prefix < OffsetLongList) 83 | { 84 | UInt64 len = prefix - OffsetShortList; // length of the encoded list 85 | UInt64 prevPos = pos; pos++; 86 | return DecodeList(data, pos, prevPos, len); 87 | } 88 | else if (prefix < MaxPrefix) 89 | { 90 | UInt64 lenlen = prefix - OffsetLongList + 1; // length of length the encoded list 91 | UInt64 lenlist = Converter.ConvertByteArrayToUInt64(data.Slice(pos + 1, pos + 1 + lenlen)); // length of encoded bytes 92 | pos = pos + lenlen + 1; 93 | UInt64 prevPos = lenlist; 94 | return DecodeList(data, pos, prevPos, lenlist); 95 | } 96 | else 97 | { 98 | throw new Exception("Only byte values between 0x00 and 0xFF are supported, but got: " + prefix); 99 | } 100 | } 101 | 102 | private static DecodeResult DecodeList(byte[] data, UInt64 pos, UInt64 prevPos, UInt64 len) 103 | { 104 | List slice = new List(); // temporary list for easily adding bytes arrays 105 | for (UInt64 i = 0; i < len; ) 106 | { 107 | // Get the next item in the data list and append it 108 | DecodeResult result = Decode(data, pos); 109 | slice.Add(result.GetDecoded()); 110 | // Increment pos by the amount bytes in the previous read 111 | prevPos = result.GetPosition(); 112 | i += (prevPos - pos); 113 | pos = prevPos; 114 | } 115 | return new DecodeResult(pos, slice.ToArray()); 116 | } 117 | 118 | // Code from: http://stackoverflow.com/questions/321370/convert-hex-string-to-byte-array 119 | public static byte[] StringToByteArray(string hex) 120 | { 121 | if (hex.Length % 2 == 1) 122 | throw new Exception("The binary key cannot have an odd number of digits"); 123 | 124 | byte[] arr = new byte[hex.Length >> 1]; 125 | 126 | for (int i = 0; i < hex.Length >> 1; ++i) 127 | { 128 | arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1]))); 129 | } 130 | 131 | return arr; 132 | } 133 | 134 | private static int GetHexVal(char hex) 135 | { 136 | int val = (int)hex; 137 | return val - (val < 58 ? 48 : 87); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Ethereum.Test/RLPEncoderTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Ethereum.Utilities; 4 | using System.Text; 5 | 6 | namespace Ethereum.Test.Utilities 7 | { 8 | [TestClass] 9 | public class RLPEncoderTest 10 | { 11 | [TestMethod] 12 | [ExpectedException(typeof(ArgumentNullException), "The input is null")] 13 | public void TestEncodeNull() 14 | { 15 | byte[] result = RLPEncoder.Encode(null); 16 | } 17 | 18 | [TestMethod] 19 | public void TestEncodeSingleCharacter() 20 | { 21 | string test = "d"; 22 | string expected = "64"; 23 | string result = RLPEncoder.Encode(test).ToHex(); 24 | Assert.AreEqual(result, expected); 25 | } 26 | 27 | [TestMethod] 28 | public void TestEncodeSingleString() 29 | { 30 | string test = "dog"; 31 | string expected = "83646f67"; 32 | string result = RLPEncoder.Encode(test).ToHex(); 33 | Assert.AreEqual(result, expected); 34 | } 35 | 36 | [TestMethod] 37 | public void TestEncodeEmptyString() 38 | { 39 | string test = ""; 40 | string expected = "80"; 41 | string result = RLPEncoder.Encode(test).ToHex(); 42 | Assert.AreEqual(result, expected); 43 | } 44 | 45 | [TestMethod] 46 | public void TestEncodeArrayOfEmptyStrings() 47 | { 48 | string[] test = new string[] { }; 49 | string expected = "c0"; 50 | string result = RLPEncoder.Encode(test).ToHex(); 51 | Assert.AreEqual(result, expected); 52 | } 53 | 54 | [TestMethod] 55 | public void TestEncodeZero() 56 | { 57 | int test = 0; 58 | string expected = "80"; 59 | string result = RLPEncoder.Encode(test).ToHex(); 60 | Assert.AreEqual(result, expected); 61 | } 62 | 63 | [TestMethod] 64 | public void TestEncodeLowInteger() 65 | { 66 | int test = 15; 67 | string expected = "0f"; 68 | string result = RLPEncoder.Encode(test).ToHex(); 69 | Assert.AreEqual(result, expected); 70 | } 71 | 72 | [TestMethod] 73 | public void TestEncodeMediumInteger() 74 | { 75 | int test = 1024; 76 | string expected = "820400"; 77 | string result = RLPEncoder.Encode(test).ToHex(); 78 | Assert.AreEqual(result, expected); 79 | } 80 | 81 | [TestMethod] 82 | public void TestEncodeBigInteger() 83 | { 84 | UInt64 test = 18446744073709551615; 85 | string expected = "88ffffffffffffffff"; 86 | string result = RLPEncoder.Encode(test).ToHex(); 87 | Assert.AreEqual(result, expected); 88 | } 89 | 90 | [TestMethod] 91 | public void TestEncodeLongString() 92 | { 93 | string test = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"; 94 | string expected = "b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974"; 95 | string result = RLPEncoder.Encode(test).ToHex(); 96 | Assert.AreEqual(result, expected); 97 | } 98 | 99 | [TestMethod] 100 | public void TestEncodeEmptyStringList() 101 | { 102 | string[] test = new string[0]; 103 | string expected = "c0"; 104 | string result = RLPEncoder.Encode(test).ToHex(); 105 | Assert.AreEqual(result, expected); 106 | } 107 | 108 | [TestMethod] 109 | public void TestEncodeShortStringList() 110 | { 111 | string[] test = new string[] { "dog", "god", "cat" }; 112 | string expected = "cc83646f6783676f6483636174"; 113 | string result = RLPEncoder.Encode(test).ToHex(); 114 | Assert.AreEqual(result, expected); 115 | } 116 | 117 | [TestMethod] 118 | public void TestEncodeLongStringList() 119 | { 120 | string[] test = new string[] { "cat", "Lorem ipsum dolor sit amet, consectetur adipisicing elit" }; 121 | string expected = "f83e83636174b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974"; 122 | string result = RLPEncoder.Encode(test).ToHex(); 123 | Assert.AreEqual(result, expected); 124 | } 125 | 126 | [TestMethod] 127 | public void TestEncodeMultiList() 128 | { 129 | Object[] test = new Object[] { 1, new Object[] { "cat" }, "dog", new Object[] { 2 } }; 130 | string expected = "cc01c48363617483646f67c102"; 131 | string result = RLPEncoder.Encode(test).ToHex(); 132 | Assert.AreEqual(result, expected); 133 | } 134 | 135 | [TestMethod] 136 | public void TestEncodeListOfEmptyLists() 137 | { 138 | Object[] test = new Object[] { new Object[] { new Object[] { }, new Object[] { } }, new Object[] { } }; 139 | string expected = "c4c2c0c0c0"; 140 | string result = RLPEncoder.Encode(test).ToHex(); 141 | Assert.AreEqual(result, expected); 142 | } 143 | 144 | [TestMethod] 145 | public void TestEncodeTwoListsOfEmptyLists() 146 | { 147 | Object[] test = new Object[] { new Object[] { }, new Object[] { new Object[] { } }, new Object[] { new Object[] { }, new Object[] { new Object[] { } } } }; 148 | string expected = "c7c0c1c0c3c0c1c0"; 149 | string result = RLPEncoder.Encode(test).ToHex(); 150 | Assert.AreEqual(result, expected); 151 | } 152 | 153 | [TestMethod] 154 | public void TestEncodeLengthLowerThan56() 155 | { 156 | int Length = 1; 157 | int Offset = 128; 158 | byte[] expected = new byte[] { (byte)0x81 }; 159 | byte[] EncodedLength = RLPEncoder.EncodeLength(Length, Offset); 160 | Assert.AreEqual(expected.ToHex(), EncodedLength.ToHex()); 161 | } 162 | 163 | [TestMethod] 164 | public void TestEncodeLengthHigherThan55() 165 | { 166 | int Length = 56; 167 | int Offset = 192; 168 | byte[] expected = new byte[] { 0xf8, 0x38 }; 169 | byte[] EncodedLength = RLPEncoder.EncodeLength(Length, Offset); 170 | Assert.AreEqual(expected.ToHex(), EncodedLength.ToHex()); 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /Ethereum.Test/RLPDecoderTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Ethereum.Utilities; 4 | using System.Text; 5 | 6 | namespace Ethereum.Test 7 | { 8 | [TestClass] 9 | public class RLPDecoderTest 10 | { 11 | [TestMethod] 12 | public void TestDecodeSingleCharacter() 13 | { 14 | string test = "64"; 15 | string expected = "d"; 16 | Object result = Encoding.ASCII.GetString((byte[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded()); 17 | Assert.AreEqual(expected, result); 18 | } 19 | 20 | [TestMethod] 21 | public void TestDecodeSingleString() 22 | { 23 | string test = "83646f67"; 24 | string expected = "dog"; 25 | Object result = Encoding.ASCII.GetString((byte[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded()); 26 | Assert.AreEqual(expected, result); 27 | } 28 | 29 | [TestMethod] 30 | public void TestDecodeEmptyString() 31 | { 32 | string test = "80"; 33 | string expected = ""; 34 | Object result = Encoding.ASCII.GetString((byte[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded()); 35 | Assert.AreEqual(expected, result); 36 | } 37 | 38 | [TestMethod] 39 | public void TestDecodeArrayOfEmptyStrings() 40 | { 41 | string test = "c0"; 42 | string[] expected = new string[] { }; 43 | bool expectedBool = (expected == null || expected.Length == 0); 44 | Object[] result = (Object[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded(); 45 | bool resultBool = result.ContainsOnlyEmpty(); 46 | Assert.AreEqual(expectedBool, resultBool); 47 | } 48 | 49 | [TestMethod] 50 | public void TestDecodeZero() 51 | { 52 | string test = "80"; 53 | UInt64 expected = 0; 54 | Object result = Converter.ConvertByteArrayToUInt64((byte[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded()); 55 | Assert.AreEqual(expected, result); 56 | } 57 | 58 | [TestMethod] 59 | public void TestDecodeLowInteger() 60 | { 61 | string test = "0f"; 62 | UInt64 expected = 15; 63 | Object result = Converter.ConvertByteArrayToUInt64((byte[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded()); 64 | Assert.AreEqual(expected, result); 65 | } 66 | 67 | [TestMethod] 68 | public void TestDecodeMediumInteger() 69 | { 70 | string test = "820400"; 71 | UInt64 expected = 1024; 72 | Object result = Converter.ConvertByteArrayToUInt64((byte[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded()); 73 | Assert.AreEqual(expected, result); 74 | } 75 | 76 | [TestMethod] 77 | public void TestDecodeBigInteger() 78 | { 79 | string test = "88ffffffffffffffff"; 80 | UInt64 expected = 18446744073709551615; 81 | Object result = Converter.ConvertByteArrayToUInt64((byte[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded()); 82 | Assert.AreEqual(expected, result); 83 | } 84 | 85 | [TestMethod] 86 | public void TestDecodeLongString() 87 | { 88 | string test = "b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974"; 89 | string expected = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"; 90 | Object result = Encoding.ASCII.GetString((byte[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded()); 91 | Assert.AreEqual(expected, result); 92 | } 93 | 94 | [TestMethod] 95 | public void TestDecodeEmptyStringList() 96 | { 97 | string test = "c0"; 98 | string[] expected = new string[0]; 99 | bool expectedBool = (expected == null || expected.Length == 0); 100 | Object[] result = (Object[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded(); 101 | bool resultBool = result.ContainsOnlyEmpty(); 102 | Assert.AreEqual(expectedBool, resultBool); 103 | } 104 | 105 | [TestMethod] 106 | public void TestDecodeShortStringList() 107 | { 108 | string test = "cc83646f6783676f6483636174"; 109 | string[] expected = new string[] { "dog", "god", "cat" }; 110 | Object[] result = (Object[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded(); 111 | Assert.AreEqual(expected[0], Encoding.ASCII.GetString((byte[])result[0])); 112 | Assert.AreEqual(expected[1], Encoding.ASCII.GetString((byte[])result[1])); 113 | Assert.AreEqual(expected[2], Encoding.ASCII.GetString((byte[])result[2])); 114 | } 115 | 116 | [TestMethod] 117 | public void TestDecodeLongStringList() // fails 118 | { 119 | string test = "f83e83636174b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974"; 120 | string[] expected = new string[] { "cat", "Lorem ipsum dolor sit amet, consectetur adipisicing elit" }; 121 | Object[] result = (Object[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded(); 122 | Assert.AreEqual(expected[0], Encoding.ASCII.GetString((byte[])result[0])); 123 | Assert.AreEqual(expected[1], Encoding.ASCII.GetString((byte[])result[1])); 124 | } 125 | 126 | [TestMethod] 127 | public void TestDecodeMultiList() // fails 128 | { 129 | string test = "cc01c48363617483646f67c102"; 130 | Object[] expected = new Object[] { (UInt64)1, new Object[] { "cat" }, "dog", new Object[] { (UInt64)2 } }; 131 | Object[] result = (Object[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded(); 132 | Assert.AreEqual(expected[0], Converter.ConvertByteArrayToUInt64((byte[])result[0])); 133 | Assert.AreEqual(expected[1].ToString(), result[1].ToString()); 134 | Assert.AreEqual(expected[2], Encoding.ASCII.GetString((byte[])result[2])); 135 | Assert.AreEqual(((Object[])expected[3])[0], Converter.ConvertByteArrayToUInt64((byte[])((Object[])result[3])[0])); 136 | } 137 | 138 | [TestMethod] 139 | public void TestDecodeListOfEmptyLists() // fails 140 | { 141 | string test = "c4c2c0c0c0"; 142 | Object[] expected = new Object[] { new Object[] { new Object[] { }, new Object[] { } }, new Object[] { } }; 143 | Object[] result = (Object[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded(); 144 | Assert.AreEqual(expected.ContainsOnlyEmpty(), result.ContainsOnlyEmpty()); 145 | } 146 | 147 | [TestMethod] 148 | public void TestDecodeTwoListsOfEmptyLists() // fails 149 | { 150 | string test = "c7c0c1c0c3c0c1c0"; 151 | Object[] expected = new Object[] { new Object[] { }, new Object[] { new Object[] { } }, new Object[] { new Object[] { }, new Object[] { new Object[] { } } } }; 152 | Object[] result = (Object[])RLPDecoder.Decode(RLPDecoder.StringToByteArray(test), UInt64.MinValue).GetDecoded(); 153 | Assert.AreEqual(expected.ContainsOnlyEmpty(), result.ContainsOnlyEmpty()); 154 | } 155 | } 156 | } 157 | --------------------------------------------------------------------------------