87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
|
package conformance
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/filecoin-project/go-state-types/abi"
|
||
|
"github.com/filecoin-project/go-state-types/crypto"
|
||
|
|
||
|
"github.com/filecoin-project/lotus/api"
|
||
|
"github.com/filecoin-project/lotus/chain/types"
|
||
|
"github.com/filecoin-project/lotus/chain/vm"
|
||
|
"github.com/filecoin-project/test-vectors/schema"
|
||
|
)
|
||
|
|
||
|
type RecordingRand struct {
|
||
|
reporter Reporter
|
||
|
api api.FullNode
|
||
|
|
||
|
lk sync.Mutex
|
||
|
recorded schema.Randomness
|
||
|
}
|
||
|
|
||
|
var _ vm.Rand = (*RecordingRand)(nil)
|
||
|
|
||
|
// NewRecordingRand returns a vm.Rand implementation that proxies calls to a
|
||
|
// full Lotus node via JSON-RPC, and records matching rules and responses so
|
||
|
// they can later be embedded in test vectors.
|
||
|
func NewRecordingRand(reporter Reporter, api api.FullNode) *RecordingRand {
|
||
|
return &RecordingRand{reporter: reporter, api: api}
|
||
|
}
|
||
|
|
||
|
func (r *RecordingRand) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||
|
ret, err := r.api.ChainGetRandomnessFromTickets(ctx, types.EmptyTSK, pers, round, entropy)
|
||
|
if err != nil {
|
||
|
return ret, err
|
||
|
}
|
||
|
|
||
|
r.reporter.Logf("fetched and recorded chain randomness for: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
|
||
|
|
||
|
match := schema.RandomnessMatch{
|
||
|
On: schema.RandomnessRule{
|
||
|
Kind: schema.RandomnessChain,
|
||
|
DomainSeparationTag: int64(pers),
|
||
|
Epoch: int64(round),
|
||
|
Entropy: entropy,
|
||
|
},
|
||
|
Return: []byte(ret),
|
||
|
}
|
||
|
r.lk.Lock()
|
||
|
r.recorded = append(r.recorded, match)
|
||
|
r.lk.Unlock()
|
||
|
|
||
|
return ret, err
|
||
|
}
|
||
|
|
||
|
func (r *RecordingRand) GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||
|
ret, err := r.api.ChainGetRandomnessFromBeacon(ctx, types.EmptyTSK, pers, round, entropy)
|
||
|
if err != nil {
|
||
|
return ret, err
|
||
|
}
|
||
|
|
||
|
r.reporter.Logf("fetched and recorded beacon randomness for: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
|
||
|
|
||
|
match := schema.RandomnessMatch{
|
||
|
On: schema.RandomnessRule{
|
||
|
Kind: schema.RandomnessBeacon,
|
||
|
DomainSeparationTag: int64(pers),
|
||
|
Epoch: int64(round),
|
||
|
Entropy: entropy,
|
||
|
},
|
||
|
Return: []byte(ret),
|
||
|
}
|
||
|
r.lk.Lock()
|
||
|
r.recorded = append(r.recorded, match)
|
||
|
r.lk.Unlock()
|
||
|
|
||
|
return ret, err
|
||
|
}
|
||
|
|
||
|
func (r *RecordingRand) Recorded() schema.Randomness {
|
||
|
r.lk.Lock()
|
||
|
defer r.lk.Unlock()
|
||
|
|
||
|
return r.recorded
|
||
|
}
|