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); }
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; }