Ejemplo n.º 1
0
        private TransactionExecutingStateSet GetChanges()
        {
            var changes = _smartContractProxy.GetChanges();

            var address = _hostSmartContractBridgeContext.Self.ToStorageKey();

            foreach (var key in changes.Writes.Keys)
            {
                if (!key.StartsWith(address))
                {
                    throw new InvalidOperationException("a contract cannot access other contracts data");
                }
            }

            foreach (var(key, value) in changes.Deletes)
            {
                if (!key.StartsWith(address))
                {
                    throw new InvalidOperationException("a contract cannot access other contracts data");
                }
            }

            foreach (var key in changes.Reads.Keys)
            {
                if (!key.StartsWith(address))
                {
                    throw new InvalidOperationException("a contract cannot access other contracts data");
                }
            }

            if (!CurrentTransactionContext.Trace.IsSuccessful())
            {
                changes.Writes.Clear();
                changes.Deletes.Clear();
            }

            return(changes);
        }
Ejemplo n.º 2
0
        public void Execute()
        {
            var s          = CurrentTransactionContext.Trace.StartTime = TimestampHelper.GetUtcNow().ToDateTime();
            var methodName = CurrentTransactionContext.Transaction.MethodName;

            try
            {
                if (!_callHandlers.TryGetValue(methodName, out var handler))
                {
                    throw new RuntimeException(
                              $"Failed to find handler for {methodName}. We have {_callHandlers.Count} handlers: " +
                              string.Join(", ", _callHandlers.Keys.OrderBy(k => k))
                              );
                }

                try
                {
                    var tx     = CurrentTransactionContext.Transaction;
                    var retVal = handler.Execute(tx.Params.ToByteArray());
                    if (retVal != null)
                    {
                        CurrentTransactionContext.Trace.ReturnValue = ByteString.CopyFrom(retVal);
                        // TODO: Clean up ReadableReturnValue
                        CurrentTransactionContext.Trace.ReadableReturnValue = handler.ReturnBytesToString(retVal);
                    }

                    CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.Executed;
                }
                catch (TargetInvocationException ex)
                {
                    CurrentTransactionContext.Trace.Error          += ex;
                    CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                }
                catch (AssertionException ex)
                {
                    CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                    CurrentTransactionContext.Trace.Error          += "\n" + ex;
                }
                catch (Exception ex)
                {
                    // TODO: Simplify exception
                    CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                    CurrentTransactionContext.Trace.Error          += "\n" + ex;
                }

                if (!handler.IsView())
                {
                    var changes = _smartContractProxy.GetChanges();

                    var address = _hostSmartContractBridgeContext.Self.ToStorageKey();
                    foreach (var key in changes.Writes.Keys)
                    {
                        if (!key.StartsWith(address))
                        {
                            throw new InvalidOperationException("a contract cannot access other contracts data");
                        }
                    }

                    foreach (var key in changes.Reads.Keys)
                    {
                        if (!key.StartsWith(address))
                        {
                            throw new InvalidOperationException("a contract cannot access other contracts data");
                        }
                    }

                    if (!CurrentTransactionContext.Trace.IsSuccessful())
                    {
                        changes.Writes.Clear();
                    }

                    CurrentTransactionContext.Trace.StateSet = changes;
                }
                else
                {
                    CurrentTransactionContext.Trace.StateSet = new TransactionExecutingStateSet();
                }
            }
            catch (Exception ex)
            {
                CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.SystemError;
                CurrentTransactionContext.Trace.Error          += ex + "\n";
            }
            finally
            {
                // TODO: Not needed
                Cleanup();
            }

            var e = CurrentTransactionContext.Trace.EndTime = TimestampHelper.GetUtcNow().ToDateTime();

            CurrentTransactionContext.Trace.Elapsed = (e - s).Ticks;
        }