コード例 #1
0
ファイル: InstructionBlockHash.cs プロジェクト: zutobg/Meadow
        public override void Execute()
        {
            // Obtain the current block number, and the block number for the block we want the hash for.
            BigInteger currentBlockNumber  = EVM.State.CurrentBlock.Header.BlockNumber;
            BigInteger targetBlockNumber   = Stack.Pop();
            BigInteger previousHeaderIndex = currentBlockNumber - targetBlockNumber - 1;

            // We only cache a finite amount of block headers, currently this is 256.
            // NOTE: Although it's defined in our configuration, we hard code it here as some official Ethereum implementations do,
            // instead of being dependent on configuration. This way, if it were to change with a fork, we still remain backward compatible here
            // and can simply just add a case.
            if (previousHeaderIndex < 0 || previousHeaderIndex > 255)
            {
                // We couldn't obtain the block hash, we return zero.
                Stack.Push(0);
            }
            else
            {
                // Obtain the hash of this previous block and push it.
                Stack.Push(BigIntegerConverter.GetBigInteger(EVM.State.PreviousHeaders[(int)previousHeaderIndex].GetHash()));

                // Verify there was not some error with block numbers mismatches on the previous header we obtained.
                if (targetBlockNumber != EVM.State.PreviousHeaders[(int)previousHeaderIndex].BlockNumber)
                {
                    throw new Exception($"BlockNumber mismatch when performing a {Opcode.ToString()} instruction in the EVM!");
                }
            }
        }
コード例 #2
0
        public override void Execute()
        {
            // Obtain our offset into call data we want to start copying at.
            BigInteger offset = Stack.Pop();

            // Read our data (if our offset is wrong or we hit the end of the array, the rest should be zeroes).
            byte[] data   = new byte[EVMDefinitions.WORD_SIZE];
            int    length = data.Length;

            if (offset > Message.Data.Length)
            {
                offset = 0;
                length = 0;
            }
            else if (offset + length > Message.Data.Length)
            {
                length = Message.Data.Length - (int)offset;
            }

            // Copy however much data we were able to out of our 32-byte desired count.
            Array.Copy(Message.Data, (int)offset, data, 0, length);

            // Convert it to a big integer and push it.
            Stack.Push(BigIntegerConverter.GetBigInteger(data));
        }
コード例 #3
0
 static Converter()
 {
     BoolConverter.Initialize();
     CharConverter.Initialize();
     ByteConverter.Initialize();
     SByteConverter.Initialize();
     Int16Converter.Initialize();
     UInt16Converter.Initialize();
     Int32Converter.Initialize();
     UInt32Converter.Initialize();
     Int64Converter.Initialize();
     UInt64Converter.Initialize();
     SingleConverter.Initialize();
     DoubleConverter.Initialize();
     DecimalConverter.Initialize();
     BigIntegerConverter.Initialize();
     BytesConverter.Initialize();
     CharsConverter.Initialize();
     StringConverter.Initialize();
     StringBuilderConverter.Initialize();
     DateTimeConverter.Initialize();
     TimeSpanConverter.Initialize();
     GuidConverter.Initialize();
     MemoryStreamConverter.Initialize();
     StreamConverter.Initialize();
 }
コード例 #4
0
        public override object ParseFromStack(Data[] stack, int stackIndex, Memory <byte> memory, StorageManager storageManager)
        {
            // If we exceeded our stack size
            if (stack.Length <= stackIndex)
            {
                throw new VarResolvingException("Could not parse variable from stack using reference type method because the stack is not populated up to the target index.");
            }

            // Obtain our pointer data from the stack.
            Memory <byte> stackEntryData = stack[stackIndex].GetBytes();

            // Switch on our location
            switch (VariableLocation)
            {
            case VarLocation.Memory:
                // Parse our pointer from the bytes.
                BigInteger pointer = BigIntegerConverter.GetBigInteger(stackEntryData.Span, false, UInt256.SIZE);

                // Parse our dereferenced value from memory. (Using our stack data as a data offset)
                return(ParseDereferencedFromMemory(memory, (int)pointer));

            case VarLocation.Storage:
                // Parse our stack data as a storage key
                StorageLocation storageLocation = new StorageLocation(stackEntryData, 0);

                // Parse our value from storage. (Using our stack data as a storage key)
                return(ParseFromStorage(storageManager, storageLocation));

            default:
                throw new VarResolvingException("Could not parse variable from stack using reference type because the provided underlying location is invalid.");
            }
        }
コード例 #5
0
ファイル: VarArray.cs プロジェクト: zutobg/Meadow
        public override object ParseFromStorage(StorageManager storageManager, StorageLocation storageLocation, IJsonRpcClient rpcClient = null)
        {
            // Obtain our storage value for our given storage location.
            Memory <byte> storageData  = storageManager.ReadStorageSlot(storageLocation.SlotKey, storageLocation.DataOffset, SizeBytes);
            BigInteger    storageValue = BigIntegerConverter.GetBigInteger(storageData.Span, false, SizeBytes);

            // Define our element slot location to iterate over.
            StorageLocation elementLocation = new StorageLocation(storageLocation.SlotKey, 0);

            // If this is a dynamic sized type, our element's storage key will be the defining
            // array's key hashed, and all consecutive element items will have consecutive storage keys.

            // In any case, we'll want to grab our array length, which is either statically defined, or
            // is defined in the storage data obtained earlier from the given location.
            int length = 0;

            if (ArraySize.HasValue)
            {
                length = ArraySize.Value;
            }
            else
            {
                elementLocation.SlotKey = KeccakHash.ComputeHashBytes(elementLocation.SlotKey.Span);
                length = (int)storageValue;
            }

            // Create our resulting object array
            object[] arrayElements = new object[length];

            // Loop for every item.
            for (int i = 0; i < arrayElements.Length; i++)
            {
                // Decode our element at this index
                arrayElements[i] = ElementObject.ParseFromStorage(storageManager, elementLocation, rpcClient);

                // Determine how to iterate, dependent on if the array is dynamically sized or not, as described earlier,
                // (since it could compact multiple elements into a single storage slot).
                if (ElementObject.StorageEntryCount == 1 && storageLocation.DataOffset + ElementObject.SizeBytes <= UInt256.SIZE)
                {
                    // It was compacted with other data (or elligible to), so we advance data offset.
                    elementLocation.DataOffset += ElementObject.SizeBytes;

                    // If our data offset exceeded the size of a slot, we advance the slot.
                    if (elementLocation.DataOffset + ElementObject.SizeBytes > UInt256.SIZE)
                    {
                        elementLocation.SlotKeyInteger++;
                        elementLocation.DataOffset = 0;
                    }
                }
                else
                {
                    // We are not compacting our storage, so we advance for each element individually.
                    elementLocation.SlotKeyInteger += ElementObject.StorageEntryCount;
                    elementLocation.DataOffset      = 0;
                }
            }

            // Return our obtained array elements
            return(arrayElements);
        }
コード例 #6
0
ファイル: InstructionExponent.cs プロジェクト: zutobg/Meadow
        public override void Execute()
        {
            // Obtain our value and exponent
            BigInteger value    = Stack.Pop();
            BigInteger exponent = Stack.Pop();

            // Calculate how much gas to deduct: the cost per exponent byte differs per Ethereum release
            byte[]     exponentBytes = BigIntegerConverter.GetBytesWithoutLeadingZeros(exponent);
            BigInteger extraGasCost  = exponentBytes.Length;

            if (Version < EthereumRelease.SpuriousDragon)
            {
                // Pre-Spurious Dragon
                extraGasCost *= GasDefinitions.GAS_EXP_BYTE;
            }
            else
            {
                // Spurious Dragon+
                extraGasCost *= GasDefinitions.GAS_EXP_BYTE_SPURIOUS_DRAGON;
            }

            // Deduct our gas
            GasState.Deduct(extraGasCost);

            // Perform an exponent operation on the two unsigned words off of the top of the stack.
            BigInteger result = BigInteger.ModPow(value, exponent, EVMDefinitions.UINT256_MAX_VALUE + 1);

            // Push the result onto the stack.
            Stack.Push(result);
        }
コード例 #7
0
ファイル: RLPxAuthBase.cs プロジェクト: michaelsproul/Meadow
        /// <summary>
        /// Recovers the ephemeral key used to sign the transformed nonce in the authentication data.
        /// Throws an exception if the recovered key is invalid, or could not be recovered.
        /// </summary>
        /// <param name="receiverPrivateKey">The private key of the receiver used to generate the shared secret.</param>
        /// <returns>Returns the remote ephemeral public key for the keypair which signed this authentication data.</returns>
        public virtual (EthereumEcdsa remoteEphemeralPublicKey, uint?chainId) RecoverDataFromSignature(EthereumEcdsa receiverPrivateKey)
        {
            // Create an EC provider with the given public key.
            EthereumEcdsa publicKey = EthereumEcdsa.Create(PublicKey, EthereumEcdsaKeyType.Public);

            // Generate the shared secret using ECDH between our local private key and this remote public key
            byte[] ecdhKey = receiverPrivateKey.ComputeECDHKey(publicKey);

            // Obtain our transformed nonce data.
            byte[] transformedNonceData = GetTransformedNonce(ecdhKey);

            // We want our signature in r,s,v format.
            BigInteger ecdsa_r = BigIntegerConverter.GetBigInteger(R, false, 32);
            BigInteger ecdsa_s = BigIntegerConverter.GetBigInteger(S, false, 32);

            (byte recoveryId, uint?chainId) = EthereumEcdsa.GetRecoveryAndChainIDFromV(V);

            // Recover the public key from the data provided.
            EthereumEcdsa remoteEphemeralPublickey = EthereumEcdsa.Recover(transformedNonceData, recoveryId, ecdsa_r, ecdsa_s);

            // Verify the key is valid

            // Return the ephemeral key
            return(remoteEphemeralPublickey, chainId);
        }
コード例 #8
0
ファイル: MiningPoW.cs プロジェクト: zutobg/Meadow
        /// <summary>
        /// Given a block header, checks if the proof of work is valid on the block header. That is, if the header values, nonce, mix hash and difficulty are all suitable.
        /// </summary>
        /// <param name="blockNumber">The number of the block which we wish to validate.</param>
        /// <param name="headerHash">Hash of a portion of the block header which is used with the nonce to generate a seed for the proof.</param>
        /// <param name="mixHash">The resulting mix hash for the provided nonce after running the hashimoto algorithm.</param>
        /// <param name="nonce">The nonce which, along with the other provided values, will calculate the mix hash to be verified.</param>
        /// <param name="difficulty">The difficulty controls filtering for a plausible solution to the block which we wish to mine.</param>
        /// <returns>Returns true if the proof of work is valid, returns false is the proof is invalid.</returns>
        public static bool CheckProof(BigInteger blockNumber, byte[] headerHash, byte[] mixHash, byte[] nonce, BigInteger difficulty)
        {
            // Verify the length of our hashes and nonce
            if (headerHash.Length != KeccakHash.HASH_SIZE || mixHash.Length != KeccakHash.HASH_SIZE || nonce.Length != 8)
            {
                return(false);
            }

            // Flip endianness if we need to (should be little endian).
            byte[] nonceFlipped = (byte[])nonce.Clone();
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(nonceFlipped);
            }

            // Obtain our cache
            Memory <byte> cache = Ethash.MakeCache(blockNumber); // TODO: Make a helper function for this to cache x results.

            // Hash our block with the given nonce and etc.
            var result = Ethash.HashimotoLight(cache, blockNumber, headerHash, nonceFlipped);

            // Verify our mix hash matches
            if (!result.MixHash.ValuesEqual(mixHash))
            {
                return(false);
            }

            // Convert the result to a big integer.
            BigInteger upperBoundInclusive = BigInteger.Pow(2, EVMDefinitions.WORD_SIZE_BITS) / BigInteger.Max(difficulty, 1);
            BigInteger resultInteger       = BigIntegerConverter.GetBigInteger(result.Result);

            return(resultInteger <= upperBoundInclusive);
        }
コード例 #9
0
 public UInt256(BigInteger value) : this(BigIntegerConverter.GetBytes(value).Reverse().ToArray())
 {
     if (value < 0)
     {
         throw new ArgumentOutOfRangeException();
     }
 }
コード例 #10
0
ファイル: RLPxAuthBase.cs プロジェクト: michaelsproul/Meadow
        public virtual void Sign(EthereumEcdsa localPrivateKey, EthereumEcdsa ephemeralPrivateKey, EthereumEcdsa receiverPublicKey, uint?chainID = null)
        {
            // Generate the shared secret using ECDH between our local private key and this remote public key
            byte[] ecdhKey = localPrivateKey.ComputeECDHKey(receiverPublicKey);

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

            // Verify the nonce is the correct length.
            if (Nonce.Length != RLPxSession.NONCE_SIZE)
            {
                // Throw an exception if an invalid nonce was provided.
                throw new ArgumentException($"Invalid size nonce provided for RLPx session when signing auth message. Should be {RLPxSession.NONCE_SIZE} bytes but was {Nonce?.Length}.");
            }

            // Obtain our transformed nonce data.
            byte[] transformedNonceData = GetTransformedNonce(ecdhKey);

            // Sign the transformed data.
            var signature = ephemeralPrivateKey.SignData(transformedNonceData);

            // We want our signature in r,s,v format.
            R = BigIntegerConverter.GetBytes(signature.r, 32);
            S = BigIntegerConverter.GetBytes(signature.s, 32);
            V = EthereumEcdsa.GetVFromRecoveryID(chainID, signature.RecoveryID);

            // Set our local public key and the public key hash.
            PublicKey = localPrivateKey.ToPublicKeyArray(false, true);
        }
コード例 #11
0
 private static byte[] HexToByteArray(string text)
 {
     if (text.Length % 2 != 0)
     {
         return(null);
     }
     return(BigIntegerConverter.ParseHex(text));
 }
コード例 #12
0
        public void RoundTripMinValueTest()
        {
            var converter = new BigIntegerConverter();
            var s         = converter.ConvertToString((BigInteger)long.MinValue - 1, null, new MemberMapData(null));
            var bi        = converter.ConvertFromString(s, null, new MemberMapData(null));

            Assert.AreEqual((BigInteger)long.MinValue - 1, bi);
        }
コード例 #13
0
        public void Test_roundtrip(NumberConversion numberConversion)
        {
            BigIntegerConverter converter = new BigIntegerConverter(numberConversion);

            TestConverter(int.MaxValue, (integer, bigInteger) => integer.Equals(bigInteger), converter);
            TestConverter(BigInteger.One, (integer, bigInteger) => integer.Equals(bigInteger), converter);
            TestConverter(BigInteger.Zero, (integer, bigInteger) => integer.Equals(bigInteger), converter);
        }
コード例 #14
0
        public void Unknown_not_supported(NumberConversion notSupportedConversion)
        {
            BigIntegerConverter converter = new BigIntegerConverter(notSupportedConversion);

            Assert.Throws <NotSupportedException>(
                () => TestConverter(int.MaxValue, (a, b) => a.Equals(b), converter));
            Assert.Throws <NotSupportedException>(
                () => TestConverter(1L, (a, b) => a.Equals(b), converter));
        }
コード例 #15
0
        static EthereumEcdsaBouncyCastle GenerateSingle(uint accountIndex, IAccountDerivation accountFactory)
        {
            var privateKey = accountFactory.GeneratePrivateKey(accountIndex);
            var keyBigInt  = BigIntegerConverter.GetBigInteger(privateKey, signed: false, byteCount: PRIVATE_KEY_SIZE);

            keyBigInt = Secp256k1Curve.EnforceLowS(keyBigInt);

            // Return our private key instance.
            return(new EthereumEcdsaBouncyCastle(privateKey, EthereumEcdsaKeyType.Private));
        }
コード例 #16
0
        public void Regression_0xa00000()
        {
            BigIntegerConverter converter = new BigIntegerConverter();
            JsonReader          reader    = new JsonTextReader(new StringReader("0xa00000"));

            reader.ReadAsString();
            BigInteger result = converter.ReadJson(reader, typeof(BigInteger), BigInteger.Zero, false, JsonSerializer.CreateDefault());

            Assert.AreEqual(BigInteger.Parse("10485760"), result);
        }
コード例 #17
0
ファイル: EVMStack.cs プロジェクト: zutobg/Meadow
        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));
        }
コード例 #18
0
        public override object ParseDereferencedFromMemory(Memory <byte> memory, int offset)
        {
            // Dynamic memory is a WORD denoting length, followed by the length in bytes of data.

            // Read a length bytes (size of word) to dereference the value.
            Memory <byte> lengthData = memory.Slice(offset, UInt256.SIZE);
            BigInteger    length     = BigIntegerConverter.GetBigInteger(lengthData.Span, false, UInt256.SIZE);

            // Read our data
            return(memory.Slice(offset + UInt256.SIZE, (int)length));
        }
コード例 #19
0
ファイル: GasUsageTests.cs プロジェクト: michaelsproul/Meadow
        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);
        }
コード例 #20
0
ファイル: GasUsageTests.cs プロジェクト: michaelsproul/Meadow
        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);
        }
コード例 #21
0
ファイル: RLP.cs プロジェクト: zutobg/Meadow
        public static BigInteger ToInteger(RLPByteArray rlpByteArray, int byteCount = 32, bool signed = false)
        {
            // If our data is null or empty, the result is 0.
            if (rlpByteArray.Data.Length == 0)
            {
                return(0);
            }

            // Obtain our integer
            return(BigIntegerConverter.GetBigInteger(rlpByteArray.Data.Span, signed, byteCount));
        }
コード例 #22
0
        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));
        }
コード例 #23
0
ファイル: RLP.cs プロジェクト: zutobg/Meadow
 // 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)));
     }
 }
コード例 #24
0
        public override object ParseFromMemory(Memory <byte> memory, int offset)
        {
            // Read a pointer bytes (size of word) to dereference the value.
            Memory <byte> pointerData = memory.Slice(offset, UInt256.SIZE);

            // Parse our pointer from the bytes.
            BigInteger pointer = BigIntegerConverter.GetBigInteger(pointerData.Span, false, UInt256.SIZE);

            // Parse our dereferenced value.
            return(ParseDereferencedFromMemory(memory, (int)pointer));
        }
コード例 #25
0
        // Test of signing and verifying using test vectors
        // http://ed25519.cr.yp.to/python/sign.input
        internal static void Test()
        {
            using (var reader = new System.IO.StreamReader(@"sign.input")) {
                int skip  = 0;
                int count = 0;
                while (true)
                {
                    string line = reader.ReadLine();
                    if (line == null)
                    {
                        break;
                    }
                    count++;
                    if (count <= skip)
                    {
                        continue;
                    }
                    System.Diagnostics.Debug.WriteLine("Line {0}", count);

                    string[] w          = line.Split(':');
                    byte[][] b          = w.Select(s => BigIntegerConverter.ParseHex(s)).ToArray();
                    byte[]   privateKey = new byte[32];
                    Buffer.BlockCopy(b[0], 0, privateKey, 0, 32);
                    byte[] publicKey = b[1];
                    byte[] message   = b[2];
                    byte[] signature = new byte[64];
                    Buffer.BlockCopy(b[3], 0, signature, 0, 64);

                    CurveEd25519 curve = new CurveEd25519();

                    byte[] sig;
                    if (!curve.Sign(privateKey, message, out sig))
                    {
                        throw new Exception("signing failed");
                    }
                    if (sig.Length != signature.Length)
                    {
                        throw new Exception("invalid sign length");
                    }
                    for (int i = 0; i < signature.Length; ++i)
                    {
                        if (sig[i] != signature[i])
                        {
                            throw new Exception("signs doesn't match");
                        }
                    }
                    if (!curve.Verify(publicKey, signature, message))
                    {
                        throw new Exception("verification failed");
                    }
                }
            }
        }
コード例 #26
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);
        }
コード例 #27
0
        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));
        }
コード例 #28
0
ファイル: InstructionCreate.cs プロジェクト: zutobg/Meadow
        public override void Execute()
        {
            // Obtain the values for our call value, and call data memory.
            BigInteger value            = Stack.Pop();
            BigInteger inputMemoryStart = Stack.Pop();
            BigInteger inputMemorySize  = Stack.Pop();

            // We'll want to charge for memory expansion first
            Memory.ExpandStream(inputMemoryStart, inputMemorySize);

            // If we're in a static context, we can't self destruct
            if (Message.IsStatic)
            {
                throw new EVMException($"{Opcode.ToString()} instruction cannot execute in a static context!");
            }

            // Verify we have enough balance and call depth hasn't exceeded the maximum.
            if (EVM.State.GetBalance(Message.To) >= value && Message.Depth < EVMDefinitions.MAX_CALL_DEPTH)
            {
                // Obtain our call information.
                byte[]     callData     = Memory.ReadBytes((long)inputMemoryStart, (int)inputMemorySize);
                BigInteger innerCallGas = GasState.Gas;
                if (Version >= EthereumRelease.TangerineWhistle)
                {
                    innerCallGas = GasDefinitions.GetMaxCallGas(innerCallGas);
                }

                // Create our message
                EVMMessage         message       = new EVMMessage(Message.To, Address.ZERO_ADDRESS, value, innerCallGas, callData, Message.Depth + 1, Address.ZERO_ADDRESS, true, Message.IsStatic);
                EVMExecutionResult innerVMResult = MeadowEVM.CreateContract(EVM.State, message);
                if (innerVMResult.Succeeded)
                {
                    // Push our resulting address onto the stack.
                    Stack.Push(BigIntegerConverter.GetBigInteger(innerVMResult.ReturnData.ToArray()));
                    EVM.ExecutionState.LastCallResult = null;
                }
                else
                {
                    // We failed, push our fail value and put the last call data in place.
                    Stack.Push(0);
                    ExecutionState.LastCallResult = innerVMResult;
                }
            }
            else
            {
                // We didn't have a sufficient balance or call depth so we push nothing to the stack. We push 0 (fail)
                Stack.Push(0);

                // Set our last call result as null.
                ExecutionState.LastCallResult = null;
            }
        }
コード例 #29
0
ファイル: EVMStack.cs プロジェクト: zutobg/Meadow
        public BigInteger Pop(bool signed = false)
        {
            // Verify we have items on the stack.
            if (_internalStack.Count == 0)
            {
                throw new EVMException("Tried to pop a value off of the stack when the stack was empty. This should not have happened.");
            }

            // Pop a value off the internal stack, convert it, and return it.
            byte[] data = _internalStack[_internalStack.Count - 1];
            _internalStack.RemoveAt(_internalStack.Count - 1);
            return(BigIntegerConverter.GetBigInteger(data, signed));
        }
コード例 #30
0
ファイル: MiningPoW.cs プロジェクト: zutobg/Meadow
        /// <summary>
        /// Mines a given block starting from the provided nonce for the provided number of rounds.
        /// </summary>
        /// <param name="blockNumber">The number of the block which we are mining.</param>
        /// <param name="difficulty">The difficulty of the block which we are mining.</param>
        /// <param name="miningHash">The mining hash (partial header hash) of the block which we are mining.</param>
        /// <param name="startNonce">The starting nonce we will use and iterate through to try and find a suitable one for the reward.</param>
        /// <param name="rounds">The number of steps to take from our starting nonce before giving up. Use ulong.MaxValue to try all.</param>
        /// <returns>Returns the nonce and mixhash if block is successfully mined, otherwise both are null.</returns>
        public static (byte[] Nonce, byte[] MixHash) Mine(BigInteger blockNumber, BigInteger difficulty, byte[] miningHash, ulong startNonce, ulong rounds)
        {
            // Verify the length of our hashes and nonce
            if (miningHash == null || miningHash.Length != KeccakHash.HASH_SIZE)
            {
                return(null, null);
            }

            // Get our cache, set our start nonce and rounds remaining
            Memory <byte> cache           = Ethash.MakeCache(blockNumber);
            ulong         nonce           = startNonce;
            BigInteger    roundsRemaining = rounds;

            // Obtain our upper bound.
            BigInteger upperBoundInclusive = (BigInteger.Pow(2, EVMDefinitions.WORD_SIZE_BITS) / BigInteger.Max(difficulty, 1)) - 1;

            // Loop for each round.
            for (ulong i = 0; i <= rounds; i++)
            {
                // Increment our nonce.
                nonce++;

                // Obtain the bytes for it
                byte[] nonceData = BitConverter.GetBytes(nonce);

                // Flip endianness if we need to (should be little endian).
                if (!BitConverter.IsLittleEndian)
                {
                    Array.Reverse(nonceData);
                }

                // Obtain our mix hash with this nonce.
                var        result        = Ethash.HashimotoLight(cache, blockNumber, miningHash, nonceData);
                BigInteger resultInteger = BigIntegerConverter.GetBigInteger(result.Result);

                // If our result is below our difficulty bound.
                if (resultInteger <= upperBoundInclusive)
                {
                    // Flip endianness if we need to (returning nonce should be big endian).
                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(nonceData);
                    }

                    // Return our nonce and mix hash.
                    return(nonceData, result.MixHash);
                }
            }

            return(null, null);
        }