Exemple #1
0
 // Type handling
 public static RLPByteArray FromInteger(BigInteger bigInteger, int byteCount = 32, bool removeLeadingZeros = false)
 {
     if (!removeLeadingZeros)
     {
         return(new RLPByteArray(BigIntegerConverter.GetBytes(bigInteger, byteCount)));
     }
     else
     {
         return(new RLPByteArray(BigIntegerConverter.GetBytesWithoutLeadingZeros(bigInteger, byteCount)));
     }
 }
        public async Task ModExpTest()
        {
            // Test the modexp precompile.
            var gas = await _precompiles.testModExp(
                BigIntegerConverter.GetBytes(BigInteger.Parse("1212121323543453245345678346345737475734753745737774573475377734577", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("3", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("4345328123928357434573234217343477", CultureInfo.InvariantCulture)))
                      .EstimateGas();

            Assert.AreEqual(29900, gas);
        }
        public async Task EcRecoverTest()
        {
            var ecRecoverTest = await _contract.testECRecover(
                new byte[] { 0xc9, 0xf1, 0xc7, 0x66, 0x85, 0x84, 0x5e, 0xa8, 0x1c, 0xac, 0x99, 0x25, 0xa7, 0x56, 0x58, 0x87, 0xb7, 0x77, 0x1b, 0x34, 0xb3, 0x5e, 0x64, 0x1c, 0xca, 0x85, 0xdb, 0x9f, 0xef, 0xd0, 0xe7, 0x1f },
                0x1c,
                BigIntegerConverter.GetBytes(BigInteger.Parse("68932463183462156574914988273446447389145511361487771160486080715355143414637", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("47416572686988136438359045243120473513988610648720291068939984598262749281683", CultureInfo.InvariantCulture)))
                                .Call();

            Assert.AreEqual("0x75c8aa4b12bc52c1f1860bc4e8af981d6542cccd", ecRecoverTest.GetHexString(hexPrefix: true));
        }
        public async Task EcRecoverTest()
        {
            var gas = await _precompiles.testECRecover(
                new byte[] { 0xc9, 0xf1, 0xc7, 0x66, 0x85, 0x84, 0x5e, 0xa8, 0x1c, 0xac, 0x99, 0x25, 0xa7, 0x56, 0x58, 0x87, 0xb7, 0x77, 0x1b, 0x34, 0xb3, 0x5e, 0x64, 0x1c, 0xca, 0x85, 0xdb, 0x9f, 0xef, 0xd0, 0xe7, 0x1f },
                0x1c,
                BigIntegerConverter.GetBytes(BigInteger.Parse("68932463183462156574914988273446447389145511361487771160486080715355143414637", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("47416572686988136438359045243120473513988610648720291068939984598262749281683", CultureInfo.InvariantCulture)))
                      .EstimateGas();

            Assert.AreEqual(32437, gas);
        }
Exemple #5
0
        public void Push(BigInteger obj)
        {
            // Verify we aren't reaching our maximum stack size.
            if (Count >= MAX_STACK_SIZE)
            {
                throw new EVMException($"Stack has overflowed past the maximum size of {MAX_STACK_SIZE} entries.");
            }

            // Push the object to the top of the stack.
            _internalStack.Add(BigIntegerConverter.GetBytes(obj));
        }
        private static EVMExecutionResult Precompile_ECAdd(MeadowEVM evm)
        {
            // Verify we're past the byzantium fork
            if (evm.Version < EthereumRelease.Byzantium)
            {
                return(new EVMExecutionResult(evm, null, true));
            }

            // Charge the gas for the precompile operation before processing.
            BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_ECADD_BASE;

            evm.GasState.Deduct(gasCharge);

            // Obtain a memory representation of our data.
            Span <byte> messageData = new Span <byte>(evm.Message.Data);

            // Obtain our component data
            BigInteger x1 = BigIntegerConverter.GetBigInteger(messageData.Slice(0, EVMDefinitions.WORD_SIZE));
            BigInteger y1 = BigIntegerConverter.GetBigInteger(messageData.Slice(32, EVMDefinitions.WORD_SIZE));
            BigInteger x2 = BigIntegerConverter.GetBigInteger(messageData.Slice(64, EVMDefinitions.WORD_SIZE));
            BigInteger y2 = BigIntegerConverter.GetBigInteger(messageData.Slice(96, EVMDefinitions.WORD_SIZE));

            // Parse and verify our points.
            FpVector3 <Fp> point1 = ParsePoint(x1, y1);

            if (point1 == null)
            {
                throw new EVMException("ECAdd precompile failed because point 1 was deemed invalid when parsing.");
            }

            FpVector3 <Fp> point2 = ParsePoint(x2, y2);

            if (point1 == null)
            {
                throw new EVMException("ECAdd precompile failed because point 2 was deemed invalid when parsing.");
            }

            // Add the two points together
            FpVector3 <Fp> additionResult = point1.Add(point2);

            // Normalize the result into X/Y components.
            (Fp resultX, Fp resultY) = additionResult.Normalize();

            // Obtain the binary data for these results
            byte[] resultXData = BigIntegerConverter.GetBytes(resultX.N, EVMDefinitions.WORD_SIZE);
            byte[] resultYData = BigIntegerConverter.GetBytes(resultY.N, EVMDefinitions.WORD_SIZE);

            // Concat them to a singular result
            byte[] returnData = resultXData.Concat(resultYData);

            // Return our result
            return(new EVMExecutionResult(evm, returnData, true));
        }
Exemple #7
0
        public void LeadingBytesNegative()
        {
            BigInteger bigInt = -1;

            byte[] result = BigIntegerConverter.GetBytes(bigInt);
            for (int i = 0; i < result.Length; i++)
            {
                Assert.Equal(0xFF, result[i]);
            }

            Assert.Equal(0x20, result.Length);
        }
        public async Task ModExpTest()
        {
            // Test the modexp precompile.
            var modExpTestBytes = await _contract.testModExp(
                BigIntegerConverter.GetBytes(BigInteger.Parse("1212121323543453245345678346345737475734753745737774573475377734577", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("3", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("4345328123928357434573234217343477", CultureInfo.InvariantCulture)))
                                  .Call();

            // Convert the result into an integer.
            var modExpTest = BigIntegerConverter.GetBigInteger(modExpTestBytes, false, modExpTestBytes.Length);

            Assert.AreEqual("856753145937825219130387866259147", modExpTest.ToString(CultureInfo.InvariantCulture));
        }
Exemple #9
0
        public void ValuesUnchanged()
        {
            Random random = new Random();

            for (int i = 0; i < 100; i++)
            {
                byte[] data = new byte[random.Next(1, 0x20 + 1)];
                random.NextBytes(data);
                BigInteger bigInteger = BigIntegerConverter.GetBigInteger(data);
                byte[]     parsed     = BigIntegerConverter.GetBytes(bigInteger);
                for (int x = 0; x < Math.Min(data.Length, parsed.Length); x++)
                {
                    Assert.Equal(data[data.Length - x - 1], parsed[parsed.Length - x - 1]);
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Generates a bloom filter for a given item with a given byte count.
        /// </summary>
        /// <param name="item">The item to generate a bloom filter for.</param>
        /// <param name="byteCount">The amount of bytes that the item is made up of.</param>
        /// <returns>Returns the bloom filter generated for this item.</returns>
        public static BigInteger Generate(BigInteger item, int byteCount = EVMDefinitions.WORD_SIZE)
        {
            // Compute our hash for this item.
            byte[] hash = KeccakHash.ComputeHashBytes(BigIntegerConverter.GetBytes(item, byteCount));

            // Create our resulting bloom filter
            BigInteger bloomFilter = 0;

            // Out of the hash, for every 16-bit bit chunk we should cycle through, we use the 11-bits of the 16-bit integer as a bit index to set in our filter.
            for (int i = 0; i < BLOOM_CHUNK_COUNT * 2; i += 2)
            {
                int bitIndex = ((hash[i] << 8) | (hash[i + 1])) & 0x7FF; // mask into an 11-bit integer.
                bloomFilter |= ((BigInteger)1 << bitIndex);              // set the bit at that index
            }

            return(bloomFilter);
        }
Exemple #11
0
        public async Task TestPrecompiles()
        {
            // Grab a list of accounts
            var accounts = await Client.Accounts();

            // Deploy our test contract
            var contract = await BasicContract.New($"TestName", true, 34, Client, new TransactionParams { From = accounts[0], Gas = 4712388 }, accounts[0]);

            // 1) This ECRecover test should yield 0x75c8aa4b12bc52c1f1860bc4e8af981d6542cccd. This test data is taken from SigningTests.cs
            var ecRecoverTest = await contract.testECRecover(
                new byte[] { 0xc9, 0xf1, 0xc7, 0x66, 0x85, 0x84, 0x5e, 0xa8, 0x1c, 0xac, 0x99, 0x25, 0xa7, 0x56, 0x58, 0x87, 0xb7, 0x77, 0x1b, 0x34, 0xb3, 0x5e, 0x64, 0x1c, 0xca, 0x85, 0xdb, 0x9f, 0xef, 0xd0, 0xe7, 0x1f },
                0x1c,
                BigIntegerConverter.GetBytes(BigInteger.Parse("68932463183462156574914988273446447389145511361487771160486080715355143414637", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("47416572686988136438359045243120473513988610648720291068939984598262749281683", CultureInfo.InvariantCulture)))
                                .Call();

            Assert.Equal("0x75c8aa4b12bc52c1f1860bc4e8af981d6542cccd", ecRecoverTest);

            // Precompile hash tests

            // 2) SHA-256
            var sha256HashTest = await contract.sha256str("hello world").Call(); // should be 0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

            Assert.Equal("0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9", sha256HashTest.ToHexString(hexPrefix: true));

            // 3) RIPEMD160
            var ripemd160HashTest = await contract.ripemd160str("hello world").Call(); // should be 0x98c615784ccb5fe5936fbc0cbe9dfdb408d92f0f

            Assert.Equal("0x98c615784ccb5fe5936fbc0cbe9dfdb408d92f0f", ripemd160HashTest.ToHexString(hexPrefix: true));

            // 4) IDENTITY + 5) MODEXP (this function uses both)
            var modExpTestBytes = await contract.testModExp(
                BigIntegerConverter.GetBytes(BigInteger.Parse("1212121323543453245345678346345737475734753745737774573475377734577", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("3", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("4345328123928357434573234217343477", CultureInfo.InvariantCulture)))
                                  .Call();

            var modExpTest = BigIntegerConverter.GetBigInteger(modExpTestBytes, false, modExpTestBytes.Length); // should be 0x856753145937825219130387866259147

            Assert.Equal(BigInteger.Parse("856753145937825219130387866259147", CultureInfo.InvariantCulture), modExpTest);

            // TODO: 6) Checking a pairing equation on bn128 curve
            // TODO: 7) Addition of bn128 curve
            // TODO: 8) Scalar multiplication of bn128 curve.
        }
        /// <summary>
        /// Verifies a hash was signed correctly given the r and s signature components.
        /// </summary>
        /// <param name="hash">The hash which was signed.</param>
        /// <param name="r">The ECDSA signature component r.</param>
        /// <param name="s">The ECDSA signature component s.</param>
        /// <returns>Returns a boolean indicating whether the data was properly signed.</returns>
        public override bool VerifyData(Span <byte> hash, BigInteger r, BigInteger s)
        {
            // Obtain our secp256k1 instance.
            using (AutoObjectPool <Secp256k1> .Get(out var secp256k1))
            {
                // Allocate memory for the signature and call our sign function.
                Span <byte> signature       = BigIntegerConverter.GetBytes(r).Concat(BigIntegerConverter.GetBytes(s));
                Span <byte> signatureParsed = new byte[SIGNATURE_RSV_SIZE];

                // The verify method requires a parsed signature. The serialized signature we provide
                // should have recovery ID, but we can provide anything, since verifying signature
                // ignores the recovery ID, and only focuses on r + s components.
                if (!secp256k1.RecoverableSignatureParseCompact(signatureParsed, signature, 0))
                {
                    var errMsg = "Unmanaged EC library failed to parse the signature when verifying signature. ";
                    if (IncludeKeyDataInExceptions)
                    {
                        errMsg += $"MessageHash: {hash.ToHexString()}, Key: {UnmanagedKey.Span.ToHexString()}";
                    }

                    throw new Exception(errMsg);
                }

                // Define the parsed public key array
                Span <byte> parsedPublicKeyData = new byte[PUBLIC_KEY_SIZE];

                // Get a serialized public key, then parse it.
                byte[] serializedPublicKey = ToPublicKeyArray(false, false);
                if (!secp256k1.PublicKeyParse(parsedPublicKeyData, serializedPublicKey))
                {
                    var errMsg = "Unmanaged EC library failed to parse public key when verifying signature. ";
                    if (IncludeKeyDataInExceptions)
                    {
                        errMsg += $"MessageHash: {hash.ToHexString()}, Key: {UnmanagedKey.Span.ToHexString()}";
                    }

                    throw new Exception(errMsg);
                }

                // Verify the signature using the parsed public key.
                return(secp256k1.Verify(signatureParsed, hash, parsedPublicKeyData));
            }
        }
Exemple #13
0
        public void LeadingBytesPositive()
        {
            BigInteger bigInt = 1;

            byte[] result = BigIntegerConverter.GetBytes(bigInt);
            for (int i = 0; i < result.Length; i++)
            {
                if (i == result.Length - 1)
                {
                    Assert.Equal(0x01, result[i]);
                }
                else
                {
                    Assert.Equal(0x00, result[i]);
                }
            }

            Assert.Equal(0x20, result.Length);
        }
Exemple #14
0
        static EthereumEcdsaNative Generate(uint accountIndex, Secp256k1 secp256k1, IAccountDerivation accountFactory)
        {
            var privateKey = accountFactory.GeneratePrivateKey(accountIndex);

            if (!secp256k1.SecretKeyVerify(privateKey))
            {
                var errMsg = "Unmanaged EC library failed to valid private key. ";
                if (IncludeKeyDataInExceptions)
                {
                    errMsg += $"Private key: {privateKey.ToHexString()}";
                }

                throw new Exception(errMsg);
            }

            var keyBigInt = BigIntegerConverter.GetBigInteger(privateKey, signed: false, byteCount: PRIVATE_KEY_SIZE);

            keyBigInt  = Secp256k1Curve.EnforceLowS(keyBigInt);
            privateKey = BigIntegerConverter.GetBytes(keyBigInt, PRIVATE_KEY_SIZE);

            return(new EthereumEcdsaNative(privateKey, EthereumEcdsaKeyType.Private));
        }
Exemple #15
0
        public void Push(BigInteger obj, uint byteCount)
        {
            // Obtain the bytes for this BigInteger.
            byte[] data = BigIntegerConverter.GetBytes(obj);

            // If the byte count is larger than the data, something is wrong.
            if (byteCount > data.Length)
            {
                throw new ArgumentException("Tried to push a value onto the stack that was larger than 256-bit. This should not have happened.");
            }

            // Determine how many bytes we're going to zero out to keep our desired bytes only.
            int relevantBytesStart = data.Length - (int)byteCount;

            for (int i = 0; i < relevantBytesStart; i++)
            {
                data[i] = 0x00;
            }

            // Push this data.
            _internalStack.Add(data);
        }
Exemple #16
0
 public static Org.BouncyCastle.Math.BigInteger ToBouncyCastleBigInteger(this BigInteger bigInteger)
 {
     return(new Org.BouncyCastle.Math.BigInteger(1, BigIntegerConverter.GetBytes(bigInteger)));
 }
Exemple #17
0
        /// <summary>
        /// Creates an ECDSA instance by recovering a public key given a hash, recovery ID, and r and s components of the resulting signature of the hash. Throws an exception if recovery is not possible.
        /// </summary>
        /// <param name="hash">The hash of the data which was signed.</param>
        /// <param name="recoveryId">The recovery ID of ECDSA during signing.</param>
        /// <param name="ecdsa_r">The r component of the ECDSA signature for the provided hash.</param>
        /// <param name="ecdsa_s">The s component of the ECDSA signature for the provided hash.</param>
        /// <returns>Returns the quotient/public key which was used to sign this hash.</returns>
        public static new EthereumEcdsaNative Recover(Span <byte> hash, byte recoveryId, BigInteger ecdsa_r, BigInteger ecdsa_s)
        {
            // Source: http://www.secg.org/sec1-v2.pdf (Section 4.1.6 - Public Key Recovery Operation)

            // Recovery ID must be between 0 and 4 (0 and 1 is all that should be used, but we support multiple cases in case)
            if (recoveryId < 0 || recoveryId > 3)
            {
                throw new ArgumentException($"ECDSA public key recovery must have a v parameter between [0, 3]. Value provided is {recoveryId.ToString(CultureInfo.InvariantCulture)}");
            }

            // NOTES:
            // First bit of recoveryID being set means y is odd, otherwise it is even.
            // The second bit indicates which item of the two to choose.

            // If the hash is null, we'll assume it's a zero length byte array
            if (hash == null)
            {
                hash = Array.Empty <byte>();
            }


            using (AutoObjectPool <Secp256k1> .Get(out var secp256k1))
            {
                // Allocate memory for the signature and create a serialized-format signature to deserialize into our native format (platform dependent, hence why we do this).
                Span <byte> publicKeyOutput       = new byte[PUBLIC_KEY_SIZE];
                Span <byte> serializedSignature   = BigIntegerConverter.GetBytes(ecdsa_r).Concat(BigIntegerConverter.GetBytes(ecdsa_s));
                Span <byte> deserializedSignature = new byte[Secp256k1.UNSERIALIZED_SIGNATURE_SIZE];
                if (!secp256k1.RecoverableSignatureParseCompact(deserializedSignature, serializedSignature, recoveryId))
                {
                    var errMsg = "Unmanaged EC library failed to parse serialized signature. ";
                    if (IncludeKeyDataInExceptions)
                    {
                        errMsg += $"CompactSignature: {serializedSignature.ToHexString()}, RecoveryID: {recoveryId}";
                    }

                    throw new Exception(errMsg);
                }

                // Recovery from our deserialized signature.
                if (!secp256k1.Recover(publicKeyOutput, deserializedSignature, hash))
                {
                    var errMsg = "Unmanaged EC library failed to recover public key. ";
                    if (IncludeKeyDataInExceptions)
                    {
                        errMsg += $"Signature: {deserializedSignature.ToHexString()}, Message: {hash.ToHexString()}";
                    }

                    throw new Exception(errMsg);
                }

                // Serialize the public key
                Span <byte> serializedKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
                if (!secp256k1.PublicKeySerialize(serializedKey, publicKeyOutput))
                {
                    var errMsg = "Unmanaged EC library failed to serialize public key. ";
                    if (IncludeKeyDataInExceptions)
                    {
                        errMsg += $"PublicKey: {publicKeyOutput.ToHexString()}";
                    }

                    throw new Exception(errMsg);
                }

                // Slice off any prefix.
                serializedKey = serializedKey.Slice(serializedKey.Length - PUBLIC_KEY_SIZE);

                // Obtain our public key from this
                return(new EthereumEcdsaNative(serializedKey.ToArray(), EthereumEcdsaKeyType.Public));
            }
        }
Exemple #18
0
 /// <summary>
 /// Writes a 256-bit integer to virtual memory at the provided address.
 /// </summary>
 /// <param name="address">The address to write to.</param>
 /// <param name="bigInteger">The 256-bit integer to write.</param>
 public void Write(long address, BigInteger bigInteger)
 {
     Write(address, BigIntegerConverter.GetBytes(bigInteger));
 }
Exemple #19
0
        /// <summary>
        /// Obtains the parent private key if provided the parent public key. This key must be a private key.
        /// </summary>
        /// <param name="parentPublicKey">The public key of the parent of this extended key.</param>
        /// <returns>Returns the private key of the parent of this extended key.</returns>
        public ExtendedKey GetParentPrivateKey(ExtendedKey parentPublicKey)
        {
            // Verify this key is a private key
            if (KeyType != EthereumEcdsaKeyType.Private)
            {
                // This key is not a private key.
                throw new ArgumentNullException("Could not obtain parent private key. Can only obtain the parent private key of a private key. This key is a public key.");
            }
            else if (parentPublicKey == null)
            {
                // The public key is null.
                throw new ArgumentNullException("Could not obtain parent private key. Provided parent public key argument is null.");
            }
            else if (parentPublicKey.KeyType == EthereumEcdsaKeyType.Private)
            {
                // The public key was not a public key.
                throw new ArgumentException("Could not obtain parent private key. Provided parent public key argument is not a public key.");
            }
            else if (Hardened)
            {
                throw new ArgumentException("Could not obtain parent private key if this key is a hardened key.");
            }
            else if (Depth == 0)
            {
                throw new ArgumentException("Could not obtain parent private key for this key because this key is a top level key.");
            }
            else if (!parentPublicKey.IsChild(this))
            {
                // The provided parent public key is not a parent.
                throw new ArgumentException("Could not obtain parent private key for this key because the provided parent public key argument is not a parent to this key.");
            }

            // Obtain the hash used to derive this current key, from the parent.
            byte[] hash = parentPublicKey.ComputeChildHash(ChildIndex, parentPublicKey.InternalKey.ToPublicKeyArray(true, false));

            // Set the child key data as the first 32 bytes of "hash"
            byte[] childKeyData = new byte[EthereumEcdsa.PRIVATE_KEY_SIZE];
            Array.Copy(hash, 0, childKeyData, 0, childKeyData.Length);

            // Initialize the child chain code
            byte[] childChainCode = new byte[CHAIN_CODE_SIZE];

            // We derive the child chain code as the data immediately following key data.
            Array.Copy(hash, 32, childChainCode, 0, childChainCode.Length);

            // Verify the chain code is equal
            if (!ChainCode.SequenceEqual(childChainCode))
            {
                throw new ArgumentException("Derived chain code from the parent at this key's child index that did not match this key's chain code.");
            }

            // Convert the key data to an integer
            BigInteger childKeyInt = BigIntegerConverter.GetBigInteger(childKeyData, false, childChainCode.Length);

            // Convert this private key to an integer
            byte[]     thisKeyData = InternalKey.ToPrivateKeyArray();
            BigInteger thisKeyInt  = BigIntegerConverter.GetBigInteger(thisKeyData, false, thisKeyData.Length);

            // Compute our parent key
            BigInteger parentPrivateKeyInt = ((thisKeyInt - childKeyInt) + Secp256k1Curve.N) % Secp256k1Curve.N;

            // Obtain our new key from this
            byte[] computedParentKeyData = BigIntegerConverter.GetBytes(parentPrivateKeyInt, EthereumEcdsa.PRIVATE_KEY_SIZE);

            // Obtain the parent private key
            EthereumEcdsa parentPrivateKey = EthereumEcdsa.Create(computedParentKeyData, EthereumEcdsaKeyType.Private);

            // Create the parent extended private key
            return(new ExtendedKey(parentPrivateKey, parentPublicKey.ChainCode, parentPublicKey.Depth, parentPublicKey.ChildIndex, parentPublicKey.Fingerprint));
        }
Exemple #20
0
        public void SigningTest()
        {
            using (var secp256k1 = new Secp256k1())
            {
                Span <byte> signature   = new byte[Secp256k1.UNSERIALIZED_SIGNATURE_SIZE];
                Span <byte> messageHash = new byte[] { 0xc9, 0xf1, 0xc7, 0x66, 0x85, 0x84, 0x5e, 0xa8, 0x1c, 0xac, 0x99, 0x25, 0xa7, 0x56, 0x58, 0x87, 0xb7, 0x77, 0x1b, 0x34, 0xb3, 0x5e, 0x64, 0x1c, 0xca, 0x85, 0xdb, 0x9f, 0xef, 0xd0, 0xe7, 0x1f };
                Span <byte> secretKey   = "e815acba8fcf085a0b4141060c13b8017a08da37f2eb1d6a5416adbb621560ef".HexToBytes();

                bool result = secp256k1.SignRecoverable(signature, messageHash, secretKey);
                Assert.True(result);

                // Recover the public key
                Span <byte> publicKeyOutput = new byte[Secp256k1.PUBKEY_LENGTH];
                result = secp256k1.Recover(publicKeyOutput, signature, messageHash);
                Assert.True(result);

                // Serialize the public key
                Span <byte> serializedKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
                result = secp256k1.PublicKeySerialize(serializedKey, publicKeyOutput);
                Assert.True(result);

                // Slice off any prefix.
                serializedKey = serializedKey.Slice(serializedKey.Length - Secp256k1.PUBKEY_LENGTH);

                Assert.Equal("0x3a2361270fb1bdd220a2fa0f187cc6f85079043a56fb6a968dfad7d7032b07b01213e80ecd4fb41f1500f94698b1117bc9f3335bde5efbb1330271afc6e85e92", serializedKey.ToHexString(true), true);

                // Verify we could obtain the correct sender from the signature.
                Span <byte> senderAddress = KeccakHash.ComputeHash(serializedKey).Slice(KeccakHash.HASH_SIZE - Address.ADDRESS_SIZE);
                Assert.Equal("0x75c8aa4b12bc52c1f1860bc4e8af981d6542cccd", senderAddress.ToArray().ToHexString(true), true);

                // Verify it works with variables generated from our managed code.
                BigInteger ecdsa_r    = BigInteger.Parse("68932463183462156574914988273446447389145511361487771160486080715355143414637", CultureInfo.InvariantCulture);
                BigInteger ecdsa_s    = BigInteger.Parse("47416572686988136438359045243120473513988610648720291068939984598262749281683", CultureInfo.InvariantCulture);
                byte       recoveryId = 1;

                byte[] ecdsa_r_bytes = BigIntegerConverter.GetBytes(ecdsa_r);
                byte[] ecdsa_s_bytes = BigIntegerConverter.GetBytes(ecdsa_s);
                signature = ecdsa_r_bytes.Concat(ecdsa_s_bytes);

                // Allocate memory for the signature and create a serialized-format signature to deserialize into our native format (platform dependent, hence why we do this).
                Span <byte> serializedSignature = ecdsa_r_bytes.Concat(ecdsa_s_bytes);
                signature = new byte[Secp256k1.UNSERIALIZED_SIGNATURE_SIZE];
                result    = secp256k1.RecoverableSignatureParseCompact(signature, serializedSignature, recoveryId);
                if (!result)
                {
                    throw new Exception("Unmanaged EC library failed to parse serialized signature.");
                }

                // Recover the public key
                publicKeyOutput = new byte[Secp256k1.PUBKEY_LENGTH];
                result          = secp256k1.Recover(publicKeyOutput, signature, messageHash);
                Assert.True(result);


                // Serialize the public key
                serializedKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
                result        = secp256k1.PublicKeySerialize(serializedKey, publicKeyOutput);
                Assert.True(result);

                // Slice off any prefix.
                serializedKey = serializedKey.Slice(serializedKey.Length - Secp256k1.PUBKEY_LENGTH);

                // Assert our key
                Assert.Equal("0x3a2361270fb1bdd220a2fa0f187cc6f85079043a56fb6a968dfad7d7032b07b01213e80ecd4fb41f1500f94698b1117bc9f3335bde5efbb1330271afc6e85e92", serializedKey.ToHexString(true), true);

                //senderAddress = EthereumEcdsa.Recover(messageHash.ToArray(), recoveryId, ecdsa_r, ecdsa_s).GetPublicKeyHash();
                //senderAddress = senderAddress.Slice(KeccakHash.HASH_SIZE - Address.ADDRESS_SIZE);
                //Assert.Equal("0x75c8aa4b12bc52c1f1860bc4e8af981d6542cccd", senderAddress.ToArray().ToHexString(true), true);
            }
        }
        private static EVMExecutionResult Precompile_ECPairing(MeadowEVM evm)
        {
            // Verify we're past the byzantium fork
            if (evm.Version < EthereumRelease.Byzantium)
            {
                return(new EVMExecutionResult(evm, null, true));
            }

            const int PAIRING_SIZE_PER_POINT = 192;

            // Verify our messatge data is divisible by our size per point.
            if (evm.Message.Data.Length % PAIRING_SIZE_PER_POINT != 0)
            {
                throw new EVMException($"ECPairing precompile failed because the call data was not divisible by the size per point ({PAIRING_SIZE_PER_POINT}).");
            }

            // Charge the gas for the precompile operation before processing.
            BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_ECPAIRING_BASE + ((evm.Message.Data.Length / PAIRING_SIZE_PER_POINT) * GasDefinitions.GAS_PRECOMPILE_ECPAIRING_PER_POINT);

            evm.GasState.Deduct(gasCharge);

            // Obtain a memory representation of our data.
            Span <byte> messageData = new Span <byte>(evm.Message.Data);

            // Define some constant variables for arithmetic.
            FpVector3 <Fp2> zero     = new FpVector3 <Fp2>(Fp2.OneValue, Fp2.OneValue, Fp2.ZeroValue);
            Fp12            exponent = Fp12.OneValue;

            // Loop for each point in our data
            for (int i = 0; i < evm.Message.Data.Length; i += PAIRING_SIZE_PER_POINT)
            {
                // Obtain our component data
                BigInteger x1   = BigIntegerConverter.GetBigInteger(messageData.Slice(i + 0, EVMDefinitions.WORD_SIZE));
                BigInteger y1   = BigIntegerConverter.GetBigInteger(messageData.Slice(i + 32, EVMDefinitions.WORD_SIZE));
                BigInteger x2_i = BigIntegerConverter.GetBigInteger(messageData.Slice(i + 64, EVMDefinitions.WORD_SIZE));
                BigInteger x2_r = BigIntegerConverter.GetBigInteger(messageData.Slice(i + 96, EVMDefinitions.WORD_SIZE));
                BigInteger y2_i = BigIntegerConverter.GetBigInteger(messageData.Slice(i + 128, EVMDefinitions.WORD_SIZE));
                BigInteger y2_r = BigIntegerConverter.GetBigInteger(messageData.Slice(i + 160, EVMDefinitions.WORD_SIZE));

                // Parse and verify our point.
                FpVector3 <Fp> point1 = ParsePoint(x1, y1);
                if (point1 == null)
                {
                    throw new EVMException("ECPairing precompile failed because point 1 was deemed invalid when parsing.");
                }

                // If our coordinates exceed our modulo divisor, they are invalid.
                if (x2_i >= Bn128Curve.P || x2_r >= Bn128Curve.P || y2_i >= Bn128Curve.P || y2_r >= Bn128Curve.P)
                {
                    throw new EVMException("ECPairing precompile failed because point 2 was deemed invalid when parsing.");
                }

                Fp2             x2     = new Fp2(x2_r, x2_i);
                Fp2             y2     = new Fp2(y2_r, y2_i);
                FpVector3 <Fp2> point2 = null;
                if (x2 == Fp2.ZeroValue && y2 == Fp2.ZeroValue)
                {
                    // Our point is the zero point.
                    point2 = zero;
                }
                else
                {
                    // Initialize our point from components.
                    point2 = new FpVector3 <Fp2>(x2, y2, Fp2.OneValue);

                    // Verify our desired point is on the curve
                    if (!point2.IsOnCurveCheck(Bn128Curve.B2))
                    {
                        throw new EVMException("ECPairing precompile failed because point 2 was not on the curve.");
                    }
                }

                // Verify multiplying by the curve order is non-zero.
                if (point2.Multiply(Bn128Curve.N).Z != Fp2.ZeroValue)
                {
                    throw new EVMException("ECPairing precompile failed because point 2 was deemed invalid. Points multiplied by the curve order should equal infinity (zero).");
                }

                // Pair our points and multiply the exponent by them.
                exponent *= Bn128Pairing.Pair(point2, point1, false);
            }

            // Return our result
            bool returnStatus = Bn128Pairing.FinalExponentiate(exponent) == Fp12.OneValue;

            byte[] returnData = BigIntegerConverter.GetBytes(returnStatus ? 1 : 0, EVMDefinitions.WORD_SIZE);
            return(new EVMExecutionResult(evm, returnData, true));
        }
Exemple #22
0
        /// <summary>
        /// Creates authentication data to send to the responder.
        /// </summary>
        /// <param name="receiverPublicKey">The responder/receiver's public key.</param>
        /// <param name="nonce">The nonce to use for the authentication data. If null, new data is generated.</param>
        /// <returns>Returns the encrypted serialized authentication data.</returns>
        public byte[] CreateAuthentiation(EthereumEcdsa receiverPublicKey, byte[] nonce = null)
        {
            // Verify this is the initiator role.
            if (Role != RLPxSessionRole.Initiator)
            {
                throw new Exception("RLPx auth data should only be created by the initiator.");
            }

            // Verify the session state is correct.
            if (SessionState != RLPxSessionState.Initial)
            {
                throw new Exception("RLPx auth creation should only be performed on a new session.");
            }

            // If the nonce is null, generate a new one.
            nonce = nonce ?? GenerateNonce();

            // Set our initiator nonce
            InitiatorNonce = nonce;

            // Set the remote public key
            RemotePublicKey = receiverPublicKey;

            // Create a new authentication message based off of our configured setting.
            RLPxAuthBase authMessage = null;

            if (UsingEIP8Authentication)
            {
                // Create our EIP8 authentication message.
                authMessage = new RLPxAuthEIP8()
                {
                    Nonce   = InitiatorNonce,
                    Version = MAX_SUPPORTED_VERSION,
                };
            }
            else
            {
                // Create our standard authentication message.
                authMessage = new RLPxAuthStandard()
                {
                    Nonce = InitiatorNonce,
                };
            }

            // Sign the authentication message
            authMessage.Sign(LocalPrivateKey, LocalEphemeralPrivateKey, RemotePublicKey, ChainId);

            // Serialize the authentication data
            byte[] serializedData = authMessage.Serialize();

            // Encrypt the data accordingly (standard uses no shared mac data, EIP8 has 2 bytes which prefix the resulting encrypted data).
            if (UsingEIP8Authentication)
            {
                // Obtain two bytes of mac data by EIP8 standards (big endian 16-bit unsigned integer equal to the size of the resulting ECIES encrypted data).
                // We can calculate this as the amount of overhead data ECIES adds is static in size.
                byte[] sharedMacData = BigIntegerConverter.GetBytes(serializedData.Length + Ecies.ECIES_ADDITIONAL_OVERHEAD, 2);

                // Encrypt the serialized data with the shared mac data, and prefix the result with it.
                byte[] encryptedSerializedData = Ecies.Encrypt(RemotePublicKey, serializedData, sharedMacData);
                AuthData = sharedMacData.Concat(encryptedSerializedData);
            }
            else
            {
                // Encrypt it using ECIES without any shared mac data.
                AuthData = Ecies.Encrypt(RemotePublicKey, serializedData, null);
            }

            // Set the session state
            SessionState = RLPxSessionState.AuthenticationCompleted;

            // Return the auth data
            return(AuthData);
        }
Exemple #23
0
 /// <summary>
 /// Obtains a string representation of our instruction
 /// </summary>
 /// <returns>Returns a string representation of our instruction.</returns>
 public override string ToString()
 {
     return($"{Opcode} 0x{BigIntegerConverter.GetBytes(PushData, (int)PushSize).ToHexString()}");
 }
Exemple #24
0
 public byte[] ToByteArray()
 {
     // Obtain the amount of bytes that constitute an address from the least significant bit side.
     return(BigIntegerConverter.GetBytes(_internalAddress, ADDRESS_SIZE));
 }
Exemple #25
0
        private static EVMExecutionResult Precompile_ModExp(MeadowEVM evm)
        {
            // Verify we're past the byzantium fork
            if (evm.Version < EthereumRelease.Byzantium)
            {
                return(new EVMExecutionResult(evm, null, true));
            }

            // Source: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-198.md

            // Obtain a memory representation of our data.
            Span <byte> messageData = new Memory <byte>(evm.Message.Data).Span;

            // Extract our base length, exponent length, and mod length (in bytes)
            BigInteger baseLength     = BigIntegerConverter.GetBigInteger(messageData.Slice(0, EVMDefinitions.WORD_SIZE));
            BigInteger exponentLength = BigIntegerConverter.GetBigInteger(messageData.Slice(32, EVMDefinitions.WORD_SIZE));
            BigInteger modLength      = BigIntegerConverter.GetBigInteger(messageData.Slice(64, EVMDefinitions.WORD_SIZE));

            // GAS CALCULATION START: Exponent is leading the word of data, so we obtain a numeric representation of the first bytes.
            BigInteger exponentHead = BigIntegerConverter.GetBigInteger(messageData.Slice(96 + (int)baseLength, EVMDefinitions.WORD_SIZE));

            // Shift our head so we only have relevant bytes (they're leading the word, so we want to cut the tail off by bitshifting).
            exponentHead >>= (8 * (int)BigInteger.Max(32 - exponentLength, 0));

            // Count our bits in our exponent head.
            int exponentHeadBitCount = -1;

            while (exponentHead > 0)
            {
                exponentHead >>= 1;
                exponentHeadBitCount++;
            }

            // Obtain our adjusted exponent length.
            // 1) If exponent length <= 32, and exponent bits are 0, this is 0.
            // 2) If exponent length <= 32, then return the index of the highest bit in exponent.
            // 3) If exponent length > 32, then we return (8 * (exponent-length - 32)) + the index of the highest bit in the exponent.
            BigInteger adjustedExponentLength = Math.Max(exponentHeadBitCount, 0) + (8 * BigInteger.Max(exponentLength - 32, 0));

            adjustedExponentLength = BigInteger.Max(adjustedExponentLength, 1);

            // GAS CALCULATION END: Calculate the final gas cost from the length of our biggest parameter, times the exponent length, divided by our divisor.
            BigInteger biggestLength = BigInteger.Max(modLength, baseLength);
            BigInteger gasCost       = (Estimate_karatsuba_difficulty(biggestLength) * adjustedExponentLength) / GasDefinitions.GAS_PRECOMPILE_MODEXP_QUAD_DIVISOR;

            // Deduct our gas cost.
            evm.GasState.Deduct(gasCost);

            // Verify our base length.
            if (baseLength == 0)
            {
                return(new EVMExecutionResult(evm, new byte[(int)modLength], true));
            }

            // Verify our mod length.
            if (modLength == 0)
            {
                return(new EVMExecutionResult(evm, null, true));
            }

            // Obtain our base, exponent and mod
            Span <byte> memBase     = messageData.Slice(96, (int)baseLength);
            BigInteger  numBase     = BigIntegerConverter.GetBigInteger(memBase, false, memBase.Length);
            Span <byte> memExponent = messageData.Slice(96 + (int)baseLength, (int)exponentLength);
            BigInteger  numExponent = BigIntegerConverter.GetBigInteger(memExponent, false, memExponent.Length);
            Span <byte> memMod      = messageData.Slice(96 + (int)baseLength + (int)exponentLength, (int)modLength);
            BigInteger  numMod      = BigIntegerConverter.GetBigInteger(memMod, false, memMod.Length);

            // Verify our divisor isn't 0.
            if (numMod == 0)
            {
                return(new EVMExecutionResult(evm, new byte[(int)modLength], true));
            }

            // Obtain our modexp result, which, by definition, we know won't be bigger than our divisor, so we bind our length to the modulo divisor length.
            BigInteger numResult = BigInteger.ModPow(numBase, numExponent, numMod);

            byte[] result = BigIntegerConverter.GetBytes(numResult, (int)modLength);

            // Return our result
            return(new EVMExecutionResult(evm, result, true));
        }
Exemple #26
0
        /// <summary>
        /// Computes the child key and child chain code for a given child key/index relative from this extended key.
        /// </summary>
        /// <param name="index">The child key/index to derive a key/chain code for.</param>
        /// <returns>Returns a key and chain code for a child relative from this extended key. Derives a key of the same type as this key.</returns>
        private (EthereumEcdsa childKey, byte[] childChainCode) GetChildKeyInternal(uint index)
        {
            // Declare a hash we will obtain of our key.
            byte[] hash = null;

            // If this is a hardened directory/key/index
            if (KeyPath.CheckHardenedDirectoryIndex(index))
            {
                // Verify we aren't trying to derive a hardened key from a public key (since private is required).
                if (KeyType == EthereumEcdsaKeyType.Public)
                {
                    // Throw an exception because hardened keys mean we need the private key, but this is the public key.
                    throw new ArgumentException("Hierarchically deterministic child key cannot be derived from a public key when the child key index is hardened. Hardened keys can only be derived when the private key is known.");
                }

                // Obtain the message to hash. (0x00 byte prefixing the private key to pad it to 33 bytes long).
                byte[] hashMessage = new byte[] { 0 }.Concat(InternalKey.ToPrivateKeyArray());

                // Next we hash our key data.
                hash = ComputeChildHash(index, hashMessage);
            }
            else
            {
                // Compute the hash on our public key and index.
                hash = ComputeChildHash(index, InternalKey.ToPublicKeyArray(true, false));
            }

            // Set the child key data as the first 32 bytes of "hash"
            byte[] childKeyData = new byte[EthereumEcdsa.PRIVATE_KEY_SIZE];
            Array.Copy(hash, 0, childKeyData, 0, childKeyData.Length);

            // Initialize the child chain code
            byte[] childChainCode = new byte[CHAIN_CODE_SIZE];

            // We derive the child chain code as the data immediately following key data.
            Array.Copy(hash, 32, childChainCode, 0, childChainCode.Length);

            // Convert the key data to an integer
            BigInteger childKeyInt = BigIntegerConverter.GetBigInteger(childKeyData, false, childChainCode.Length);

            // If the child key is above N
            if (childKeyInt >= Secp256k1Curve.N)
            {
                throw new ArgumentException("Calculated child key value cannot exceed or equal N on the secp256k1 curve. Hierarchically deterministic child key cannot derive here. Try again.");
            }

            // Define our resulting key to obtain
            EthereumEcdsa childKey = null;

            // Obtain our child key depending on type.;
            if (KeyType == EthereumEcdsaKeyType.Public)
            {
                // Obtain our public key and add it to G * childKey
                var q = Secp256k1Curve.Parameters.Curve.DecodePoint(InternalKey.ToPublicKeyArray(true, false));
                q = Secp256k1Curve.Parameters.G.Multiply(childKeyInt.ToBouncyCastleBigInteger()).Add(q);
                if (q.IsInfinity)
                {
                    throw new ArgumentException("Calculated child key value point is infinity. This is a very rare occurrence. Hierarchically deterministic child key cannot derive here.");
                }

                // Normalize our point.
                q = q.Normalize();


                var p       = Secp256k1Curve.DomainParameters.Curve.CreatePoint(q.XCoord.ToBigInteger(), q.YCoord.ToBigInteger());
                var encoded = p.GetEncoded(compressed: true);
                // Derive our child data.
                childKey = EthereumEcdsa.Create(encoded, EthereumEcdsaKeyType.Public);
            }
            else
            {
                // Add our private key to our parsed new key, mod N, to derive our new key.
                BigInteger computedChildKeyInt = (BigIntegerConverter.GetBigInteger(InternalKey.ToPrivateKeyArray()) + childKeyInt) % Secp256k1Curve.N;

                // Verify our computed child key is non-zero
                if (computedChildKeyInt == 0)
                {
                    throw new ArgumentException("Calculated child private key is zero. This is a very rare occurrence. Hierarchically deterministic child key cannot derive here.");
                }

                // Obtain our new key from this
                byte[] computedChildKeyData = BigIntegerConverter.GetBytes(computedChildKeyInt, EthereumEcdsa.PRIVATE_KEY_SIZE);

                // Initialize our key
                childKey = EthereumEcdsa.Create(computedChildKeyData, EthereumEcdsaKeyType.Private);
            }

            // Return our obtained data.
            return(childKey, childChainCode);
        }
Exemple #27
0
        static async Task Main(string[] args)
        {
            Console.WriteLine("Starting...");

            int  port;
            bool meadow = true;

            if (!meadow)
            {
                port = 7545;
            }
            else
            {
                // Bootstrap our meadow test node server.
                var testNode = new Meadow.TestNode.TestNodeServer();

                // Print our undefined rpc methods.
                var undefinedRpcMethods = testNode.GetUndefinedRpcMethods();
                Console.WriteLine("Warning: following RPC methods are not defined: \n" + string.Join(", ", undefinedRpcMethods.Select(r => r.Value())));

                // Start up the server and obtain the port.
                await testNode.RpcServer.StartAsync();

                port = testNode.RpcServer.ServerPort;
            }

            async Task <Exception> GetExecutionTraceException(IJsonRpcClient rpcClient, JsonRpcError error)
            {
                if (meadow)
                {
                    var executionTrace = await rpcClient.GetExecutionTrace();

                    var traceAnalysis = new ExecutionTraceAnalysis(executionTrace);

                    // Build our aggregate exception
                    var aggregateException = traceAnalysis.GetAggregateException(error.ToException());
                    return(aggregateException);
                }
                else
                {
                    if (error != null)
                    {
                        throw error.ToException();
                    }
                    else
                    {
                        throw new Exception("Execution exception");
                    }
                }
            }

            // Connect our client to the server.
            var client = JsonRpcClient.Create(
                new Uri($"http://{IPAddress.Loopback}:{port}"),
                defaultGasLimit: 6_000_000,
                defaultGasPrice: 0);

            client.ErrorFormatter = GetExecutionTraceException;

            // If we're testing meadow, we enable special coverage/tracing options.
            if (meadow)
            {
                await client.SetCoverageEnabled(true);

                await client.SetTracingEnabled(true);
            }

            //var missingConstructorContract = await MissingConstructorChild.New(client);
            //var someNum = await missingConstructorContract.someNum().Call();
            #region ErrorContract
            // Try deploying the error generating contract and test some calls.
            var errorContract = await ErrorContract.New(client, new TransactionParams { Gas = 4712388 });

            //await errorContract.doRevert().ExpectRevertTransaction();
            //await errorContract.doAssert().ExpectRevertTransaction();
            //await errorContract.doThrow().ExpectRevertCall();
            #endregion

            #region Inheritance Tests
            // Test inheritance with an inherited contract.
            var inheritedContract = await InheritedContract.New(client, new TransactionParams { Gas = 4712388 });

            await inheritedContract.testFunction();

            await inheritedContract.testFunctionWithInheritedModifier();

            // Test inheritance with a seperate file which we inherited from.
            var multiInheritedContract = await MultifileInheritedContract.New(client, new TransactionParams { Gas = 4712388 });

            await multiInheritedContract.testFunction();

            await multiInheritedContract.testFunctionWithInheritedModifier();

            #endregion

            try
            {
                await FailDeploymentContract.New(client);
            }
            catch { }

            #region Callstack Tests
            // Try throwing asserts in further call depth and spanning more than one file.
            await multiInheritedContract.testInheritedAssertThrow().ExpectRevertTransaction();

            if (meadow)
            {
                // Test parsing an execution trace of the last call/transaction.
                var executionTrace = await client.GetExecutionTrace();

                ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace);

                // Testing: Build our aggregate exception
                var aggregateException = traceAnalysis.GetAggregateException();
                try
                {
                    throw aggregateException;
                }
                catch { }
            }
            #endregion

            #region ExampleContract Tests
            // Deploy our main example contract
            var exContract = await ExampleContract.New($"TestName", true, 34, client, new TransactionParams { Gas = 4712388 });

            await exContract.testRevert().ExpectRevertTransaction();

            await exContract.testBranchCoverage().ExpectRevertTransaction();

            if (meadow)
            {
                // Test parsing an execution trace of the last call/transaction.
                var executionTrace = await client.GetExecutionTrace();

                ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace);

                // Testing: Build our aggregate exception
                var aggregateException = traceAnalysis.GetAggregateException();
                try
                {
                    throw aggregateException;
                }
                catch { }
            }

            // Test the modexp precompile.
            var modExpTestBytes = await exContract.testModExp(
                BigIntegerConverter.GetBytes(BigInteger.Parse("1212121323543453245345678346345737475734753745737774573475377734577", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("3", CultureInfo.InvariantCulture)),
                BigIntegerConverter.GetBytes(BigInteger.Parse("4345328123928357434573234217343477", CultureInfo.InvariantCulture)))
                                  .Call();

            var modExpTest = BigIntegerConverter.GetBigInteger(modExpTestBytes, false, modExpTestBytes.Length);
            // should be 856753145937825219130387866259147

            // Test events
            var eventTest = await exContract.emitDataEvent(1, 2, 3).TransactionReceipt();

            var eventLogFirst = eventTest.FirstEventLog <ExampleContract.DataEvent>();
            var eventLogLast  = eventTest.LastEventLog <ExampleContract.DataEvent>();
            var eventLogAll   = eventTest.EventLogs <ExampleContract.DataEvent>();
            var eventLogsBase = eventTest.EventLogs();

            // Test for chris
            var result = await exContract.getFirstByteFromByte32(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }).Call();

            // Try testing branch coverage (which ends in an assert being thrown)
            await exContract.testBranchCoverage().ExpectRevertTransaction();

            //await exContract.noopFunc();
            var echoGasEst = await exContract.echoInt24(34).EstimateGas();

            await exContract.testInstructions1().TransactionReceipt();

            var transactionReceipt = await exContract.echoInt24(22).TransactionReceipt();

            #endregion

            #region Performance Tests
            // Define start time for an execution loop to test performance of a few basic calls.
            DateTime start     = DateTime.Now;
            DateTime iteration = start;

            // Note: Change the loop condition here as needed.
            for (int i = 0; i < 1; i++)
            {
                var addr = await exContract.echoAddress(new Address(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }));

                var int24Test = await exContract.echoInt24(7777);

                var stringTest = await exContract.echoString("This is a string.");

                var enabledThingTest = await exContract.enabledThing();

                var isNineTest = await exContract.myFunc(9);

                var givenName = await exContract.givenName();

                // Precompile hash tests
                var sha256HashTest = await exContract.sha256str("hello world");       // should be 0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

                var ripemd160HashTest = await exContract.ripemd160str("hello world"); // should be 0x98c615784ccb5fe5936fbc0cbe9dfdb408d92f0f

                // This ECRecover test should yield 0x75c8aa4b12bc52c1f1860bc4e8af981d6542cccd. This test data is taken from SigningTests.cs
                var ecRecoverTest = await exContract.testECRecover(
                    new byte[] { 0xc9, 0xf1, 0xc7, 0x66, 0x85, 0x84, 0x5e, 0xa8, 0x1c, 0xac, 0x99, 0x25, 0xa7, 0x56, 0x58, 0x87, 0xb7, 0x77, 0x1b, 0x34, 0xb3, 0x5e, 0x64, 0x1c, 0xca, 0x85, 0xdb, 0x9f, 0xef, 0xd0, 0xe7, 0x1f },
                    0x1c,
                    BigIntegerConverter.GetBytes(BigInteger.Parse("68932463183462156574914988273446447389145511361487771160486080715355143414637", CultureInfo.InvariantCulture)),
                    BigIntegerConverter.GetBytes(BigInteger.Parse("47416572686988136438359045243120473513988610648720291068939984598262749281683", CultureInfo.InvariantCulture)));

                Console.WriteLine($"#{i}: {DateTime.Now - iteration}");
                iteration = DateTime.Now;
            }

            DateTime end = DateTime.Now;
            #endregion

            // If this is meadow, we do special post-execution tasks.
            if (meadow)
            {
                // Test obtaining coverage maps, disabling them, clearing them.
                var coverageMaps = await client.GetAllCoverageMaps();

                await client.SetCoverageEnabled(false);

                await client.ClearCoverage();

                // Obtain our generated solc data, create a report, and open it.
                var solcData = GeneratedSolcData.Default.GetSolcData();

                // Match coverage contract addresses with deployed contracts that the client keeps track of.
                var contractInstances = GeneratedSolcData.Default.MatchCoverageData(coverageMaps);

                var reportPath = Path.GetFullPath("Report");
                MiscUtil.ResetDirectory(reportPath);
                ReportGenerator.CreateReport(GeneratedSolcData.Default.SolidityCompilerVersion, contractInstances, solcData.SolcSourceInfo, solcData.SolcBytecodeInfo, null, null, reportPath);
                MiscUtil.OpenBrowser(Path.Join(reportPath, ReportGenerator.REPORT_INDEX_FILE));
            }

            // Output our execution loop time.
            Console.WriteLine($"Total Time: {end - start}");
            Console.ReadLine();
        }
Exemple #28
0
        /// <summary>
        /// Creates authentication acknowledgement data to send to the initiator, signalling that their authentication
        /// data was successfully verified, and providing the initiator with information that they have already provided
        /// to the responder (so they can both derive the same shared secrets).
        /// </summary>
        /// <param name="nonce">The nonce to use for the authentication data. If null, new data is generated.</param>
        /// <returns>Returns the encrypted serialized authentication acknowledgement data.</returns>
        public byte[] CreateAuthenticationAcknowledgement(byte[] nonce = null)
        {
            // Verify this is the responder role.
            if (Role != RLPxSessionRole.Responder)
            {
                throw new Exception("RLPx auth-ack data should only be created by the responder.");
            }

            // Verify the session state is correct.
            if (SessionState != RLPxSessionState.AuthenticationCompleted)
            {
                throw new Exception("RLPx auth-ack creation should only be performed on a session after auth was received/verified.");
            }

            // If the nonce is null, generate a new one.
            if (nonce == null)
            {
                nonce = new byte[NONCE_SIZE];
                _randomNumberGenerator.GetBytes(nonce);
            }

            // Set the responder nonce
            ResponderNonce = nonce ?? GenerateNonce();

            // If we are using EIP8
            RLPxAuthAckBase authAckMessage = null;

            if (UsingEIP8Authentication)
            {
                // We use EIP8 authentication acknowledgement
                authAckMessage = new RLPxAuthAckEIP8()
                {
                    EphemeralPublicKey = LocalEphemeralPrivateKey.ToPublicKeyArray(false, true),
                    Nonce   = ResponderNonce,
                    Version = MAX_SUPPORTED_VERSION,
                };
            }
            else
            {
                // We use standard authentication acknowledgement
                authAckMessage = new RLPxAuthAckStandard()
                {
                    EphemeralPublicKey = LocalEphemeralPrivateKey.ToPublicKeyArray(false, true),
                    Nonce      = ResponderNonce,
                    TokenFound = false, // TODO: Check for a saved session key from before, and set this accordingly.
                };
            }

            // Serialize the authentication-acknowledgement data
            byte[] serializedData = authAckMessage.Serialize();

            // Encrypt the data accordingly (standard uses no shared mac data, EIP8 has 2 bytes which prefix the resulting encrypted data).
            if (UsingEIP8Authentication)
            {
                // Obtain two bytes of mac data by EIP8 standards (big endian 16-bit unsigned integer equal to the size of the resulting ECIES encrypted data).
                // We can calculate this as the amount of overhead data ECIES adds is static in size.
                byte[] sharedMacData = BigIntegerConverter.GetBytes(serializedData.Length + Ecies.ECIES_ADDITIONAL_OVERHEAD, 2);

                // Encrypt the serialized data with the shared mac data, prefix the result with it.
                byte[] encryptedSerializedData = Ecies.Encrypt(RemotePublicKey, serializedData, sharedMacData);
                AuthAckData = sharedMacData.Concat(encryptedSerializedData);
            }
            else
            {
                // Encrypt it using ECIES without any shared mac data.
                AuthAckData = Ecies.Encrypt(RemotePublicKey, serializedData, null);
            }

            // Set the session state
            SessionState = RLPxSessionState.AcknowledgementCompleted;

            // Return the auth-ack data
            return(AuthAckData);
        }