예제 #1
0
 protected void SerializePrefix(byte[] bytes, ContractTxData contractTxData)
 {
     byte[] vmVersion = this.primitiveSerializer.Serialize(contractTxData.VmVersion);
     byte[] gasPrice  = this.primitiveSerializer.Serialize(contractTxData.GasPrice);
     byte[] gasLimit  = this.primitiveSerializer.Serialize(contractTxData.GasLimit.Value);
     bytes[0] = contractTxData.OpCodeType;
     vmVersion.CopyTo(bytes, OpcodeSize);
     gasPrice.CopyTo(bytes, OpcodeSize + VmVersionSize);
     gasLimit.CopyTo(bytes, OpcodeSize + VmVersionSize + GasPriceSize);
 }
예제 #2
0
        private Result <ContractTxData> SerializeCreateContract(byte[] smartContractBytes, int vmVersion, ulong gasPrice, Gas gasLimit)
        {
            var remaining = smartContractBytes.Slice(PrefixSize, (uint)(smartContractBytes.Length - PrefixSize));

            IList <byte[]> decodedParams = RLPDecode(remaining);

            var contractExecutionCode = this.primitiveSerializer.Deserialize <byte[]>(decodedParams[0]);
            var methodParameters      = this.DeserializeMethodParameters(decodedParams[1]);

            var callData = new ContractTxData(vmVersion, gasPrice, gasLimit, contractExecutionCode, methodParameters);

            return(Result.Ok(callData));
        }
예제 #3
0
        protected virtual Result <ContractTxData> SerializeCreateContract(byte[] smartContractBytes, int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit)
        {
            byte[] remaining = smartContractBytes.Slice(PrefixSize, (uint)(smartContractBytes.Length - PrefixSize));

            IList <byte[]> decodedParams = RLPDecode(remaining);

            var contractExecutionCode = this.primitiveSerializer.Deserialize <byte[]>(decodedParams[0]);

            object[] methodParameters = this.DeserializeMethodParameters(decodedParams[1]);
            string[] signatures       = (decodedParams.Count > 2) ? this.DeserializeSignatures(decodedParams[2]) : null;

            var callData = new ContractTxData(vmVersion, gasPrice, gasLimit, contractExecutionCode, methodParameters, signatures);

            return(Result.Ok(callData));
        }
예제 #4
0
        private Result <ContractTxData> SerializeCallContract(byte[] smartContractBytes, int vmVersion, ulong gasPrice, Gas gasLimit)
        {
            var contractAddressBytes = smartContractBytes.Slice(PrefixSize, AddressSize);
            var contractAddress      = new uint160(contractAddressBytes);

            var remaining = smartContractBytes.Slice(CallContractPrefixSize,
                                                     (uint)(smartContractBytes.Length - CallContractPrefixSize));

            IList <byte[]> decodedParams = RLPDecode(remaining);

            var methodName       = this.primitiveSerializer.Deserialize <string>(decodedParams[0]);
            var methodParameters = this.DeserializeMethodParameters(decodedParams[1]);
            var callData         = new ContractTxData(vmVersion, gasPrice, gasLimit, contractAddress, methodName, methodParameters);

            return(Result.Ok(callData));
        }
예제 #5
0
        private byte[] SerializeCreateContract(ContractTxData contractTxData)
        {
            var rlpBytes = new List <byte[]>();

            rlpBytes.Add(contractTxData.ContractExecutionCode);

            this.AddMethodParams(rlpBytes, contractTxData.MethodParameters);

            var encoded = RLP.EncodeList(rlpBytes.Select(RLP.EncodeElement).ToArray());

            var bytes = new byte[PrefixSize + encoded.Length];

            this.SerializePrefix(bytes, contractTxData);

            encoded.CopyTo(bytes, PrefixSize);

            return(bytes);
        }
예제 #6
0
        public Result <ContractTxData> SerializeCallContract(byte[] smartContractBytes, int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit)
        {
            byte[] contractAddressBytes = smartContractBytes.Slice(PrefixSize, AddressSize);
            var    contractAddress      = new uint160(contractAddressBytes);

            byte[] remaining = smartContractBytes.Slice(CallContractPrefixSize,
                                                        (uint)(smartContractBytes.Length - CallContractPrefixSize));

            IList <byte[]> decodedParams = RLPDecode(remaining);

            string methodName = this.primitiveSerializer.Deserialize <string>(decodedParams[0]);

            object[] methodParameters = this.DeserializeMethodParameters(decodedParams[1]);
            string[] signatures       = (decodedParams.Count > 2) ? this.DeserializeSignatures(decodedParams[2]) : null;

            var callData = new ContractTxData(vmVersion, gasPrice, gasLimit, contractAddress, methodName, methodParameters, signatures);

            return(Result.Ok(callData));
        }
예제 #7
0
        private byte[] SerializeCallContract(ContractTxData contractTxData)
        {
            var rlpBytes = new List <byte[]>();

            rlpBytes.Add(this.primitiveSerializer.Serialize(contractTxData.MethodName));

            this.AddMethodParams(rlpBytes, contractTxData.MethodParameters);

            var encoded = RLP.EncodeList(rlpBytes.Select(RLP.EncodeElement).ToArray());

            var bytes = new byte[CallContractPrefixSize + encoded.Length];

            this.SerializePrefix(bytes, contractTxData);

            contractTxData.ContractAddress.ToBytes().CopyTo(bytes, PrefixSize);

            encoded.CopyTo(bytes, CallContractPrefixSize);

            return(bytes);
        }
예제 #8
0
 public byte[] Serialize(ContractTxData contractTxData)
 {
     return(IsCallContract(contractTxData.OpCodeType)
         ? this.SerializeCallContract(contractTxData)
         : this.SerializeCreateContract(contractTxData));
 }
        public IContractExecutionResult Execute(IContractTransactionContext transactionContext)
        {
            // Deserialization can't fail because this has already been through SmartContractFormatRule.
            Result <ContractTxData> callDataDeserializationResult = this.serializer.Deserialize(transactionContext.Data);
            ContractTxData          callData = callDataDeserializationResult.Value;

            bool creation = callData.IsCreateContract;

            var block = new Block(
                transactionContext.BlockHeight,
                transactionContext.CoinbaseAddress.ToAddress()
                );

            IState state = this.stateFactory.Create(
                this.stateRoot,
                block,
                transactionContext.TxOutValue,
                transactionContext.TransactionHash);

            StateTransitionResult result;
            IState newState = state.Snapshot();

            if (creation)
            {
                var message = new ExternalCreateMessage(
                    transactionContext.Sender,
                    transactionContext.TxOutValue,
                    callData.GasLimit,
                    callData.ContractExecutionCode,
                    callData.MethodParameters
                    );

                result = this.stateProcessor.Apply(newState, message);
            }
            else
            {
                var message = new ExternalCallMessage(
                    callData.ContractAddress,
                    transactionContext.Sender,
                    transactionContext.TxOutValue,
                    callData.GasLimit,
                    new MethodCall(callData.MethodName, callData.MethodParameters)
                    );

                result = this.stateProcessor.Apply(newState, message);
            }

            bool revert = !result.IsSuccess;

            Transaction internalTransaction = this.transferProcessor.Process(
                newState.ContractState,
                result.Success?.ContractAddress,
                transactionContext,
                newState.InternalTransfers,
                revert);

            if (result.IsSuccess)
            {
                state.TransitionTo(newState);
            }

            bool outOfGas = result.IsFailure && result.Error.Kind == StateTransitionErrorKind.OutOfGas;

            (Money fee, TxOut refundTxOut) = this.refundProcessor.Process(
                callData,
                transactionContext.MempoolFee,
                transactionContext.Sender,
                result.GasConsumed,
                outOfGas);

            var executionResult = new SmartContractExecutionResult
            {
                To = !callData.IsCreateContract ? callData.ContractAddress : null,
                NewContractAddress  = !revert && creation ? result.Success?.ContractAddress : null,
                ErrorMessage        = result.Error?.GetErrorMessage(),
                Revert              = revert,
                GasConsumed         = result.GasConsumed,
                Return              = result.Success?.ExecutionResult,
                InternalTransaction = internalTransaction,
                Fee    = fee,
                Refund = refundTxOut,
                Logs   = state.GetLogs(this.contractPrimitiveSerializer)
            };

            return(executionResult);
        }