diff --git a/packages/solo/run.go b/packages/solo/run.go index b4300bb02f..5a32bec505 100644 --- a/packages/solo/run.go +++ b/packages/solo/run.go @@ -67,7 +67,7 @@ func (ch *Chain) runTaskNoLock(reqs []isc.Request, estimateGas bool) *vm.VMTaskR ValidatorFeeTarget: ch.ValidatorFeeTarget, Log: ch.Log().Desugar().WithOptions(zap.AddCallerSkip(1)).Sugar(), // state baseline is always valid in Solo - EnableGasBurnLogging: true, + EnableGasBurnLogging: ch.Env.enableGasBurnLogging, EstimateGasMode: estimateGas, MigrationsOverride: ch.migrationScheme, } diff --git a/packages/solo/solo.go b/packages/solo/solo.go index 56d5b764f3..83d5fc8860 100644 --- a/packages/solo/solo.go +++ b/packages/solo/solo.go @@ -65,6 +65,7 @@ type Solo struct { chains map[isc.ChainID]*Chain processorConfig *processors.Config disableAutoAdjustStorageDeposit bool + enableGasBurnLogging bool seed cryptolib.Seed publisher *publisher.Publisher ctx context.Context @@ -129,6 +130,7 @@ type InitOptions struct { AutoAdjustStorageDeposit bool Debug bool PrintStackTrace bool + GasBurnLogEnabled bool Seed cryptolib.Seed Log *logger.Logger } @@ -139,6 +141,7 @@ func DefaultInitOptions() *InitOptions { PrintStackTrace: false, Seed: cryptolib.Seed{}, AutoAdjustStorageDeposit: false, // is OFF by default + GasBurnLogEnabled: true, // is ON by default } } @@ -176,6 +179,7 @@ func New(t testing.TB, initOptions ...*InitOptions) *Solo { chains: make(map[isc.ChainID]*Chain), processorConfig: coreprocessors.NewConfigWithCoreContracts(), disableAutoAdjustStorageDeposit: !opt.AutoAdjustStorageDeposit, + enableGasBurnLogging: opt.GasBurnLogEnabled, seed: opt.Seed, publisher: publisher.New(opt.Log.Named("publisher")), ctx: ctx, diff --git a/packages/vm/core/blocklog/receipt.go b/packages/vm/core/blocklog/receipt.go index 6c3fe18408..90633bdf09 100644 --- a/packages/vm/core/blocklog/receipt.go +++ b/packages/vm/core/blocklog/receipt.go @@ -78,6 +78,11 @@ func (rec *RequestReceipt) Read(r io.Reader) error { rec.Error = new(isc.UnresolvedVMError) rr.Read(rec.Error) } + if len(rr.Bytes()) != 0 { + rec.GasBurnLog = new(gas.BurnLog) + rr.Read(rec.GasBurnLog) + } + return rr.Err } @@ -92,6 +97,9 @@ func (rec *RequestReceipt) Write(w io.Writer) error { if rec.Error != nil { ww.Write(rec.Error) } + if rec.GasBurnLog != nil { + ww.Write(rec.GasBurnLog) + } return ww.Err } @@ -102,6 +110,7 @@ func (rec *RequestReceipt) String() string { ret += fmt.Sprintf("Gas budget / burned / fee charged: %d / %d /%d\n", rec.GasBudget, rec.GasBurned, rec.GasFeeCharged) ret += fmt.Sprintf("Storage deposit charged: %d\n", rec.SDCharged) ret += fmt.Sprintf("Call data: %s\n", rec.Request) + ret += fmt.Sprintf("burn log: %s\n", rec.GasBurnLog) return ret } @@ -134,6 +143,7 @@ func (rec *RequestReceipt) ToISCReceipt(resolvedError *isc.VMError) *isc.Receipt BlockIndex: rec.BlockIndex, RequestIndex: rec.RequestIndex, ResolvedError: resolvedError.Error(), + GasBurnLog: rec.GasBurnLog, } } diff --git a/packages/vm/core/evm/evmtest/utils_test.go b/packages/vm/core/evm/evmtest/utils_test.go index 316d21b6c9..6448da0af9 100644 --- a/packages/vm/core/evm/evmtest/utils_test.go +++ b/packages/vm/core/evm/evmtest/utils_test.go @@ -90,6 +90,7 @@ func initEVM(t testing.TB, nativeContracts ...*coreutil.ContractProcessor) *solo AutoAdjustStorageDeposit: true, Debug: true, PrintStackTrace: true, + GasBurnLogEnabled: false, }) for _, c := range nativeContracts { env = env.WithNativeContract(c) diff --git a/packages/vm/gas/burnlog.go b/packages/vm/gas/burnlog.go index 56f3f9facf..89cc742ff4 100644 --- a/packages/vm/gas/burnlog.go +++ b/packages/vm/gas/burnlog.go @@ -2,7 +2,10 @@ package gas import ( "fmt" + "io" "strings" + + "github.com/iotaledger/wasp/packages/util/rwutil" ) type BurnRecord struct { @@ -18,21 +21,49 @@ func NewGasBurnLog() *BurnLog { return &BurnLog{Records: make([]BurnRecord, 0)} } -func (h *BurnLog) Record(code BurnCode, gas uint64) { - if h != nil { - h.Records = append(h.Records, BurnRecord{code, gas}) +func (l *BurnLog) Record(code BurnCode, gas uint64) { + if l != nil { + l.Records = append(l.Records, BurnRecord{code, gas}) + } +} + +func (l *BurnLog) Read(r io.Reader) error { + rr := rwutil.NewReader(r) + recordLen := rr.ReadUint32() + l.Records = make([]BurnRecord, recordLen) + for i := 0; i < int(recordLen); i++ { + name := rr.ReadString() + burnCode := BurnCodeFromName(name) + gasBurned := rr.ReadUint64() + + l.Records[i] = BurnRecord{ + Code: burnCode, + GasBurned: gasBurned, + } + } + return rr.Err +} + +func (l *BurnLog) Write(w io.Writer) error { + ww := rwutil.NewWriter(w) + recordLen := len(l.Records) + ww.WriteUint32(uint32(recordLen)) + for _, record := range l.Records { + ww.WriteString(record.Code.Name()) + ww.WriteUint64(record.GasBurned) } + return ww.Err } -func (h *BurnLog) String() string { - if h == nil { +func (l *BurnLog) String() string { + if l == nil { return "(no burn history)" } - ret := make([]string, 0, len(h.Records)+2) + ret := make([]string, 0, len(l.Records)+2) var total uint64 - for i := range h.Records { - ret = append(ret, fmt.Sprintf("%10s: %d", h.Records[i].Code.Name(), h.Records[i].GasBurned)) - total += h.Records[i].GasBurned + for i := range l.Records { + ret = append(ret, fmt.Sprintf("%10s: %d", l.Records[i].Code.Name(), l.Records[i].GasBurned)) + total += l.Records[i].GasBurned } ret = append(ret, "---------------", fmt.Sprintf("%10s: %d", "TOTAL", total)) return strings.Join(ret, "\n") diff --git a/packages/vm/gas/burnlog_test.go b/packages/vm/gas/burnlog_test.go new file mode 100644 index 0000000000..d64214e4f3 --- /dev/null +++ b/packages/vm/gas/burnlog_test.go @@ -0,0 +1,23 @@ +package gas_test + +import ( + "testing" + + "github.com/iotaledger/wasp/packages/util/rwutil" + "github.com/iotaledger/wasp/packages/vm/gas" +) + +func TestBurnLogSerialization(t *testing.T) { + var burnLog gas.BurnLog + burnLog.Records = []gas.BurnRecord{ + { + Code: gas.BurnCodeCallTargetNotFound, + GasBurned: 10, + }, + { + Code: gas.BurnCodeUtilsHashingSha3, + GasBurned: 80, + }, + } + rwutil.ReadWriteTest(t, &burnLog, new(gas.BurnLog)) +} diff --git a/packages/vm/gas/types.go b/packages/vm/gas/types.go index fc65caa90d..767599d8c7 100644 --- a/packages/vm/gas/types.go +++ b/packages/vm/gas/types.go @@ -1,6 +1,9 @@ package gas -import "errors" +import ( + "errors" + "fmt" +) type BurnCode uint16 @@ -22,3 +25,12 @@ func (c BurnCode) Name() string { } return r.Name } + +func BurnCodeFromName(name string) BurnCode { + for burnCode := range burnTable { + if burnCode.Name() == name { + return burnCode + } + } + panic(fmt.Sprintf("name %s not exist", name)) +}