lotus/tvx/drivers/tipset_message_producer.go

202 lines
5.3 KiB
Go
Raw Normal View History

generate test-vectors based on tests from chain-validation project (#181) * Read a subset of filecoin state over the full node API * wip * import export wip * extract actors from message * generate car for any state * library for providing a pruned statetree * test vector schema draft + example 'message' class test vector. * message => messages test vector class. * fixup * wip * use lb.NewBlockstore with ID * fixup lotus-soup, and generate * fix deals * magic params * work on schema / export of test vector * fixup * wip deserialise state tree * pass at building a test case from a message * progress loading / serializing * recreation of ipld nodes * generation of vector creates json * kick off tvx tool. * wip * wip * retain init actor state. * initial test with printed out state * remove testing.T, but keep require and assert libraries * wip refactor state tree plucking. * simplified * removed factories * remove builder.Build ; remove interface - use concrete iface * comment out validateState * remove Validator * remove TestDriverBuilder * remove client * remove box * remove gen * remove factories * remove KeyManager interfafce * moved stuff around * remove ValidationConfig * extract randomness * extract config and key_manager * extract statewrapper * extract applier * rename factories to various * flatten chain-validation package * initial marshal of test vector * do not require schema package * fixup * run all messages tests * better names * run all messages tests * remove Indent setting from JSON encoder for now * refactor, and actually running successfully ;-) * remove irrelevant files; rename extract-msg command. * remove root CID from state_tree object in schema. * add tvx/lotus package; adjust .gitignore. * tidy up command flag management. * add comment. * remove validateState and trackState * remove xerrors * remove NewVM * remove commented out RootCID sets * enable more tests * add all `message_application` tests * delete all.json * update Message struct * fix message serialization * support multiple messages * gofmt * remove custom Message and SignedMessage types * update tests with gzip and adhere to new schema for compressed CAR * improved iface for Marshal * update Validation * remove test-suites and utils * better names for chain. methods * go mod tidy * remove top-level dummyT Co-authored-by: Will Scott <will@cypherpunk.email> Co-authored-by: Raúl Kripalani <raul@protocol.ai>
2020-08-05 17:40:09 +00:00
package drivers
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/runtime/exitcode"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
vtypes "github.com/filecoin-project/oni/tvx/chain/types"
)
type TipSetMessageBuilder struct {
driver *TestDriver
bbs []*BlockBuilder
}
func NewTipSetMessageBuilder(testDriver *TestDriver) *TipSetMessageBuilder {
return &TipSetMessageBuilder{
driver: testDriver,
bbs: nil,
}
}
func (t *TipSetMessageBuilder) WithBlockBuilder(bb *BlockBuilder) *TipSetMessageBuilder {
t.bbs = append(t.bbs, bb)
return t
}
func (t *TipSetMessageBuilder) Apply() vtypes.ApplyTipSetResult {
result := t.apply()
t.Clear()
return result
}
func (t *TipSetMessageBuilder) ApplyAndValidate() vtypes.ApplyTipSetResult {
result := t.apply()
t.validateResult(result)
t.Clear()
return result
}
func (tb *TipSetMessageBuilder) apply() vtypes.ApplyTipSetResult {
var blks []vtypes.BlockMessagesInfo
for _, b := range tb.bbs {
blks = append(blks, b.build())
}
result, err := tb.driver.applier.ApplyTipSetMessages(tb.driver.ExeCtx.Epoch, blks, tb.driver.Randomness())
require.NoError(t, err)
//t.driver.StateTracker.TrackResult(result)
return result
}
func (tb *TipSetMessageBuilder) validateResult(result vtypes.ApplyTipSetResult) {
expected := []ExpectedResult{}
for _, b := range tb.bbs {
expected = append(expected, b.expectedResults...)
}
if len(result.Receipts) > len(expected) {
t.Fatalf("ApplyTipSetMessages returned more result than expected. Expected: %d, Actual: %d", len(expected), len(result.Receipts))
return
}
for i := range result.Receipts {
if tb.driver.Config.ValidateExitCode() {
assert.Equal(t, expected[i].ExitCode, result.Receipts[i].ExitCode, "Message Number: %d Expected ExitCode: %s Actual ExitCode: %s", i, expected[i].ExitCode.Error(), result.Receipts[i].ExitCode.Error())
}
if tb.driver.Config.ValidateReturnValue() {
assert.Equal(t, expected[i].ReturnVal, result.Receipts[i].ReturnValue, "Message Number: %d Expected ReturnValue: %v Actual ReturnValue: %v", i, expected[i].ReturnVal, result.Receipts[i].ReturnValue)
}
}
}
func (t *TipSetMessageBuilder) Clear() {
t.bbs = nil
}
type BlockBuilder struct {
TD *TestDriver
miner address.Address
ticketCount int64
secpMsgs []*types.SignedMessage
blsMsgs []*types.Message
expectedResults []ExpectedResult
}
type ExpectedResult struct {
ExitCode exitcode.ExitCode
ReturnVal []byte
}
func NewBlockBuilder(td *TestDriver, miner address.Address) *BlockBuilder {
return &BlockBuilder{
TD: td,
miner: miner,
ticketCount: 1,
secpMsgs: nil,
blsMsgs: nil,
expectedResults: nil,
}
}
func (bb *BlockBuilder) addResult(code exitcode.ExitCode, retval []byte) {
bb.expectedResults = append(bb.expectedResults, ExpectedResult{
ExitCode: code,
ReturnVal: retval,
})
}
func (bb *BlockBuilder) WithBLSMessageOk(blsMsg *types.Message) *BlockBuilder {
bb.blsMsgs = append(bb.blsMsgs, blsMsg)
bb.addResult(exitcode.Ok, EmptyReturnValue)
return bb
}
func (bb *BlockBuilder) WithBLSMessageDropped(blsMsg *types.Message) *BlockBuilder {
bb.blsMsgs = append(bb.blsMsgs, blsMsg)
return bb
}
func (bb *BlockBuilder) WithBLSMessageAndCode(bm *types.Message, code exitcode.ExitCode) *BlockBuilder {
bb.blsMsgs = append(bb.blsMsgs, bm)
bb.addResult(code, EmptyReturnValue)
return bb
}
func (bb *BlockBuilder) WithBLSMessageAndRet(bm *types.Message, retval []byte) *BlockBuilder {
bb.blsMsgs = append(bb.blsMsgs, bm)
bb.addResult(exitcode.Ok, retval)
return bb
}
func (bb *BlockBuilder) WithSECPMessageAndCode(bm *types.Message, code exitcode.ExitCode) *BlockBuilder {
secpMsg := bb.toSignedMessage(bm)
bb.secpMsgs = append(bb.secpMsgs, secpMsg)
bb.addResult(code, EmptyReturnValue)
return bb
}
func (bb *BlockBuilder) WithSECPMessageAndRet(bm *types.Message, retval []byte) *BlockBuilder {
secpMsg := bb.toSignedMessage(bm)
bb.secpMsgs = append(bb.secpMsgs, secpMsg)
bb.addResult(exitcode.Ok, retval)
return bb
}
func (bb *BlockBuilder) WithSECPMessageOk(bm *types.Message) *BlockBuilder {
secpMsg := bb.toSignedMessage(bm)
bb.secpMsgs = append(bb.secpMsgs, secpMsg)
bb.addResult(exitcode.Ok, EmptyReturnValue)
return bb
}
func (bb *BlockBuilder) WithSECPMessageDropped(bm *types.Message) *BlockBuilder {
secpMsg := bb.toSignedMessage(bm)
bb.secpMsgs = append(bb.secpMsgs, secpMsg)
return bb
}
func (bb *BlockBuilder) WithTicketCount(count int64) *BlockBuilder {
bb.ticketCount = count
return bb
}
func (bb *BlockBuilder) toSignedMessage(m *types.Message) *types.SignedMessage {
from := m.From
if from.Protocol() == address.ID {
from = bb.TD.ActorPubKey(from)
}
if from.Protocol() != address.SECP256K1 {
t.Fatalf("Invalid address for SECP signature, address protocol: %v", from.Protocol())
}
raw, err := m.Serialize()
require.NoError(t, err)
sig, err := bb.TD.Wallet().Sign(from, raw)
require.NoError(t, err)
return &types.SignedMessage{
Message: *m,
Signature: sig,
}
}
func (bb *BlockBuilder) build() vtypes.BlockMessagesInfo {
return vtypes.BlockMessagesInfo{
BLSMessages: bb.blsMsgs,
SECPMessages: bb.secpMsgs,
Miner: bb.miner,
TicketCount: bb.ticketCount,
}
}