Merge pull request #11167 from filecoin-project/asr/randomness

feat: refactor: return randomness base to FVM without hashing
This commit is contained in:
Aayush Rajasekaran 2023-08-22 12:15:24 -04:00 committed by GitHub
commit 7491956197
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 371 additions and 160 deletions

View File

@ -641,6 +641,11 @@ type FullNode interface {
// StateGetRandomnessFromBeacon is used to sample the beacon for randomness.
StateGetRandomnessFromBeacon(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) //perm:read
// StateGetRandomnessDigestFromTickets. is used to sample the chain for randomness.
StateGetRandomnessDigestFromTickets(ctx context.Context, randEpoch abi.ChainEpoch, tsk types.TipSetKey) (abi.Randomness, error) //perm:read
// StateGetRandomnessDigestFromBeacon is used to sample the beacon for randomness.
StateGetRandomnessDigestFromBeacon(ctx context.Context, randEpoch abi.ChainEpoch, tsk types.TipSetKey) (abi.Randomness, error) //perm:read
// StateGetBeaconEntry returns the beacon entry for the given filecoin epoch. If
// the entry has not yet been produced, the call will block until the entry
// becomes available

View File

@ -3263,6 +3263,36 @@ func (mr *MockFullNodeMockRecorder) StateGetNetworkParams(arg0 interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetNetworkParams", reflect.TypeOf((*MockFullNode)(nil).StateGetNetworkParams), arg0)
}
// StateGetRandomnessDigestFromBeacon mocks base method.
func (m *MockFullNode) StateGetRandomnessDigestFromBeacon(arg0 context.Context, arg1 abi.ChainEpoch, arg2 types.TipSetKey) (abi.Randomness, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateGetRandomnessDigestFromBeacon", arg0, arg1, arg2)
ret0, _ := ret[0].(abi.Randomness)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateGetRandomnessDigestFromBeacon indicates an expected call of StateGetRandomnessDigestFromBeacon.
func (mr *MockFullNodeMockRecorder) StateGetRandomnessDigestFromBeacon(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetRandomnessDigestFromBeacon", reflect.TypeOf((*MockFullNode)(nil).StateGetRandomnessDigestFromBeacon), arg0, arg1, arg2)
}
// StateGetRandomnessDigestFromTickets mocks base method.
func (m *MockFullNode) StateGetRandomnessDigestFromTickets(arg0 context.Context, arg1 abi.ChainEpoch, arg2 types.TipSetKey) (abi.Randomness, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "StateGetRandomnessDigestFromTickets", arg0, arg1, arg2)
ret0, _ := ret[0].(abi.Randomness)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// StateGetRandomnessDigestFromTickets indicates an expected call of StateGetRandomnessDigestFromTickets.
func (mr *MockFullNodeMockRecorder) StateGetRandomnessDigestFromTickets(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGetRandomnessDigestFromTickets", reflect.TypeOf((*MockFullNode)(nil).StateGetRandomnessDigestFromTickets), arg0, arg1, arg2)
}
// StateGetRandomnessFromBeacon mocks base method.
func (m *MockFullNode) StateGetRandomnessFromBeacon(arg0 context.Context, arg1 crypto.DomainSeparationTag, arg2 abi.ChainEpoch, arg3 []byte, arg4 types.TipSetKey) (abi.Randomness, error) {
m.ctrl.T.Helper()

View File

@ -494,6 +494,10 @@ type FullNodeMethods struct {
StateGetNetworkParams func(p0 context.Context) (*NetworkParams, error) `perm:"read"`
StateGetRandomnessDigestFromBeacon func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (abi.Randomness, error) `perm:"read"`
StateGetRandomnessDigestFromTickets func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (abi.Randomness, error) `perm:"read"`
StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"`
StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"`
@ -3432,6 +3436,28 @@ func (s *FullNodeStub) StateGetNetworkParams(p0 context.Context) (*NetworkParams
return nil, ErrNotSupported
}
func (s *FullNodeStruct) StateGetRandomnessDigestFromBeacon(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (abi.Randomness, error) {
if s.Internal.StateGetRandomnessDigestFromBeacon == nil {
return *new(abi.Randomness), ErrNotSupported
}
return s.Internal.StateGetRandomnessDigestFromBeacon(p0, p1, p2)
}
func (s *FullNodeStub) StateGetRandomnessDigestFromBeacon(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (abi.Randomness, error) {
return *new(abi.Randomness), ErrNotSupported
}
func (s *FullNodeStruct) StateGetRandomnessDigestFromTickets(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (abi.Randomness, error) {
if s.Internal.StateGetRandomnessDigestFromTickets == nil {
return *new(abi.Randomness), ErrNotSupported
}
return s.Internal.StateGetRandomnessDigestFromTickets(p0, p1, p2)
}
func (s *FullNodeStub) StateGetRandomnessDigestFromTickets(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (abi.Randomness, error) {
return *new(abi.Randomness), ErrNotSupported
}
func (s *FullNodeStruct) StateGetRandomnessFromBeacon(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) {
if s.Internal.StateGetRandomnessFromBeacon == nil {
return *new(abi.Randomness), ErrNotSupported

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -80,7 +80,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
pstate cid.Cid,
bms []FilecoinBlockMessages,
epoch abi.ChainEpoch,
r vm.Rand,
r rand.Rand,
em stmgr.ExecMonitor,
vmTracing bool,
baseFee abi.TokenAmount,

View File

@ -201,7 +201,7 @@ func (filec *FilecoinEC) ValidateBlock(ctx context.Context, b *types.FullBlock)
return xerrors.Errorf("failed to marshal miner address to cbor: %w", err)
}
vrfBase, err := rand.DrawRandomness(rBeacon.Data, crypto.DomainSeparationTag_ElectionProofProduction, h.Height, buf.Bytes())
vrfBase, err := rand.DrawRandomnessFromBase(rBeacon.Data, crypto.DomainSeparationTag_ElectionProofProduction, h.Height, buf.Bytes())
if err != nil {
return xerrors.Errorf("could not draw randomness: %w", err)
}
@ -267,7 +267,7 @@ func (filec *FilecoinEC) ValidateBlock(ctx context.Context, b *types.FullBlock)
beaconBase = h.BeaconEntries[len(h.BeaconEntries)-1]
}
vrfBase, err := rand.DrawRandomness(beaconBase.Data, crypto.DomainSeparationTag_TicketProduction, h.Height-build.TicketRandomnessLookback, buf.Bytes())
vrfBase, err := rand.DrawRandomnessFromBase(beaconBase.Data, crypto.DomainSeparationTag_TicketProduction, h.Height-build.TicketRandomnessLookback, buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to compute vrf base for ticket: %w", err)
}
@ -345,7 +345,7 @@ func (filec *FilecoinEC) VerifyWinningPoStProof(ctx context.Context, nv network.
rbase = h.BeaconEntries[len(h.BeaconEntries)-1]
}
rand, err := rand.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, h.Height, buf.Bytes())
rand, err := rand.DrawRandomnessFromBase(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, h.Height, buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying winning post proof: %w", err)
}

View File

@ -376,7 +376,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
buf.Write(pts.MinTicket().VRFProof)
}
ticketRand, err := rand.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes())
ticketRand, err := rand.DrawRandomnessFromBase(rbase.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes())
if err != nil {
return nil, nil, nil, err
}
@ -647,7 +647,7 @@ func IsRoundWinner(ctx context.Context, round abi.ChainEpoch,
return nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
}
electionRand, err := rand.DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf.Bytes())
electionRand, err := rand.DrawRandomnessFromBase(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf.Bytes())
if err != nil {
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
}

View File

@ -43,6 +43,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/consensus"
lrand "github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@ -590,19 +591,21 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sys vm.Syscal
return c, nil
}
var _ lrand.Rand = new(fakeRand)
// TODO: copied from actors test harness, deduplicate or remove from here
type fakeRand struct{}
func (fr *fakeRand) GetChainRandomness(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (fr *fakeRand) GetChainRandomness(ctx context.Context, randEpoch abi.ChainEpoch) ([32]byte, error) {
out := make([]byte, 32)
_, _ = rand.New(rand.NewSource(int64(randEpoch * 1000))).Read(out) //nolint
return out, nil
return *(*[32]byte)(out), nil
}
func (fr *fakeRand) GetBeaconRandomness(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (fr *fakeRand) GetBeaconRandomness(ctx context.Context, randEpoch abi.ChainEpoch) ([32]byte, error) {
out := make([]byte, 32)
_, _ = rand.New(rand.NewSource(int64(randEpoch))).Read(out) //nolint
return out, nil
return *(*[32]byte)(out), nil
}
func currentTotalPower(ctx context.Context, vm vm.Interface, maddr address.Address) (*power0.CurrentTotalPowerReturn, error) {

View File

@ -17,18 +17,20 @@ import (
"github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
var log = logging.Logger("rand")
func DrawRandomness(rbase []byte, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func DrawRandomnessFromBase(rbase []byte, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
return DrawRandomnessFromDigest(blake2b.Sum256(rbase), pers, round, entropy)
}
func DrawRandomnessFromDigest(digest [32]byte, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
h := blake2b.New256()
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
return nil, xerrors.Errorf("deriving randomness: %w", err)
}
VRFDigest := blake2b.Sum256(rbase)
_, err := h.Write(VRFDigest[:])
_, err := h.Write(digest[:])
if err != nil {
return nil, xerrors.Errorf("hashing VRFDigest: %w", err)
}
@ -70,18 +72,18 @@ func (sr *stateRand) GetBeaconRandomnessTipset(ctx context.Context, round abi.Ch
return randTs, nil
}
func (sr *stateRand) getChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte, lookback bool) ([]byte, error) {
func (sr *stateRand) getChainRandomness(ctx context.Context, round abi.ChainEpoch, lookback bool) ([32]byte, error) {
_, span := trace.StartSpan(ctx, "store.GetChainRandomness")
defer span.End()
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
ts, err := sr.cs.LoadTipSet(ctx, types.NewTipSetKey(sr.blks...))
if err != nil {
return nil, err
return [32]byte{}, err
}
if round > ts.Height() {
return nil, xerrors.Errorf("cannot draw randomness from the future")
return [32]byte{}, xerrors.Errorf("cannot draw randomness from the future")
}
searchHeight := round
@ -91,14 +93,10 @@ func (sr *stateRand) getChainRandomness(ctx context.Context, pers crypto.DomainS
randTs, err := sr.cs.GetTipsetByHeight(ctx, searchHeight, ts, lookback)
if err != nil {
return nil, err
return [32]byte{}, err
}
mtb := randTs.MinTicketBlock()
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(mtb.Ticket.VRFProof, pers, round, entropy)
return blake2b.Sum256(randTs.MinTicketBlock().Ticket.VRFProof), nil
}
type NetworkVersionGetter func(context.Context, abi.ChainEpoch) network.Version
@ -110,7 +108,12 @@ type stateRand struct {
networkVersionGetter NetworkVersionGetter
}
func NewStateRand(cs *store.ChainStore, blks []cid.Cid, b beacon.Schedule, networkVersionGetter NetworkVersionGetter) vm.Rand {
type Rand interface {
GetChainRandomness(ctx context.Context, round abi.ChainEpoch) ([32]byte, error)
GetBeaconRandomness(ctx context.Context, round abi.ChainEpoch) ([32]byte, error)
}
func NewStateRand(cs *store.ChainStore, blks []cid.Cid, b beacon.Schedule, networkVersionGetter NetworkVersionGetter) Rand {
return &stateRand{
cs: cs,
blks: blks,
@ -120,76 +123,102 @@ func NewStateRand(cs *store.ChainStore, blks []cid.Cid, b beacon.Schedule, netwo
}
// network v0-12
func (sr *stateRand) getBeaconRandomnessV1(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (sr *stateRand) getBeaconRandomnessV1(ctx context.Context, round abi.ChainEpoch) ([32]byte, error) {
randTs, err := sr.GetBeaconRandomnessTipset(ctx, round, true)
if err != nil {
return nil, err
return [32]byte{}, err
}
be, err := sr.cs.GetLatestBeaconEntry(ctx, randTs)
if err != nil {
return nil, err
return [32]byte{}, err
}
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(be.Data, pers, round, entropy)
return blake2b.Sum256(be.Data), nil
}
// network v13
func (sr *stateRand) getBeaconRandomnessV2(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (sr *stateRand) getBeaconRandomnessV2(ctx context.Context, round abi.ChainEpoch) ([32]byte, error) {
randTs, err := sr.GetBeaconRandomnessTipset(ctx, round, false)
if err != nil {
return nil, err
return [32]byte{}, err
}
be, err := sr.cs.GetLatestBeaconEntry(ctx, randTs)
if err != nil {
return nil, err
return [32]byte{}, err
}
// if at (or just past -- for null epochs) appropriate epoch
// or at genesis (works for negative epochs)
return DrawRandomness(be.Data, pers, round, entropy)
return blake2b.Sum256(be.Data), nil
}
// network v14 and on
func (sr *stateRand) getBeaconRandomnessV3(ctx context.Context, pers crypto.DomainSeparationTag, filecoinEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (sr *stateRand) getBeaconRandomnessV3(ctx context.Context, filecoinEpoch abi.ChainEpoch) ([32]byte, error) {
if filecoinEpoch < 0 {
return sr.getBeaconRandomnessV2(ctx, pers, filecoinEpoch, entropy)
return sr.getBeaconRandomnessV2(ctx, filecoinEpoch)
}
be, err := sr.extractBeaconEntryForEpoch(ctx, filecoinEpoch)
if err != nil {
log.Errorf("failed to get beacon entry as expected: %s", err)
return nil, err
return [32]byte{}, err
}
return DrawRandomness(be.Data, pers, filecoinEpoch, entropy)
return blake2b.Sum256(be.Data), nil
}
func (sr *stateRand) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, filecoinEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (sr *stateRand) GetChainRandomness(ctx context.Context, filecoinEpoch abi.ChainEpoch) ([32]byte, error) {
nv := sr.networkVersionGetter(ctx, filecoinEpoch)
if nv >= network.Version13 {
return sr.getChainRandomness(ctx, pers, filecoinEpoch, entropy, false)
return sr.getChainRandomness(ctx, filecoinEpoch, false)
}
return sr.getChainRandomness(ctx, pers, filecoinEpoch, entropy, true)
return sr.getChainRandomness(ctx, filecoinEpoch, true)
}
func (sr *stateRand) GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, filecoinEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (sr *stateRand) GetBeaconRandomness(ctx context.Context, filecoinEpoch abi.ChainEpoch) ([32]byte, error) {
nv := sr.networkVersionGetter(ctx, filecoinEpoch)
if nv >= network.Version14 {
return sr.getBeaconRandomnessV3(ctx, pers, filecoinEpoch, entropy)
return sr.getBeaconRandomnessV3(ctx, filecoinEpoch)
} else if nv == network.Version13 {
return sr.getBeaconRandomnessV2(ctx, pers, filecoinEpoch, entropy)
return sr.getBeaconRandomnessV2(ctx, filecoinEpoch)
} else {
return sr.getBeaconRandomnessV1(ctx, pers, filecoinEpoch, entropy)
return sr.getBeaconRandomnessV1(ctx, filecoinEpoch)
}
}
func (sr *stateRand) DrawChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, filecoinEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
digest, err := sr.GetChainRandomness(ctx, filecoinEpoch)
if err != nil {
return nil, xerrors.Errorf("failed to get chain randomness: %w", err)
}
ret, err := DrawRandomnessFromDigest(digest, pers, filecoinEpoch, entropy)
if err != nil {
return nil, xerrors.Errorf("failed to draw chain randomness: %w", err)
}
return ret, nil
}
func (sr *stateRand) DrawBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, filecoinEpoch abi.ChainEpoch, entropy []byte) ([]byte, error) {
digest, err := sr.GetBeaconRandomness(ctx, filecoinEpoch)
if err != nil {
return nil, xerrors.Errorf("failed to get beacon randomness: %w", err)
}
ret, err := DrawRandomnessFromDigest(digest, pers, filecoinEpoch, entropy)
if err != nil {
return nil, xerrors.Errorf("failed to draw beacon randomness: %w", err)
}
return ret, nil
}
func (sr *stateRand) extractBeaconEntryForEpoch(ctx context.Context, filecoinEpoch abi.ChainEpoch) (*types.BeaconEntry, error) {
randTs, err := sr.GetBeaconRandomnessTipset(ctx, filecoinEpoch, false)
if err != nil {

View File

@ -69,7 +69,7 @@ func TestNullRandomnessV1(t *testing.T) {
}
//stm: @BLOCKCHAIN_RAND_DRAW_RANDOMNESS_01
rand2, err := rand.DrawRandomness(resp.Entry.Data, pers, randEpoch, entropy)
rand2, err := rand.DrawRandomnessFromBase(resp.Entry.Data, pers, randEpoch, entropy)
if err != nil {
t.Fatal(err)
}
@ -148,8 +148,8 @@ func TestNullRandomnessV2(t *testing.T) {
}
//stm: @BLOCKCHAIN_RAND_DRAW_RANDOMNESS_01, @BLOCKCHAIN_RAND_EXTRACT_BEACON_ENTRY_FOR_EPOCH_01, @BLOCKCHAIN_RAND_GET_BEACON_RANDOMNESS_TIPSET_03
// note that the randEpoch passed to DrawRandomness is still randEpoch (not the latest ts height)
rand2, err := rand.DrawRandomness(resp.Entry.Data, pers, randEpoch, entropy)
// note that the randEpoch passed to DrawRandomnessFromBase is still randEpoch (not the latest ts height)
rand2, err := rand.DrawRandomnessFromBase(resp.Entry.Data, pers, randEpoch, entropy)
if err != nil {
t.Fatal(err)
}
@ -232,7 +232,7 @@ func TestNullRandomnessV3(t *testing.T) {
}
//stm: @BLOCKCHAIN_RAND_DRAW_RANDOMNESS_01
rand2, err := rand.DrawRandomness(resp.Entry.Data, pers, randEpoch, entropy)
rand2, err := rand.DrawRandomnessFromBase(resp.Entry.Data, pers, randEpoch, entropy)
if err != nil {
t.Fatal(err)
}

View File

@ -355,7 +355,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
return nil, xerrors.Errorf("failed to marshal miner address: %w", err)
}
prand, err := rand.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
prand, err := rand.DrawRandomnessFromBase(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
if err != nil {
return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err)
}

View File

@ -509,7 +509,17 @@ func (sm *StateManager) GetRandomnessFromBeacon(ctx context.Context, personaliza
r := rand.NewStateRand(sm.ChainStore(), pts.Cids(), sm.beacon, sm.GetNetworkVersion)
return r.GetBeaconRandomness(ctx, personalization, randEpoch, entropy)
digest, err := r.GetBeaconRandomness(ctx, randEpoch)
if err != nil {
return nil, xerrors.Errorf("getting beacon randomness: %w", err)
}
ret, err := rand.DrawRandomnessFromDigest(digest, personalization, randEpoch, entropy)
if err != nil {
return nil, xerrors.Errorf("drawing beacon randomness: %w", err)
}
return ret, nil
}
@ -521,5 +531,38 @@ func (sm *StateManager) GetRandomnessFromTickets(ctx context.Context, personaliz
r := rand.NewStateRand(sm.ChainStore(), pts.Cids(), sm.beacon, sm.GetNetworkVersion)
return r.GetChainRandomness(ctx, personalization, randEpoch, entropy)
digest, err := r.GetChainRandomness(ctx, randEpoch)
if err != nil {
return nil, xerrors.Errorf("getting chain randomness: %w", err)
}
ret, err := rand.DrawRandomnessFromDigest(digest, personalization, randEpoch, entropy)
if err != nil {
return nil, xerrors.Errorf("drawing chain randomness: %w", err)
}
return ret, nil
}
func (sm *StateManager) GetRandomnessDigestFromBeacon(ctx context.Context, randEpoch abi.ChainEpoch, tsk types.TipSetKey) ([32]byte, error) {
pts, err := sm.ChainStore().GetTipSetFromKey(ctx, tsk)
if err != nil {
return [32]byte{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
r := rand.NewStateRand(sm.ChainStore(), pts.Cids(), sm.beacon, sm.GetNetworkVersion)
return r.GetBeaconRandomness(ctx, randEpoch)
}
func (sm *StateManager) GetRandomnessDigestFromTickets(ctx context.Context, randEpoch abi.ChainEpoch, tsk types.TipSetKey) ([32]byte, error) {
pts, err := sm.ChainStore().LoadTipSet(ctx, tsk)
if err != nil {
return [32]byte{}, xerrors.Errorf("loading tipset key: %w", err)
}
r := rand.NewStateRand(sm.ChainStore(), pts.Cids(), sm.beacon, sm.GetNetworkVersion)
return r.GetChainRandomness(ctx, randEpoch)
}

View File

@ -33,6 +33,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/policy"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs"
@ -43,7 +44,7 @@ var _ Interface = (*FVM)(nil)
var _ ffi_cgo.Externs = (*FvmExtern)(nil)
type FvmExtern struct {
Rand
rand.Rand
blockstore.Blockstore
epoch abi.ChainEpoch
lbState LookbackStateGetter

View File

@ -33,6 +33,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
)
@ -229,21 +230,35 @@ func (rt *Runtime) GetActorCodeCID(addr address.Address) (ret cid.Cid, ok bool)
}
func (rt *Runtime) GetRandomnessFromTickets(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness {
res, err := rt.vm.rand.GetChainRandomness(rt.ctx, personalization, randEpoch, entropy)
digest, err := rt.vm.rand.GetChainRandomness(rt.ctx, randEpoch)
if err != nil {
panic(aerrors.Fatalf("could not get ticket randomness: %s", err))
}
return res
ret, err := rand.DrawRandomnessFromDigest(digest, personalization, randEpoch, entropy)
if err != nil {
panic(aerrors.Fatalf("could not draw ticket randomness: %s", err))
}
return ret
}
func (rt *Runtime) GetRandomnessFromBeacon(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness {
res, err := rt.vm.rand.GetBeaconRandomness(rt.ctx, personalization, randEpoch, entropy)
digest, err := rt.vm.rand.GetBeaconRandomness(rt.ctx, randEpoch)
if err != nil {
panic(aerrors.Fatalf("could not get beacon randomness: %s", err))
panic(aerrors.Fatalf("could not get ticket randomness: %s", err))
}
return res
ret, err := rand.DrawRandomnessFromDigest(digest, personalization, randEpoch, entropy)
if err != nil {
panic(aerrors.Fatalf("could not draw ticket randomness: %s", err))
}
return ret
}
func (rt *Runtime) NewActorAddress() address.Address {

View File

@ -21,7 +21,6 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
builtin_types "github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/exitcode"
"github.com/filecoin-project/go-state-types/network"
@ -32,6 +31,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/account"
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/metrics"
@ -223,7 +223,7 @@ type LegacyVM struct {
buf *blockstore.BufferedBlockstore
blockHeight abi.ChainEpoch
areg *ActorRegistry
rand Rand
rand rand.Rand
circSupplyCalc CircSupplyCalculator
networkVersion network.Version
baseFee abi.TokenAmount
@ -237,7 +237,7 @@ type VMOpts struct {
StateBase cid.Cid
Epoch abi.ChainEpoch
Timestamp uint64
Rand Rand
Rand rand.Rand
Bstore blockstore.Blockstore
Actors *ActorRegistry
Syscalls SyscallBuilder
@ -286,11 +286,6 @@ func NewLegacyVM(ctx context.Context, opts *VMOpts) (*LegacyVM, error) {
}, nil
}
type Rand interface {
GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error)
}
type ApplyRet struct {
types.MessageReceipt
ActorErr aerrors.ActorError

View File

@ -15,7 +15,8 @@ import (
"github.com/filecoin-project/test-vectors/schema"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/chain/actors/builtin"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
@ -207,7 +208,7 @@ func doExtractMessage(opts extractOpts) error {
// TODO sometimes this returns a nil receipt and no error ¯\_(ツ)_/¯
// ex: https://filfox.info/en/message/bafy2bzacebpxw3yiaxzy2bako62akig46x3imji7fewszen6fryiz6nymu2b2
// This code is lenient and skips receipt comparison in case of a nil receipt.
rec, err := FullAPI.StateGetReceipt(ctx, mcid, execTs.Key())
rec, err := FullAPI.StateSearchMsg(ctx, execTs.Key(), mcid, api.LookbackNoLimit, false)
if err != nil {
return fmt.Errorf("failed to find receipt on chain: %w", err)
}
@ -217,9 +218,9 @@ func doExtractMessage(opts extractOpts) error {
var receipt *schema.Receipt
if rec != nil {
receipt = &schema.Receipt{
ExitCode: int64(rec.ExitCode),
ReturnValue: rec.Return,
GasUsed: rec.GasUsed,
ExitCode: int64(rec.Receipt.ExitCode),
ReturnValue: rec.Receipt.Return,
GasUsed: rec.Receipt.GasUsed,
}
reporter := new(conformance.LogReporter)
@ -326,7 +327,7 @@ func doExtractMessage(opts extractOpts) error {
// resolveFromChain queries the chain for the provided message, using the block CID to
// speed up the query, if provided
func resolveFromChain(ctx context.Context, api v0api.FullNode, mcid cid.Cid, block string) (msg *types.Message, execTs *types.TipSet, incTs *types.TipSet, err error) {
func resolveFromChain(ctx context.Context, api lapi.FullNode, mcid cid.Cid, block string) (msg *types.Message, execTs *types.TipSet, incTs *types.TipSet, err error) {
// Extract the full message.
msg, err = api.ChainGetMessage(ctx, mcid)
if err != nil {
@ -339,7 +340,7 @@ func resolveFromChain(ctx context.Context, api v0api.FullNode, mcid cid.Cid, blo
log.Printf("locating message in blockchain")
// Locate the message.
msgInfo, err := api.StateSearchMsg(ctx, mcid)
msgInfo, err := api.StateSearchMsg(ctx, types.EmptyTSK, mcid, lapi.LookbackNoLimit, false)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to locate message: %w", err)
}
@ -384,7 +385,7 @@ func resolveFromChain(ctx context.Context, api v0api.FullNode, mcid cid.Cid, blo
// as the previous tipset. In the context of vector generation, the target
// tipset is the one where a message was executed, and the previous tipset is
// the one where the message was included.
func fetchThisAndPrevTipset(ctx context.Context, api v0api.FullNode, target types.TipSetKey) (targetTs *types.TipSet, prevTs *types.TipSet, err error) {
func fetchThisAndPrevTipset(ctx context.Context, api v1api.FullNode, target types.TipSetKey) (targetTs *types.TipSet, prevTs *types.TipSet, err error) {
// get the tipset on which this message was "executed" on.
// https://github.com/filecoin-project/lotus/issues/2847
targetTs, err = api.ChainGetTipSet(ctx, target)

View File

@ -10,13 +10,13 @@ import (
"github.com/filecoin-project/go-jsonrpc"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
lcli "github.com/filecoin-project/lotus/cli"
)
// FullAPI is a JSON-RPC client targeting a full node. It's initialized in a
// cli.BeforeFunc.
var FullAPI v0api.FullNode
var FullAPI v1api.FullNode
// Closer is the closer for the JSON-RPC client, which must be called on
// cli.AfterFunc.
@ -102,7 +102,7 @@ func initialize(c *cli.Context) error {
// Make the API client.
var err error
if FullAPI, Closer, err = lcli.GetFullNodeAPI(c); err != nil {
if FullAPI, Closer, err = lcli.GetFullNodeAPIV1(c); err != nil {
err = fmt.Errorf("failed to locate Lotus node; err: %w", err)
}
return err

View File

@ -14,7 +14,8 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v1api"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
@ -24,13 +25,13 @@ import (
// StateSurgeon is an object used to fetch and manipulate state.
type StateSurgeon struct {
ctx context.Context
api v0api.FullNode
api v1api.FullNode
stores *Stores
}
// NewSurgeon returns a state surgeon, an object used to fetch and manipulate
// state.
func NewSurgeon(ctx context.Context, api v0api.FullNode, stores *Stores) *StateSurgeon {
func NewSurgeon(ctx context.Context, api v1api.FullNode, stores *Stores) *StateSurgeon {
return &StateSurgeon{
ctx: ctx,
api: api,
@ -86,9 +87,9 @@ func (sg *StateSurgeon) GetMaskedStateTree(previousRoot cid.Cid, retain []addres
// GetAccessedActors identifies the actors that were accessed during the
// execution of a message.
func (sg *StateSurgeon) GetAccessedActors(ctx context.Context, a v0api.FullNode, mid cid.Cid) ([]address.Address, error) {
func (sg *StateSurgeon) GetAccessedActors(ctx context.Context, a v1api.FullNode, mid cid.Cid) ([]address.Address, error) {
log.Printf("calculating accessed actors during execution of message: %s", mid)
msgInfo, err := a.StateSearchMsg(ctx, mid)
msgInfo, err := a.StateSearchMsg(ctx, types.EmptyTSK, mid, api.LookbackNoLimit, false)
if err != nil {
return nil, err
}

View File

@ -18,7 +18,7 @@ import (
format "github.com/ipfs/go-ipld-format"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/actors/adt"
)
@ -39,7 +39,7 @@ type Stores struct {
// NewProxyingStores is a set of Stores backed by a proxying Blockstore that
// proxies Get requests for unknown CIDs to a Filecoin node, via the
// ChainReadObj RPC.
func NewProxyingStores(ctx context.Context, api v0api.FullNode) *Stores {
func NewProxyingStores(ctx context.Context, api v1api.FullNode) *Stores {
ds := dssync.MutexWrap(ds.NewMapDatastore())
bs := &proxyingBlockstore{
ctx: ctx,
@ -84,7 +84,7 @@ type TracingBlockstore interface {
// a Filecoin node via JSON-RPC.
type proxyingBlockstore struct {
ctx context.Context
api v0api.FullNode
api v1api.FullNode
lk sync.Mutex
tracing bool

View File

@ -23,6 +23,7 @@ import (
"github.com/filecoin-project/lotus/chain/consensus"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
"github.com/filecoin-project/lotus/chain/index"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
@ -89,9 +90,9 @@ type ExecuteTipsetParams struct {
ParentEpoch abi.ChainEpoch
Tipset *schema.Tipset
ExecEpoch abi.ChainEpoch
// Rand is an optional vm.Rand implementation to use. If nil, the driver
// will use a vm.Rand that returns a fixed value for all calls.
Rand vm.Rand
// Rand is an optional rand.Rand implementation to use. If nil, the driver
// will use a rand.Rand that returns a fixed value for all calls.
Rand rand.Rand
// BaseFee if not nil or zero, will override the basefee of the tipset.
BaseFee abi.TokenAmount
}
@ -200,9 +201,9 @@ type ExecuteMessageParams struct {
BaseFee abi.TokenAmount
NetworkVersion network.Version
// Rand is an optional vm.Rand implementation to use. If nil, the driver
// will use a vm.Rand that returns a fixed value for all calls.
Rand vm.Rand
// Rand is an optional rand.Rand implementation to use. If nil, the driver
// will use a rand.Rand that returns a fixed value for all calls.
Rand rand.Rand
// Lookback is the LookbackStateGetter; returns the state tree at a given epoch.
Lookback vm.LookbackStateGetter

View File

@ -4,25 +4,24 @@ import (
"context"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/rand"
)
type fixedRand struct{}
var _ vm.Rand = (*fixedRand)(nil)
var _ rand.Rand = (*fixedRand)(nil)
// NewFixedRand creates a test vm.Rand that always returns fixed bytes value
// of utf-8 string 'i_am_random_____i_am_random_____'.
func NewFixedRand() vm.Rand {
func NewFixedRand() rand.Rand {
return &fixedRand{}
}
func (r *fixedRand) GetChainRandomness(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
func (r *fixedRand) GetChainRandomness(_ context.Context, _ abi.ChainEpoch) ([32]byte, error) {
return *(*[32]byte)([]byte("i_am_random_____i_am_random_____")), nil
}
func (r *fixedRand) GetBeaconRandomness(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
func (r *fixedRand) GetBeaconRandomness(_ context.Context, _ abi.ChainEpoch) ([32]byte, error) {
return *(*[32]byte)([]byte("i_am_random_____i_am_random_____")), nil // 32 bytes.
}

View File

@ -6,17 +6,16 @@ import (
"sync"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/test-vectors/schema"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/api/v1api"
"github.com/filecoin-project/lotus/chain/rand"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
)
type RecordingRand struct {
reporter Reporter
api v0api.FullNode
api v1api.FullNode
// once guards the loading of the head tipset.
// can be removed when https://github.com/filecoin-project/lotus/issues/4223
@ -27,12 +26,12 @@ type RecordingRand struct {
recorded schema.Randomness
}
var _ vm.Rand = (*RecordingRand)(nil)
var _ rand.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 v0api.FullNode) *RecordingRand {
func NewRecordingRand(reporter Reporter, api v1api.FullNode) *RecordingRand {
return &RecordingRand{reporter: reporter, api: api}
}
@ -44,22 +43,20 @@ func (r *RecordingRand) loadHead() {
r.head = head.Key()
}
func (r *RecordingRand) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *RecordingRand) GetChainRandomness(ctx context.Context, round abi.ChainEpoch) ([32]byte, error) {
r.once.Do(r.loadHead)
// FullNode's v0 ChainGetRandomnessFromTickets handles whether we should be looking forward or back
ret, err := r.api.ChainGetRandomnessFromTickets(ctx, r.head, pers, round, entropy)
// FullNode's v1 ChainGetRandomnessFromTickets handles whether we should be looking forward or back
ret, err := r.api.StateGetRandomnessDigestFromTickets(ctx, round, r.head)
if err != nil {
return ret, err
return [32]byte{}, err
}
r.reporter.Logf("fetched and recorded chain randomness for: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
r.reporter.Logf("fetched and recorded chain randomness for: epoch=%d, result=%x", round, ret)
match := schema.RandomnessMatch{
On: schema.RandomnessRule{
Kind: schema.RandomnessChain,
DomainSeparationTag: int64(pers),
Epoch: int64(round),
Entropy: entropy,
},
Return: []byte(ret),
}
@ -67,24 +64,22 @@ func (r *RecordingRand) GetChainRandomness(ctx context.Context, pers crypto.Doma
r.recorded = append(r.recorded, match)
r.lk.Unlock()
return ret, err
return *(*[32]byte)(ret), err
}
func (r *RecordingRand) GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *RecordingRand) GetBeaconRandomness(ctx context.Context, round abi.ChainEpoch) ([32]byte, error) {
r.once.Do(r.loadHead)
ret, err := r.api.StateGetRandomnessFromBeacon(ctx, pers, round, entropy, r.head)
ret, err := r.api.StateGetRandomnessDigestFromBeacon(ctx, round, r.head)
if err != nil {
return ret, err
return [32]byte{}, err
}
r.reporter.Logf("fetched and recorded beacon randomness for: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
r.reporter.Logf("fetched and recorded beacon randomness for: epoch=%d, result=%x", round, ret)
match := schema.RandomnessMatch{
On: schema.RandomnessRule{
Kind: schema.RandomnessBeacon,
DomainSeparationTag: int64(pers),
Epoch: int64(round),
Entropy: entropy,
},
Return: []byte(ret),
}
@ -92,7 +87,7 @@ func (r *RecordingRand) GetBeaconRandomness(ctx context.Context, pers crypto.Dom
r.recorded = append(r.recorded, match)
r.lk.Unlock()
return ret, err
return *(*[32]byte)(ret), err
}
func (r *RecordingRand) Recorded() schema.Randomness {

View File

@ -1,23 +1,21 @@
package conformance
import (
"bytes"
"context"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/test-vectors/schema"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/rand"
)
type ReplayingRand struct {
reporter Reporter
recorded schema.Randomness
fallback vm.Rand
fallback rand.Rand
}
var _ vm.Rand = (*ReplayingRand)(nil)
var _ rand.Rand = (*ReplayingRand)(nil)
// NewReplayingRand replays recorded randomness when requested, falling back to
// fixed randomness if the value cannot be found; hence this is a safe
@ -30,50 +28,44 @@ func NewReplayingRand(reporter Reporter, recorded schema.Randomness) *ReplayingR
}
}
func (r *ReplayingRand) match(requested schema.RandomnessRule) ([]byte, bool) {
func (r *ReplayingRand) match(requested schema.RandomnessRule) ([32]byte, bool) {
for _, other := range r.recorded {
if other.On.Kind == requested.Kind &&
other.On.Epoch == requested.Epoch &&
other.On.DomainSeparationTag == requested.DomainSeparationTag &&
bytes.Equal(other.On.Entropy, requested.Entropy) {
return other.Return, true
other.On.Epoch == requested.Epoch {
return *(*[32]byte)(other.Return), true
}
}
return nil, false
return [32]byte{}, false
}
func (r *ReplayingRand) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *ReplayingRand) GetChainRandomness(ctx context.Context, round abi.ChainEpoch) ([32]byte, error) {
rule := schema.RandomnessRule{
Kind: schema.RandomnessChain,
DomainSeparationTag: int64(pers),
Epoch: int64(round),
Entropy: entropy,
}
if ret, ok := r.match(rule); ok {
r.reporter.Logf("returning saved chain randomness: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
r.reporter.Logf("returning saved chain randomness: epoch=%d, result=%x", round, ret)
return ret, nil
}
r.reporter.Logf("returning fallback chain randomness: dst=%d, epoch=%d, entropy=%x", pers, round, entropy)
r.reporter.Logf("returning fallback chain randomness: epoch=%d", round)
return r.fallback.GetChainRandomness(ctx, pers, round, entropy)
return r.fallback.GetChainRandomness(ctx, round)
}
func (r *ReplayingRand) GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
func (r *ReplayingRand) GetBeaconRandomness(ctx context.Context, round abi.ChainEpoch) ([32]byte, error) {
rule := schema.RandomnessRule{
Kind: schema.RandomnessBeacon,
DomainSeparationTag: int64(pers),
Epoch: int64(round),
Entropy: entropy,
}
if ret, ok := r.match(rule); ok {
r.reporter.Logf("returning saved beacon randomness: dst=%d, epoch=%d, entropy=%x, result=%x", pers, round, entropy, ret)
r.reporter.Logf("returning saved beacon randomness: epoch=%d, result=%x", round, ret)
return ret, nil
}
r.reporter.Logf("returning fallback beacon randomness: dst=%d, epoch=%d, entropy=%x", pers, round, entropy)
r.reporter.Logf("returning fallback beacon randomness: epoch=%d, ", round)
return r.fallback.GetBeaconRandomness(ctx, pers, round, entropy)
return r.fallback.GetBeaconRandomness(ctx, round)
}

View File

@ -235,6 +235,8 @@
* [StateGetClaim](#StateGetClaim)
* [StateGetClaims](#StateGetClaims)
* [StateGetNetworkParams](#StateGetNetworkParams)
* [StateGetRandomnessDigestFromBeacon](#StateGetRandomnessDigestFromBeacon)
* [StateGetRandomnessDigestFromTickets](#StateGetRandomnessDigestFromTickets)
* [StateGetRandomnessFromBeacon](#StateGetRandomnessFromBeacon)
* [StateGetRandomnessFromTickets](#StateGetRandomnessFromTickets)
* [StateListActors](#StateListActors)
@ -6963,6 +6965,52 @@ Response:
}
```
### StateGetRandomnessDigestFromBeacon
StateGetRandomnessDigestFromBeacon is used to sample the beacon for randomness.
Perms: read
Inputs:
```json
[
10101,
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
]
]
```
Response: `"Bw=="`
### StateGetRandomnessDigestFromTickets
StateGetRandomnessDigestFromTickets. is used to sample the chain for randomness.
Perms: read
Inputs:
```json
[
10101,
[
{
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
},
{
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
}
]
]
```
Response: `"Bw=="`
### StateGetRandomnessFromBeacon
StateGetRandomnessFromBeacon is used to sample the beacon for randomness.

2
extern/filecoin-ffi vendored

@ -1 +1 @@
Subproject commit a458f638e3c8603c9b5a9ed9847c3af4597e46d4
Subproject commit 8c79a5f876ced3587f7fb872d29e1cd159d06b08

2
extern/test-vectors vendored

@ -1 +1 @@
Subproject commit 28b0c45eab4c302864af0aeaaff813625cfafe97
Subproject commit dcffbc519c1d59c211b8ffb653d7c0f2591486e7

2
go.mod
View File

@ -59,7 +59,7 @@ require (
github.com/filecoin-project/specs-actors/v6 v6.0.2
github.com/filecoin-project/specs-actors/v7 v7.0.1
github.com/filecoin-project/specs-actors/v8 v8.0.1
github.com/filecoin-project/test-vectors/schema v0.0.5
github.com/filecoin-project/test-vectors/schema v0.0.6-0.20230822140104-bed37e1ca04f
github.com/gbrlsnchs/jwt/v3 v3.0.1
github.com/gdamore/tcell/v2 v2.2.0
github.com/go-openapi/spec v0.19.11

4
go.sum
View File

@ -369,8 +369,8 @@ github.com/filecoin-project/specs-actors/v7 v7.0.1 h1:w72xCxijK7xs1qzmJiw+WYJaVt
github.com/filecoin-project/specs-actors/v7 v7.0.1/go.mod h1:tPLEYXoXhcpyLh69Ccq91SOuLXsPWjHiY27CzawjUEk=
github.com/filecoin-project/specs-actors/v8 v8.0.1 h1:4u0tIRJeT5G7F05lwLRIsDnsrN+bJ5Ixj6h49Q7uE2Y=
github.com/filecoin-project/specs-actors/v8 v8.0.1/go.mod h1:UYIPg65iPWoFw5NEftREdJwv9b/5yaLKdCgTvNI/2FA=
github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg=
github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
github.com/filecoin-project/test-vectors/schema v0.0.6-0.20230822140104-bed37e1ca04f h1:Ho3kK/WetJ7wco2VhR/pOZ9HD/WWL1BDEzYRTFQK8dw=
github.com/filecoin-project/test-vectors/schema v0.0.6-0.20230822140104-bed37e1ca04f/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=

View File

@ -531,7 +531,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type
return nil, err
}
rand, err := lrand.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
rand, err := lrand.DrawRandomnessFromBase(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
if err != nil {
err = xerrors.Errorf("failed to get randomness for winning post: %w", err)
return nil, err
@ -599,7 +599,7 @@ func (m *Miner) computeTicket(ctx context.Context, brand *types.BeaconEntry, rou
buf.Write(chainRand.VRFProof)
}
input, err := lrand.DrawRandomness(brand.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes())
input, err := lrand.DrawRandomnessFromBase(brand.Data, crypto.DomainSeparationTag_TicketProduction, round-build.TicketRandomnessLookback, buf.Bytes())
if err != nil {
return nil, err
}

View File

@ -1752,7 +1752,34 @@ func (a *StateAPI) StateGetRandomnessFromTickets(ctx context.Context, personaliz
func (a *StateAPI) StateGetRandomnessFromBeacon(ctx context.Context, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte, tsk types.TipSetKey) (abi.Randomness, error) {
return a.StateManager.GetRandomnessFromBeacon(ctx, personalization, randEpoch, entropy, tsk)
}
func (a *StateAPI) StateGetRandomnessDigestFromTickets(ctx context.Context, randEpoch abi.ChainEpoch, tsk types.TipSetKey) (abi.Randomness, error) {
ts, err := a.Chain.GetTipSetFromKey(ctx, tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
ret, err := a.StateManager.GetRandomnessDigestFromTickets(ctx, randEpoch, ts.Key())
if err != nil {
return nil, xerrors.Errorf("failed to get randomness digest from tickets: %w", err)
}
return ret[:], nil
}
func (a *StateAPI) StateGetRandomnessDigestFromBeacon(ctx context.Context, randEpoch abi.ChainEpoch, tsk types.TipSetKey) (abi.Randomness, error) {
ts, err := a.Chain.GetTipSetFromKey(ctx, tsk)
if err != nil {
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
ret, err := a.StateManager.GetRandomnessDigestFromBeacon(ctx, randEpoch, ts.Key())
if err != nil {
return nil, xerrors.Errorf("failed to get randomness digest from tickets: %w", err)
}
return ret[:], nil
}
func (a *StateAPI) StateGetBeaconEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) {