Esempio n. 1
0
        public ExecutionStatus GetDeployHeight(UInt160 contractAddress, SystemContractExecutionFrame frame)
        {
            frame.ReturnValue = new byte[64];
            try
            {
                if (HardforkHeights.IsHardfork_3Active(frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight()))
                {
                    if (HardforkHeights.IsHardfork_6Active(
                            frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight()))
                    {
                        frame.ReturnValue = _deployHeight.GetValue(contractAddress.ToBytes()) ?? new byte[64];
                    }
                    else
                    {
                        frame.ReturnValue = _deployHeight.GetValue(contractAddress.ToBytes());
                    }
                }
            }
            catch (Exception e)
            {
                Logger.LogInformation($"Exception while get deploy height: {e}");
            }

            return(ExecutionStatus.Ok);
        }
Esempio n. 2
0
        private ExecutionStatus DeployV1(byte[] byteCode, SystemContractExecutionFrame frame)
        {
            Logger.LogInformation($"Deploy({byteCode.ToHex()})");
            frame.ReturnValue = Array.Empty <byte>();
            frame.UseGas(checked (GasMetering.DeployCost + GasMetering.DeployCostPerByte * (ulong)byteCode.Length));
            var receipt = _context.Receipt ?? throw new InvalidOperationException();
            // calculate contract hash and register it
            // the contractAddress at which the bytecode will be stored as calculated
            // from the sender address (To) and its nonce.
            var hash = UInt160Utils.Zero.ToBytes().Ripemd();

            if (receipt.Transaction?.From != null)
            {
                hash = receipt.Transaction.From.ToBytes()
                       .Concat(receipt.Transaction.Nonce.ToBytes())
                       .Ripemd();
            }

            var contract = new Contract(hash, byteCode);

            if (!VirtualMachine.VerifyContract(contract.ByteCode, false))
            {
                Logger.LogInformation("Failed to verify contract");
                return(ExecutionStatus.ExecutionHalted);
            }

            try
            {
                _context.Snapshot.Contracts.AddContract(_context.Sender, new Contract(hash, contract.ByteCode));
                Logger.LogInformation($"New contract with address {hash.ToHex()} deployed");

                if (HardforkHeights.IsHardfork_3Active(frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight()))
                {
                    _deployHeight.SetValue(hash.ToBytes(),
                                           frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight().ToBytes().ToArray());
                }
            }
            catch (OutOfGasException e)
            {
                Logger.LogInformation("Out of gas");
                frame.UseGas(e.GasUsed);
                return(ExecutionStatus.GasOverflow);
            }

            return(ExecutionStatus.Ok);
        }
Esempio n. 3
0
        public ExecutionStatus SetDeployHeight(UInt160 contractAddress, byte[] height, SystemContractExecutionFrame frame)
        {
            try
            {
                // Only contract itself can change its deploy height
                if (!frame.CurrentAddress.Equals(contractAddress))
                {
                    throw new Exception("Only contract itself can change its deploy height");
                }

                if (HardforkHeights.IsHardfork_3Active(frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight()))
                {
                    _deployHeight.SetValue(contractAddress.ToBytes(), height.ToArray());
                }
            }
            catch (Exception e)
            {
                Logger.LogInformation($"Exception while set deploy height: {e}");
                return(ExecutionStatus.UnknownError);
            }

            return(ExecutionStatus.Ok);
        }
Esempio n. 4
0
        private ExecutionStatus DeployV2(byte[] byteCode, SystemContractExecutionFrame frame)
        {
            Logger.LogInformation($"Deploy({byteCode.ToHex()})");
            frame.ReturnValue = Array.Empty <byte>();
            frame.UseGas(checked (GasMetering.DeployCost + GasMetering.DeployCostPerByte * (ulong)byteCode.Length));
            var receipt = _context.Receipt ?? throw new InvalidOperationException();
            /* calculate contract hash and register it */
            var hash = UInt160Utils.Zero.ToBytes().Ripemd();

            if (receipt.Transaction?.From != null)
            {
                hash = receipt.Transaction.From.ToBytes()
                       .Concat(receipt.Transaction.Nonce.ToBytes())
                       .Ripemd();
            }

            // TODO: this is fake, we have to think of what happens if someone tries to get current address during deploy
            // deployment code
            var deploymentContract = new Contract(hash, byteCode);

            if (!VirtualMachine.VerifyContract(deploymentContract.ByteCode, true))
            {
                Logger.LogInformation("Failed to verify deployment contract");
                return(ExecutionStatus.ExecutionHalted);
            }

            try
            {
                _context.Snapshot.Contracts.AddContract(_context.Sender, new Contract(hash, deploymentContract.ByteCode));
            }
            catch (OutOfGasException e)
            {
                Logger.LogInformation("Out of gas");
                frame.UseGas(e.GasUsed);
                return(ExecutionStatus.GasOverflow);
            }

            var status = VirtualMachine.InvokeWasmContract(deploymentContract, _context, Array.Empty <byte>(), frame.GasLimit);

            if (status.Status != ExecutionStatus.Ok || status.ReturnValue is null)
            {
                Logger.LogInformation("Failed to initialize contract");
                return(ExecutionStatus.ExecutionHalted);
            }

            // runtime code
            var runtimeContract = new Contract(hash, status.ReturnValue);

            if (!VirtualMachine.VerifyContract(runtimeContract.ByteCode, true))
            {
                Logger.LogInformation("Failed to verify runtime contract");
                return(ExecutionStatus.ExecutionHalted);
            }

            try
            {
                _context.Snapshot.Contracts.AddContract(_context.Sender, new Contract(hash, runtimeContract.ByteCode));
                Logger.LogInformation($"New contract with address {hash.ToHex()} deployed");
                if (HardforkHeights.IsHardfork_3Active(frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight()))
                {
                    _deployHeight.SetValue(hash.ToBytes(),
                                           frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight().ToBytes().ToArray());
                }
            }
            catch (OutOfGasException e)
            {
                Logger.LogInformation("Out of gas");
                frame.UseGas(e.GasUsed);
                return(ExecutionStatus.GasOverflow);
            }

            return(ExecutionStatus.Ok);
        }