-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
R4R: Simulation Queued Time Operations #2348
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -98,13 +98,14 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp, | |
request := RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, pastSigningValidators, event, header) | ||
// These are operations which have been queued by previous operations | ||
operationQueue := make(map[int][]Operation) | ||
timeOperationQueue := []FutureOperation{} | ||
var blockLogBuilders []*strings.Builder | ||
|
||
if testingMode { | ||
blockLogBuilders = make([]*strings.Builder, numBlocks) | ||
} | ||
displayLogs := logPrinter(testingMode, blockLogBuilders) | ||
blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, numBlocks, displayLogs) | ||
blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, timeOperationQueue, numBlocks, displayLogs) | ||
if !testingMode { | ||
b.ResetTimer() | ||
} else { | ||
|
@@ -140,8 +141,10 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp, | |
// Run queued operations. Ignores blocksize if blocksize is too small | ||
numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), tb, r, app, ctx, keys, logWriter, displayLogs, event) | ||
thisBlockSize -= numQueuedOpsRan | ||
numQueuedTimeOpsRan := runQueuedTimeOperations(timeOperationQueue, header.Time, tb, r, app, ctx, keys, logWriter, displayLogs, event) | ||
thisBlockSize -= numQueuedTimeOpsRan | ||
operations := blockSimulator(thisBlockSize, r, app, ctx, keys, header, logWriter) | ||
opCount += operations + numQueuedOpsRan | ||
opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan | ||
|
||
res := app.EndBlock(abci.RequestEndBlock{}) | ||
header.Height++ | ||
|
@@ -173,7 +176,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp, | |
|
||
// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize | ||
// memory overhead | ||
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []WeightedOperation, operationQueue map[int][]Operation, totalNumBlocks int, displayLogs func()) func( | ||
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []WeightedOperation, operationQueue map[int][]Operation, timeOperationQueue []FutureOperation, totalNumBlocks int, displayLogs func()) func( | ||
blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, header abci.Header, logWriter func(string)) (opCount int) { | ||
totalOpWeight := 0 | ||
for i := 0; i < len(ops); i++ { | ||
|
@@ -200,7 +203,7 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event f | |
} | ||
logWriter(logUpdate) | ||
|
||
queueOperations(operationQueue, futureOps) | ||
queueOperations(operationQueue, timeOperationQueue, futureOps) | ||
if testingMode { | ||
if onOperation { | ||
assertAllInvariants(t, app, invariants, displayLogs) | ||
|
@@ -239,15 +242,22 @@ func getBlockSize(r *rand.Rand, blockSize int) int { | |
} | ||
|
||
// adds all future operations into the operation queue. | ||
func queueOperations(queuedOperations map[int][]Operation, futureOperations []FutureOperation) { | ||
func queueOperations(queuedOperations map[int][]Operation, queuedTimeOperations []FutureOperation, futureOperations []FutureOperation) { | ||
if futureOperations == nil { | ||
return | ||
} | ||
for _, futureOp := range futureOperations { | ||
if val, ok := queuedOperations[futureOp.BlockHeight]; ok { | ||
queuedOperations[futureOp.BlockHeight] = append(val, futureOp.Op) | ||
if futureOp.BlockHeight != 0 { | ||
if val, ok := queuedOperations[futureOp.BlockHeight]; ok { | ||
queuedOperations[futureOp.BlockHeight] = append(val, futureOp.Op) | ||
} else { | ||
queuedOperations[futureOp.BlockHeight] = []Operation{futureOp.Op} | ||
} | ||
} else { | ||
queuedOperations[futureOp.BlockHeight] = []Operation{futureOp.Op} | ||
index := sort.Search(len(queuedTimeOperations), func(i int) bool { return queuedTimeOperations[i].BlockTime.After(futureOp.BlockTime) }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we have to do a search, can you make a TODO comment to make the queued time ops a sorted data structure? (This can then be addressed #postlaunch or if it bottlenecks the simulation) Right now we have to copy all the time ops on insertion / deletion, which is an O(N) operation. |
||
queuedTimeOperations = append(queuedTimeOperations, FutureOperation{}) | ||
copy(queuedTimeOperations[index+1:], queuedTimeOperations[index:]) | ||
queuedTimeOperations[index] = futureOp | ||
} | ||
} | ||
} | ||
|
@@ -274,6 +284,27 @@ func runQueuedOperations(queueOperations map[int][]Operation, height int, tb tes | |
return 0 | ||
} | ||
|
||
// nolint: errcheck | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do want this passing errcheck though. Is there a specific line/error your trying to skip? |
||
func runQueuedTimeOperations(queueOperations []FutureOperation, currentTime time.Time, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, | ||
privKeys []crypto.PrivKey, logWriter func(string), displayLogs func(), event func(string)) (numOpsRan int) { | ||
|
||
numOpsRan = 0 | ||
for len(queueOperations) > 0 && currentTime.After(queueOperations[0].BlockTime) { | ||
// For now, queued operations cannot queue more operations. | ||
// If a need arises for us to support queued messages to queue more messages, this can | ||
// be changed. | ||
logUpdate, _, err := queueOperations[0].Op(r, app, ctx, privKeys, event) | ||
logWriter(logUpdate) | ||
if err != nil { | ||
displayLogs() | ||
tb.FailNow() | ||
} | ||
queueOperations = queueOperations[1:] | ||
numOpsRan++ | ||
} | ||
return numOpsRan | ||
} | ||
|
||
func getKeys(validators map[string]mockValidator) []string { | ||
keys := make([]string, len(validators)) | ||
i := 0 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you combine the lines subtracting the block size?