From 4254407a9b19ed56954727cd244b676c0fdb0369 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 4 Apr 2022 19:28:36 +0300 Subject: [PATCH] dao: add GetTxExecResult method --- pkg/core/dao/dao.go | 93 +++++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index e5e27d4ba..b178d2aaf 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -254,41 +254,84 @@ func (dao *Simple) GetAppExecResults(hash util.Uint256, trig trigger.Type) ([]st if err != nil { return nil, err } - r := io.NewBinReaderFromBuf(bs) - switch pref := r.ReadB(); pref { + if len(bs) == 0 { + return nil, fmt.Errorf("%w: empty execution log", ErrInternalDBInconsistency) + } + switch bs[0] { case storage.ExecBlock: + r := io.NewBinReaderFromBuf(bs) + _ = r.ReadB() _, err = block.NewTrimmedFromReader(dao.Version.StateRootInHeader, r) if err != nil { return nil, err } - case storage.ExecTransaction: - if len(bs) >= 6 && bs[5] == transaction.DummyVersion { - return nil, storage.ErrKeyNotFound - } - _ = r.ReadU32LE() - tx := &transaction.Transaction{} - tx.DecodeBinary(r) - default: - return nil, fmt.Errorf("%w: unexpected executable prefix %d", ErrInternalDBInconsistency, pref) - } - if r.Err != nil { - return nil, r.Err - } - result := make([]state.AppExecResult, 0, 2) - for { - aer := new(state.AppExecResult) - aer.DecodeBinary(r) - if r.Err != nil { - if r.Err == iocore.EOF { - break + result := make([]state.AppExecResult, 0, 2) + for { + aer := new(state.AppExecResult) + aer.DecodeBinary(r) + if r.Err != nil { + if r.Err == iocore.EOF { + break + } + return nil, r.Err } - return nil, r.Err + if aer.Trigger&trig != 0 { + result = append(result, *aer) + } + } + return result, nil + case storage.ExecTransaction: + _, _, aer, err := decodeTxAndExecResult(bs) + if err != nil { + return nil, err } if aer.Trigger&trig != 0 { - result = append(result, *aer) + return []state.AppExecResult{*aer}, nil } + return nil, nil + default: + return nil, fmt.Errorf("%w: unexpected executable prefix %d", ErrInternalDBInconsistency, bs[0]) } - return result, nil +} + +// GetTxExecResult gets application execution result of the specified transaction +// and returns the transaction itself, its height and its AppExecResult. +func (dao *Simple) GetTxExecResult(hash util.Uint256) (uint32, *transaction.Transaction, *state.AppExecResult, error) { + key := dao.makeExecutableKey(hash) + bs, err := dao.Store.Get(key) + if err != nil { + return 0, nil, nil, err + } + if len(bs) == 0 { + return 0, nil, nil, fmt.Errorf("%w: empty execution log", ErrInternalDBInconsistency) + } + if bs[0] != storage.ExecTransaction { + return 0, nil, nil, storage.ErrKeyNotFound + } + return decodeTxAndExecResult(bs) +} + +// decodeTxAndExecResult decodes transaction, its height and execution result from +// the given executable bytes. It performs no executable prefix check. +func decodeTxAndExecResult(buf []byte) (uint32, *transaction.Transaction, *state.AppExecResult, error) { + if len(buf) >= 6 && buf[5] == transaction.DummyVersion { + return 0, nil, nil, storage.ErrKeyNotFound + } + r := io.NewBinReaderFromBuf(buf) + _ = r.ReadB() + h := r.ReadU32LE() + tx := &transaction.Transaction{} + tx.DecodeBinary(r) + if r.Err != nil { + return 0, nil, nil, r.Err + } + aer := new(state.AppExecResult) + aer.DecodeBinary(r) + if r.Err != nil { + return 0, nil, nil, r.Err + } + + return h, tx, aer, nil } // -- end notification event.