diff --git a/api/doc/thor.yaml b/api/doc/thor.yaml index 44ef1eb68..5c31b84ca 100644 --- a/api/doc/thor.yaml +++ b/api/doc/thor.yaml @@ -322,6 +322,8 @@ paths: Query event logs generated by vechain smart contracts. Events are created using the `LOG` opcode in the Ethereum Virtual Machine (EVM). Event logs provide a way to track specific occurrences and state changes within a smart contract. By querying these logs, you can gain insights into the history of events emitted by a particular contract. + + Limited to a max of 1000 entries per query. requestBody: required: true @@ -351,6 +353,8 @@ paths: summary: Query VET transfer events description: | Query VET transfers with a given criteria. + + Limited to a max of 1000 entries per query. requestBody: required: true content: diff --git a/logdb/logdb.go b/logdb/logdb.go index 5d0bf744b..f465efd6e 100644 --- a/logdb/logdb.go +++ b/logdb/logdb.go @@ -19,7 +19,8 @@ import ( ) const ( - refIDQuery = "(SELECT id FROM ref WHERE data=?)" + refIDQuery = "(SELECT id FROM ref WHERE data=?)" + limitThreshold = 1000 ) type LogDB struct { @@ -107,8 +108,14 @@ FROM (%v) e LEFT JOIN ref r7 ON e.topic3 = r7.id LEFT JOIN ref r8 ON e.topic4 = r8.id` - if filter == nil { - return db.queryEvents(ctx, fmt.Sprintf(query, "event")) + if filter == nil { // default query filtering + filter = &EventFilter{ + Options: &Options{ + Offset: 0, + Limit: limitThreshold, + }, + Order: "desc", + } } var ( @@ -146,10 +153,17 @@ FROM (%v) e } // if there is limit option, set order inside subquery - if filter.Options != nil { - subQuery += " LIMIT ?, ?" - args = append(args, filter.Options.Offset, filter.Options.Limit) + subQuery += " LIMIT ?, ?" // all queries are bounded to a max of 1000 results + if filter.Options != nil && filter.Options.Limit > 1000 { + // offset could have been specified + filter.Options.Limit = limitThreshold + } else if filter.Options == nil { + filter.Options = &Options{ + Offset: 0, + Limit: limitThreshold, + } } + args = append(args, filter.Options.Offset, filter.Options.Limit) subQuery = "SELECT e.* FROM (" + subQuery + ") s LEFT JOIN event e ON s.seq = e.seq" @@ -165,8 +179,14 @@ FROM (%v) t LEFT JOIN ref r3 ON t.sender = r3.id LEFT JOIN ref r4 ON t.recipient = r4.id` - if filter == nil { - return db.queryTransfers(ctx, fmt.Sprintf(query, "transfer")) + if filter == nil { // default query filtering + filter = &TransferFilter{ + Options: &Options{ + Offset: 0, + Limit: limitThreshold, + }, + Order: "desc", + } } var ( @@ -203,10 +223,17 @@ FROM (%v) t } // if there is limit option, set order inside subquery - if filter.Options != nil { - subQuery += " LIMIT ?, ?" - args = append(args, filter.Options.Offset, filter.Options.Limit) + subQuery += " LIMIT ?, ?" + if filter.Options != nil && filter.Options.Limit > limitThreshold { + // offset could have been specified + filter.Options.Limit = limitThreshold + } else if filter.Options == nil { + filter.Options = &Options{ + Offset: 0, + Limit: limitThreshold, + } } + args = append(args, filter.Options.Offset, filter.Options.Limit) subQuery = "SELECT e.* FROM (" + subQuery + ") s LEFT JOIN transfer e ON s.seq = e.seq" diff --git a/logdb/logdb_test.go b/logdb/logdb_test.go index 684c245cc..efa4388cc 100644 --- a/logdb/logdb_test.go +++ b/logdb/logdb_test.go @@ -132,7 +132,7 @@ func TestEvents(t *testing.T) { var allEvents eventLogs var allTransfers transferLogs - for i := 0; i < 100; i++ { + for i := 0; i < 2000; i++ { b = new(block.Builder). ParentID(b.Header().ID()). Transaction(newTx()). @@ -187,11 +187,14 @@ func TestEvents(t *testing.T) { arg *logdb.EventFilter want eventLogs }{ - {"query all events", &logdb.EventFilter{}, allEvents}, - {"query all events with nil option", nil, allEvents}, - {"query all events asc", &logdb.EventFilter{Order: logdb.ASC}, allEvents}, - {"query all events desc", &logdb.EventFilter{Order: logdb.DESC}, allEvents.Reverse()}, + {"query all events", &logdb.EventFilter{}, allEvents[:1000]}, + {"query all events with nil option", nil, allEvents.Reverse()[:1000]}, + {"query all events asc", &logdb.EventFilter{Order: logdb.ASC}, allEvents[:1000]}, + {"query all events desc", &logdb.EventFilter{Order: logdb.DESC}, allEvents.Reverse()[:1000]}, {"query all events limit offset", &logdb.EventFilter{Options: &logdb.Options{Offset: 1, Limit: 10}}, allEvents[1:11]}, + {"query all transfers offset", &logdb.EventFilter{Options: &logdb.Options{Offset: 1500, Limit: 10000}, Order: logdb.ASC}, allEvents[1500:2500]}, + {"query all events outsized limit ", &logdb.EventFilter{Options: &logdb.Options{Limit: 2000}}, allEvents[:1000]}, + {"query all events outsized limit offset", &logdb.EventFilter{Options: &logdb.Options{Offset: 2, Limit: 2000}}, allEvents[2:1002]}, {"query all events range", &logdb.EventFilter{Range: &logdb.Range{From: 10, To: 20}}, allEvents.Filter(func(ev *logdb.Event) bool { return ev.BlockNumber >= 10 && ev.BlockNumber <= 20 })}, {"query events with range and desc", &logdb.EventFilter{Range: &logdb.Range{From: 10, To: 20}, Order: logdb.DESC}, allEvents.Filter(func(ev *logdb.Event) bool { return ev.BlockNumber >= 10 && ev.BlockNumber <= 20 }).Reverse()}, {"query events with limit with desc", &logdb.EventFilter{Order: logdb.DESC, Options: &logdb.Options{Limit: 10}}, allEvents.Reverse()[0:10]}, @@ -218,11 +221,14 @@ func TestEvents(t *testing.T) { arg *logdb.TransferFilter want transferLogs }{ - {"query all transfers", &logdb.TransferFilter{}, allTransfers}, - {"query all transfers with nil option", nil, allTransfers}, - {"query all transfers asc", &logdb.TransferFilter{Order: logdb.ASC}, allTransfers}, - {"query all transfers desc", &logdb.TransferFilter{Order: logdb.DESC}, allTransfers.Reverse()}, + {"query all transfers", &logdb.TransferFilter{}, allTransfers[:1000]}, + {"query all transfers with nil option", nil, allTransfers.Reverse()[:1000]}, + {"query all transfers asc", &logdb.TransferFilter{Order: logdb.ASC}, allTransfers[:1000]}, + {"query all transfers desc", &logdb.TransferFilter{Order: logdb.DESC}, allTransfers.Reverse()[:1000]}, {"query all transfers limit offset", &logdb.TransferFilter{Options: &logdb.Options{Offset: 1, Limit: 10}}, allTransfers[1:11]}, + {"query all transfers offset", &logdb.TransferFilter{Options: &logdb.Options{Offset: 1500, Limit: 10000}, Order: logdb.ASC}, allTransfers[1500:2500]}, + {"query all transfers outsized limit ", &logdb.TransferFilter{Options: &logdb.Options{Limit: 2000}}, allTransfers[:1000]}, + {"query all transfers outsized limit offset", &logdb.TransferFilter{Options: &logdb.Options{Offset: 2, Limit: 2000}}, allTransfers[2:1002]}, {"query all transfers range", &logdb.TransferFilter{Range: &logdb.Range{From: 10, To: 20}}, allTransfers.Filter(func(tr *logdb.Transfer) bool { return tr.BlockNumber >= 10 && tr.BlockNumber <= 20 })}, {"query transfers with range and desc", &logdb.TransferFilter{Range: &logdb.Range{From: 10, To: 20}, Order: logdb.DESC}, allTransfers.Filter(func(tr *logdb.Transfer) bool { return tr.BlockNumber >= 10 && tr.BlockNumber <= 20 }).Reverse()}, {"query transfers with limit with desc", &logdb.TransferFilter{Order: logdb.DESC, Options: &logdb.Options{Limit: 10}}, allTransfers.Reverse()[0:10]},