Documentation
¶
Index ¶
- Constants
- Variables
- func NewTestingKeyManager() *testingKeyManager
- func NewTestingKeyManagerWithSlashableRoots(slashableDataRoots [][]byte) *testingKeyManager
- func NewTestingQBFTController(identifier []byte, share *types.Share, config qbft.IConfig) *qbft.Controller
- func NewTestingStorage() *testingStorage
- func NewTestingTimer() qbft.Timer
- func TestingEncryption(pk *rsa.PublicKey, data []byte) []byte
- func UnknownDutyValueCheck() qbft.ProposedValueCheckF
- type TestKeySet
- func (ks *TestKeySet) Committee() []*types.Operator
- func (ks *TestKeySet) KeyGenOutput(opId types.OperatorID) *dkg.KeyGenOutput
- func (ks *TestKeySet) SignedOutputBytes(requestID dkg.RequestID, opId types.OperatorID, root []byte) []byte
- func (ks *TestKeySet) SignedOutputObject(requestID dkg.RequestID, opId types.OperatorID, root []byte) *dkg.SignedOutput
- type TestQBFTTimer
- type TestingBeaconNode
- func (bn *TestingBeaconNode) DomainData(epoch spec.Epoch, domain spec.DomainType) (spec.Domain, error)
- func (bn *TestingBeaconNode) GetAttestationData(slot spec.Slot, committeeIndex spec.CommitteeIndex) (*spec.AttestationData, error)
- func (bn *TestingBeaconNode) GetBeaconBlock(slot spec.Slot, committeeIndex spec.CommitteeIndex, graffiti, randao []byte) (*bellatrix.BeaconBlock, error)
- func (bn *TestingBeaconNode) GetBeaconNetwork() types.BeaconNetwork
- func (bn *TestingBeaconNode) GetSyncCommitteeContribution(slot spec.Slot, subnetID uint64, pubKey spec.BLSPubKey) (*altair.SyncCommitteeContribution, error)
- func (bn *TestingBeaconNode) GetSyncMessageBlockRoot() (spec.Root, error)
- func (bn *TestingBeaconNode) GetSyncSubcommitteeIndex(slot spec.Slot, pubKey spec.BLSPubKey) ([]uint64, error)
- func (bn *TestingBeaconNode) IsSyncCommitteeAggregator(proof []byte) (bool, error)
- func (bn *TestingBeaconNode) SetSyncCommitteeAggregatorRootHexes(roots map[string]bool)
- func (bn *TestingBeaconNode) SubmitAggregateSelectionProof(slot spec.Slot, committeeIndex spec.CommitteeIndex, slotSig []byte) (*spec.AggregateAndProof, error)
- func (bn *TestingBeaconNode) SubmitAttestation(attestation *spec.Attestation) error
- func (bn *TestingBeaconNode) SubmitBeaconBlock(block *bellatrix.SignedBeaconBlock) error
- func (bn *TestingBeaconNode) SubmitSignedAggregateSelectionProof(msg *spec.SignedAggregateAndProof) error
- func (bn *TestingBeaconNode) SubmitSignedContributionAndProof(contribution *altair.SignedContributionAndProof) error
- func (bn *TestingBeaconNode) SubmitSyncMessage(msg *altair.SyncCommitteeMessage) error
- func (bn *TestingBeaconNode) SyncCommitteeSubnetID(subCommitteeID uint64) (uint64, error)
- type TestingKeygenProtocol
- type TestingNetwork
- func (net *TestingNetwork) Broadcast(message *types.SSVMessage) error
- func (net *TestingNetwork) BroadcastDKGMessage(msg *dkg.SignedMessage) error
- func (net *TestingNetwork) StreamDKGBlame(blame *dkg.BlameOutput) error
- func (net *TestingNetwork) StreamDKGOutput(output map[types.OperatorID]*dkg.SignedOutput) error
- func (net *TestingNetwork) SyncHighestDecided(identifier types.MessageID) error
- func (net *TestingNetwork) SyncHighestRoundChange(identifier types.MessageID, height qbft.Height) error
Constants ¶
const ( TestingDutySlot = 12 TestingDutySlot2 = 50 TestingDutyEpoch = 0 TestingDutyEpoch2 = 1 TestingValidatorIndex = 1 UnknownDutyType = 100 )
Variables ¶
var AggregatorMsgID = func() []byte { ret := types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleAggregator) return ret[:] }()
var AggregatorRunner = func(keySet *TestKeySet) ssv.Runner { return baseRunner(types.BNRoleAggregator, ssv.AggregatorValueCheckF(NewTestingKeyManager(), types.NowTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex), keySet) }
var AttesterMsgID = func() []byte { ret := types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleAttester) return ret[:] }()
var AttesterRunner = func(keySet *TestKeySet) ssv.Runner { return baseRunner(types.BNRoleAttester, ssv.AttesterValueCheckF(NewTestingKeyManager(), types.NowTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex), keySet) }
var AttesterRunner7Operators = func(keySet *TestKeySet) ssv.Runner { return baseRunner(types.BNRoleAttester, ssv.AttesterValueCheckF(NewTestingKeyManager(), types.NowTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex), keySet) }
var BaseInstance = func() *qbft.Instance { return baseInstance(TestingShare(Testing4SharesSet()), Testing4SharesSet(), []byte{1, 2, 3, 4}) }
var BaseValidator = func(keySet *TestKeySet) *ssv.Validator { return ssv.NewValidator( NewTestingNetwork(), NewTestingBeaconNode(), NewTestingStorage(), TestingShare(keySet), NewTestingKeyManager(), map[types.BeaconRole]ssv.Runner{ types.BNRoleAttester: AttesterRunner(keySet), types.BNRoleProposer: ProposerRunner(keySet), types.BNRoleAggregator: AggregatorRunner(keySet), types.BNRoleSyncCommittee: SyncCommitteeRunner(keySet), types.BNRoleSyncCommitteeContribution: SyncCommitteeContributionRunner(keySet), }, ) }
var CommitDataBytes = func(data []byte) []byte { d := &qbft.CommitData{ Data: data, } ret, _ := d.Encode() return ret }
var DecidedRunner = func(keySet *TestKeySet) ssv.Runner { return decideRunner(TestAttesterConsensusData, qbft.FirstHeight, keySet) }
var DecidedRunnerUnknownDutyType = func(keySet *TestKeySet) ssv.Runner { return decideRunner(TestConsensusUnkownDutyTypeData, qbft.FirstHeight, keySet) }
var DecidedRunnerWithHeight = func(height qbft.Height, keySet *TestKeySet) ssv.Runner { return decideRunner(TestAttesterConsensusData, height, keySet) }
var DecidingMsgsForHeight = func(consensusData, msgIdentifier []byte, height qbft.Height, keySet *TestKeySet) []*qbft.SignedMessage { msgs := make([]*qbft.SignedMessage, 0) for h := qbft.Height(qbft.FirstHeight); h <= height; h++ { msgs = append(msgs, SignQBFTMsg(keySet.Shares[1], 1, &qbft.Message{ MsgType: qbft.ProposalMsgType, Height: h, Round: qbft.FirstRound, Identifier: msgIdentifier, Data: ProposalDataBytes(consensusData, nil, nil), })) for i := uint64(1); i <= keySet.Threshold; i++ { msgs = append(msgs, SignQBFTMsg(keySet.Shares[types.OperatorID(i)], types.OperatorID(i), &qbft.Message{ MsgType: qbft.PrepareMsgType, Height: h, Round: qbft.FirstRound, Identifier: msgIdentifier, Data: PrepareDataBytes(consensusData), })) } for i := uint64(1); i <= keySet.Threshold; i++ { msgs = append(msgs, SignQBFTMsg(keySet.Shares[types.OperatorID(i)], types.OperatorID(i), &qbft.Message{ MsgType: qbft.CommitMsgType, Height: h, Round: qbft.FirstRound, Identifier: msgIdentifier, Data: CommitDataBytes(consensusData), })) } } return msgs }
var DespositDataSigningRoot = func(keySet *TestKeySet, initMsg *dkg.Init) []byte { root, _, _ := types.GenerateETHDepositData( keySet.ValidatorPK.Serialize(), initMsg.WithdrawalCredentials, initMsg.Fork, types.DomainDeposit, ) return root }
var InitMessageDataBytes = func(operators []types.OperatorID, threshold uint16, withdrawalCred []byte, fork spec.Version) []byte { m := &dkg.Init{ OperatorIDs: operators, Threshold: threshold, WithdrawalCredentials: withdrawalCred, Fork: fork, } byts, _ := m.Encode() return byts }
var MultiSignQBFTMsg = func(sks []*bls.SecretKey, ids []types.OperatorID, msg *qbft.Message) *qbft.SignedMessage { if len(sks) == 0 || len(ids) != len(sks) { panic("sks != ids") } var signed *qbft.SignedMessage for i, sk := range sks { if signed == nil { signed = SignQBFTMsg(sk, ids[i], msg) } else { if err := signed.Aggregate(SignQBFTMsg(sk, ids[i], msg)); err != nil { panic(err.Error()) } } } return signed }
var PartialDepositDataBytes = func(signer types.OperatorID, root []byte, sk *bls.SecretKey) []byte { d := &dkg.PartialDepositData{ Signer: signer, Root: root, Signature: sk.SignByte(root).Serialize(), } ret, _ := d.Encode() return ret }
var PostConsensusAggregatorMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return postConsensusAggregatorMsg(sk, id, false, false) }
var PostConsensusAttestationMsg = func(sk *bls.SecretKey, id types.OperatorID, height qbft.Height) *ssv.SignedPartialSignatureMessage { return postConsensusAttestationMsg(sk, id, height, false, false) }
var PostConsensusAttestationMsgWithWrongRoot = func(sk *bls.SecretKey, id types.OperatorID, height qbft.Height) *ssv.SignedPartialSignatureMessage { return postConsensusAttestationMsg(sk, id, height, true, false) }
var PostConsensusAttestationMsgWithWrongSig = func(sk *bls.SecretKey, id types.OperatorID, height qbft.Height) *ssv.SignedPartialSignatureMessage { return postConsensusAttestationMsg(sk, id, height, true, false) }
var PostConsensusProposerMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return postConsensusBeaconBlockMsg(sk, id, false, false) }
var PostConsensusSyncCommitteeContributionMsg = func(sk *bls.SecretKey, id types.OperatorID, keySet *TestKeySet) *ssv.SignedPartialSignatureMessage { return postConsensusSyncCommitteeContributionMsg(sk, id, TestingValidatorIndex, keySet, false, false) }
var PostConsensusSyncCommitteeMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return postConsensusSyncCommitteeMsg(sk, id, false, false) }
var PreConsensusContributionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return PreConsensusCustomSlotContributionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot) }
var PreConsensusContributionProofNextEpochMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return contributionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot2, TestingDutySlot2, false, false) }
var PreConsensusCustomSlotContributionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID, slot spec.Slot) *ssv.SignedPartialSignatureMessage { return contributionProofMsg(msgSK, beaconSK, msgID, beaconID, slot, TestingDutySlot, false, false) }
var PreConsensusCustomSlotSelectionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID, slot spec.Slot) *ssv.SignedPartialSignatureMessage { return selectionProofMsg(msgSK, beaconSK, msgID, beaconID, slot, TestingDutySlot, 1) }
var PreConsensusFailedMsg = func(msgSigner *bls.SecretKey, msgSignerID types.OperatorID) *ssv.SignedPartialSignatureMessage { signer := NewTestingKeyManager() beacon := NewTestingBeaconNode() d, _ := beacon.DomainData(TestingDutyEpoch, types.DomainRandao) signed, root, _ := signer.SignBeaconObject(types.SSZUint64(TestingDutyEpoch), d, msgSigner.GetPublicKey().Serialize()) msg := ssv.PartialSignatureMessages{ Type: ssv.RandaoPartialSig, Messages: []*ssv.PartialSignatureMessage{ { Slot: TestingDutySlot, PartialSignature: signed[:], SigningRoot: root, Signer: msgSignerID, }, }, } sig, _ := signer.SignRoot(msg, types.PartialSignatureType, msgSigner.GetPublicKey().Serialize()) return &ssv.SignedPartialSignatureMessage{ Message: msg, Signature: sig, Signer: msgSignerID, } }
var PreConsensusMultiSelectionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return selectionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot, TestingDutySlot, 3) }
var PreConsensusRandaoDifferentEpochMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return randaoMsg(sk, id, false, TestingDutyEpoch+1, TestingDutySlot, 1) }
var PreConsensusRandaoDifferentSignerMsg = func(msgSigner, randaoSigner *bls.SecretKey, msgSignerID, randaoSignerID types.OperatorID) *ssv.SignedPartialSignatureMessage { signer := NewTestingKeyManager() beacon := NewTestingBeaconNode() d, _ := beacon.DomainData(TestingDutyEpoch, types.DomainRandao) signed, root, _ := signer.SignBeaconObject(types.SSZUint64(TestingDutyEpoch), d, randaoSigner.GetPublicKey().Serialize()) msg := ssv.PartialSignatureMessages{ Type: ssv.RandaoPartialSig, Messages: []*ssv.PartialSignatureMessage{ { Slot: TestingDutySlot, PartialSignature: signed[:], SigningRoot: root, Signer: randaoSignerID, }, }, } sig, _ := signer.SignRoot(msg, types.PartialSignatureType, msgSigner.GetPublicKey().Serialize()) return &ssv.SignedPartialSignatureMessage{ Message: msg, Signature: sig, Signer: msgSignerID, } }
var PreConsensusRandaoMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return randaoMsg(sk, id, false, TestingDutyEpoch, TestingDutySlot, 1) }
var PreConsensusRandaoMultiMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return randaoMsg(sk, id, false, TestingDutyEpoch, TestingDutySlot, 2) }
var PreConsensusRandaoNextEpochMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return randaoMsg(sk, id, false, TestingDutyEpoch2, TestingDutySlot2, 1) }
PreConsensusRandaoNextEpochMsg testing for a second duty start
var PreConsensusRandaoNoMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return randaoMsg(sk, id, false, TestingDutyEpoch, TestingDutySlot, 0) }
var PreConsensusRandaoWrongSlotMsg = func(sk *bls.SecretKey, id types.OperatorID) *ssv.SignedPartialSignatureMessage { return randaoMsg(sk, id, false, TestingDutyEpoch, TestingDutySlot+1, 1) }
var PreConsensusSelectionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return PreConsensusCustomSlotSelectionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot) }
var PreConsensusSelectionProofNextEpochMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return selectionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot2, TestingDutySlot2, 1) }
var PreConsensusWrongCountContributionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return contributionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot, TestingDutySlot, false, true) }
var PreConsensusWrongMsgSlotContributionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return contributionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot, TestingDutySlot+1, false, false) }
var PreConsensusWrongMsgSlotSelectionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return selectionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot, TestingDutySlot+1, 1) }
var PreConsensusWrongOrderContributionProofMsg = func(msgSK, beaconSK *bls.SecretKey, msgID, beaconID types.OperatorID) *ssv.SignedPartialSignatureMessage { return contributionProofMsg(msgSK, beaconSK, msgID, beaconID, TestingDutySlot, TestingDutySlot, true, false) }
var PrepareDataBytes = func(data []byte) []byte { d := &qbft.PrepareData{ Data: data, } ret, _ := d.Encode() return ret }
var ProposalDataBytes = func(data []byte, rcj, pj []*qbft.SignedMessage) []byte { d := &qbft.ProposalData{ Data: data, RoundChangeJustification: rcj, PrepareJustification: pj, } ret, _ := d.Encode() return ret }
var ProposerMsgID = func() []byte { ret := types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleProposer) return ret[:] }()
var ProposerRunner = func(keySet *TestKeySet) ssv.Runner { return baseRunner(types.BNRoleProposer, ssv.ProposerValueCheckF(NewTestingKeyManager(), types.NowTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex), keySet) }
var ProtocolMsgDataBytes = func(stage stubdkg.Stage) []byte { d := &stubdkg.ProtocolMsg{ Stage: stage, } ret, _ := d.Encode() return ret }
var RoundChangeDataBytes = func(preparedValue []byte, preparedRound qbft.Round) []byte { return RoundChangePreparedDataBytes(preparedValue, preparedRound, nil) }
var RoundChangePreparedDataBytes = func(preparedValue []byte, preparedRound qbft.Round, justif []*qbft.SignedMessage) []byte { d := &qbft.RoundChangeData{ PreparedValue: preparedValue, PreparedRound: preparedRound, RoundChangeJustification: justif, } ret, _ := d.Encode() return ret }
var SSVDecidingMsgs = func(consensusData []byte, ks *TestKeySet, role types.BeaconRole) []*types.SSVMessage { id := types.NewMsgID(TestingValidatorPubKey[:], role) ssvMsgF := func(qbftMsg *qbft.SignedMessage, partialSigMsg *ssv.SignedPartialSignatureMessage) *types.SSVMessage { var byts []byte var msgType types.MsgType if partialSigMsg != nil { msgType = types.SSVPartialSignatureMsgType byts, _ = partialSigMsg.Encode() } else { msgType = types.SSVConsensusMsgType byts, _ = qbftMsg.Encode() } return &types.SSVMessage{ MsgType: msgType, MsgID: id, Data: byts, } } base := make([]*types.SSVMessage, 0) if role == types.BNRoleProposer { for i := uint64(1); i <= ks.Threshold; i++ { base = append(base, ssvMsgF(nil, PreConsensusRandaoMsg(ks.Shares[types.OperatorID(i)], types.OperatorID(i)))) } } if role == types.BNRoleAggregator { for i := uint64(1); i <= ks.Threshold; i++ { base = append(base, ssvMsgF(nil, PreConsensusSelectionProofMsg(ks.Shares[types.OperatorID(i)], ks.Shares[types.OperatorID(i)], types.OperatorID(i), types.OperatorID(i)))) } } if role == types.BNRoleSyncCommitteeContribution { for i := uint64(1); i <= ks.Threshold; i++ { base = append(base, ssvMsgF(nil, PreConsensusContributionProofMsg(ks.Shares[types.OperatorID(i)], ks.Shares[types.OperatorID(i)], types.OperatorID(i), types.OperatorID(i)))) } } qbftMsgs := DecidingMsgsForHeight(consensusData, id[:], qbft.FirstHeight, ks) for _, msg := range qbftMsgs { base = append(base, ssvMsgF(msg, nil)) } return base }
var SSVMsgAggregator = func(qbftMsg *qbft.SignedMessage, partialSigMsg *ssv.SignedPartialSignatureMessage) *types.SSVMessage { return ssvMsg(qbftMsg, partialSigMsg, types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleAggregator)) }
var SSVMsgAttester = func(qbftMsg *qbft.SignedMessage, partialSigMsg *ssv.SignedPartialSignatureMessage) *types.SSVMessage { return ssvMsg(qbftMsg, partialSigMsg, types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleAttester)) }
var SSVMsgProposer = func(qbftMsg *qbft.SignedMessage, partialSigMsg *ssv.SignedPartialSignatureMessage) *types.SSVMessage { return ssvMsg(qbftMsg, partialSigMsg, types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleProposer)) }
var SSVMsgSyncCommittee = func(qbftMsg *qbft.SignedMessage, partialSigMsg *ssv.SignedPartialSignatureMessage) *types.SSVMessage { return ssvMsg(qbftMsg, partialSigMsg, types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleSyncCommittee)) }
var SSVMsgSyncCommitteeContribution = func(qbftMsg *qbft.SignedMessage, partialSigMsg *ssv.SignedPartialSignatureMessage) *types.SSVMessage { return ssvMsg(qbftMsg, partialSigMsg, types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleSyncCommitteeContribution)) }
var SSVMsgWrongID = func(qbftMsg *qbft.SignedMessage, partialSigMsg *ssv.SignedPartialSignatureMessage) *types.SSVMessage { return ssvMsg(qbftMsg, partialSigMsg, types.NewMsgID(TestingWrongValidatorPubKey[:], types.BNRoleAttester)) }
var SevenOperatorsInstance = func() *qbft.Instance { return baseInstance(TestingShare(Testing7SharesSet()), Testing7SharesSet(), []byte{1, 2, 3, 4}) }
var SignDKGMsg = func(sk *ecdsa.PrivateKey, id types.OperatorID, msg *dkg.Message) *dkg.SignedMessage { domain := types.PrimusTestnet sigType := types.DKGSignatureType r, _ := types.ComputeSigningRoot(msg, types.ComputeSignatureDomain(domain, sigType)) sig, _ := crypto.Sign(r, sk) return &dkg.SignedMessage{ Message: msg, Signer: id, Signature: sig, } }
var SignQBFTMsg = func(sk *bls.SecretKey, id types.OperatorID, msg *qbft.Message) *qbft.SignedMessage { domain := types.PrimusTestnet sigType := types.QBFTSignatureType r, _ := types.ComputeSigningRoot(msg, types.ComputeSignatureDomain(domain, sigType)) sig := sk.SignByte(r) return &qbft.SignedMessage{ Message: msg, Signers: []types.OperatorID{id}, Signature: sig.Serialize(), } }
var SyncCommitteeContributionMsgID = func() []byte { ret := types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleSyncCommitteeContribution) return ret[:] }()
var SyncCommitteeContributionRunner = func(keySet *TestKeySet) ssv.Runner { return baseRunner(types.BNRoleSyncCommitteeContribution, ssv.SyncCommitteeContributionValueCheckF(NewTestingKeyManager(), types.NowTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex), keySet) }
var SyncCommitteeMsgID = func() []byte { ret := types.NewMsgID(TestingValidatorPubKey[:], types.BNRoleSyncCommittee) return ret[:] }()
var SyncCommitteeRunner = func(keySet *TestKeySet) ssv.Runner { return baseRunner(types.BNRoleSyncCommittee, ssv.SyncCommitteeValueCheckF(NewTestingKeyManager(), types.NowTestNetwork, TestingValidatorPubKey[:], TestingValidatorIndex), keySet) }
var TenOperatorsInstance = func() *qbft.Instance { return baseInstance(TestingShare(Testing10SharesSet()), Testing10SharesSet(), []byte{1, 2, 3, 4}) }
var TestAggregatorConsensusData = &types.ConsensusData{ Duty: TestingAggregatorDuty, AggregateAndProof: TestingAggregateAndProof, }
var TestAggregatorConsensusDataByts, _ = TestAggregatorConsensusData.Encode()
var TestAttesterConsensusData = &types.ConsensusData{ Duty: TestingAttesterDuty, AttestationData: TestingAttestationData, }
var TestAttesterConsensusDataByts, _ = TestAttesterConsensusData.Encode()
var TestConsensusUnkownDutyTypeData = &types.ConsensusData{ Duty: TestingUnknownDutyType, AttestationData: TestingAttestationData, }
var TestConsensusUnkownDutyTypeDataByts, _ = TestConsensusUnkownDutyTypeData.Encode()
var TestConsensusWrongDutyPKData = &types.ConsensusData{ Duty: TestingWrongDutyPK, AttestationData: TestingAttestationData, }
var TestConsensusWrongDutyPKDataByts, _ = TestConsensusWrongDutyPKData.Encode()
var TestProposerConsensusData = &types.ConsensusData{ Duty: TestingProposerDuty, BlockData: TestingBeaconBlock, }
var TestProposerConsensusDataByts, _ = TestProposerConsensusData.Encode()
var TestSyncCommitteeConsensusData = &types.ConsensusData{ Duty: TestingSyncCommitteeDuty, SyncCommitteeBlockRoot: TestingSyncCommitteeBlockRoot, }
var TestSyncCommitteeConsensusDataByts, _ = TestSyncCommitteeConsensusData.Encode()
var TestSyncCommitteeContributionConsensusData = &types.ConsensusData{ Duty: TestingSyncCommitteeContributionDuty, SyncCommitteeContribution: map[spec.BLSSignature]*altair.SyncCommitteeContribution{ TestingContributionProofsSigned[0]: TestingSyncCommitteeContributions[0], TestingContributionProofsSigned[1]: TestingSyncCommitteeContributions[1], TestingContributionProofsSigned[2]: TestingSyncCommitteeContributions[2], }, }
var TestSyncCommitteeContributionConsensusDataByts, _ = TestSyncCommitteeContributionConsensusData.Encode()
var TestingAggregateAndProof = &spec.AggregateAndProof{ AggregatorIndex: 1, SelectionProof: spec.BLSSignature{}, Aggregate: &spec.Attestation{ AggregationBits: bitfield.NewBitlist(128), Signature: spec.BLSSignature{}, Data: TestingAttestationData, }, }
var TestingAggregatorDuty = &types.Duty{ Type: types.BNRoleAggregator, PubKey: TestingValidatorPubKey, Slot: TestingDutySlot, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 22, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
var TestingAggregatorDutyNextEpoch = &types.Duty{ Type: types.BNRoleAggregator, PubKey: TestingValidatorPubKey, Slot: TestingDutySlot2, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 22, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
TestingAggregatorDutyNextEpoch testing for a second duty start
var TestingAttestationData = &spec.AttestationData{ Slot: 12, Index: 3, BeaconBlockRoot: spec.Root{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2}, Source: &spec.Checkpoint{ Epoch: 0, Root: spec.Root{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2}, }, Target: &spec.Checkpoint{ Epoch: 1, Root: spec.Root{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2}, }, }
var TestingAttesterDuty = &types.Duty{ Type: types.BNRoleAttester, PubKey: TestingValidatorPubKey, Slot: TestingDutySlot, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 3, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
var TestingBeaconBlock = &bellatrix.BeaconBlock{ Slot: 12, ProposerIndex: 10, ParentRoot: spec.Root{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2}, StateRoot: spec.Root{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2}, Body: &bellatrix.BeaconBlockBody{ RANDAOReveal: spec.BLSSignature{}, ETH1Data: &spec.ETH1Data{ DepositRoot: spec.Root{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2}, DepositCount: 100, BlockHash: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2}, }, Graffiti: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2}, ProposerSlashings: []*spec.ProposerSlashing{}, AttesterSlashings: []*spec.AttesterSlashing{}, Attestations: []*spec.Attestation{ { AggregationBits: bitfield.NewBitlist(122), Data: TestingAttestationData, Signature: spec.BLSSignature{}, }, }, Deposits: []*spec.Deposit{}, VoluntaryExits: []*spec.SignedVoluntaryExit{}, SyncAggregate: &altair.SyncAggregate{ SyncCommitteeBits: bitfield.NewBitvector512(), SyncCommitteeSignature: spec.BLSSignature{}, }, ExecutionPayload: &bellatrix.ExecutionPayload{ ParentHash: spec.Hash32{}, FeeRecipient: bellatrix.ExecutionAddress{}, StateRoot: spec.Hash32{}, ReceiptsRoot: spec.Hash32{}, LogsBloom: [256]byte{}, PrevRandao: [32]byte{}, BlockNumber: 100, GasLimit: 1000000, GasUsed: 800000, Timestamp: 123456789, BaseFeePerGas: [32]byte{}, BlockHash: spec.Hash32{}, Transactions: []bellatrix.Transaction{}, }, }, }
var TestingConfig = func(keySet *TestKeySet) *qbft.Config { return &qbft.Config{ Signer: NewTestingKeyManager(), SigningPK: keySet.Shares[1].GetPublicKey().Serialize(), Domain: types.PrimusTestnet, ValueCheckF: func(data []byte) error { if bytes.Equal(data, TestingInvalidValueCheck) { return errors.New("invalid value") } return nil }, ProposerF: func(state *qbft.State, round qbft.Round) types.OperatorID { return 1 }, Storage: NewTestingStorage(), Network: NewTestingNetwork(), Timer: NewTestingTimer(), } }
var TestingContributionProofIndexes = []uint64{0, 1, 2}
var TestingContributionProofsSigned = func() []spec.BLSSignature { byts1, _ := hex.DecodeString("b18833bb7549ec33e8ac414ba002fd45bb094ca300bd24596f04a434a89beea462401da7c6b92fb3991bd17163eb603604a40e8dd6781266c990023446776ff42a9313df26a0a34184a590e57fa4003d610c2fa214db4e7dec468592010298bc") byts2, _ := hex.DecodeString("9094342c95146554df849dc20f7425fca692dacee7cb45258ddd264a8e5929861469fda3d1567b9521cba83188ffd61a0dbe6d7180c7a96f5810d18db305e9143772b766d368aa96d3751f98d0ce2db9f9e6f26325702088d87f0de500c67c68") byts3, _ := hex.DecodeString("a7f88ce43eff3aa8cdd2e3957c5bead4e21353fbecac6079a5398d03019bc45ff7c951785172deee70e9bc5abbc8ca6a0f0441e9d4cc9da74c31121357f7d7c7de9533f6f457da493e3314e22d554ab76613e469b050e246aff539a33807197c") ret := make([]spec.BLSSignature, 0) for _, byts := range [][]byte{byts1, byts2, byts3} { b := spec.BLSSignature{} copy(b[:], byts) ret = append(ret, b) } return ret }()
var TestingDKGNode = func(keySet *TestKeySet) *dkg.Node { network := NewTestingNetwork() km := NewTestingKeyManager() config := &dkg.Config{ KeygenProtocol: func(network dkg.Network, operatorID types.OperatorID, identifier dkg.RequestID, init *dkg.Init) dkg.Protocol { return &TestingKeygenProtocol{ KeyGenOutput: keySet.KeyGenOutput(1), } }, ReshareProtocol: func(network dkg.Network, operatorID types.OperatorID, identifier dkg.RequestID, reshare *dkg.Reshare, output *dkg.KeyGenOutput) dkg.Protocol { return &TestingKeygenProtocol{ KeyGenOutput: keySet.KeyGenOutput(1), } }, Network: network, Storage: NewTestingStorage(), SignatureDomainType: types.PrimusTestnet, Signer: km, } return dkg.NewNode(&dkg.Operator{ OperatorID: 1, ETHAddress: keySet.DKGOperators[1].ETHAddress, EncryptionPubKey: &keySet.DKGOperators[1].EncryptionKey.PublicKey, }, config) }
var TestingForkVersion = types.PraterNetwork.ForkVersion()
var TestingInvalidValueCheck = []byte{1, 1, 1, 1}
var TestingProposerDuty = &types.Duty{ Type: types.BNRoleProposer, PubKey: TestingValidatorPubKey, Slot: TestingDutySlot, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 3, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
var TestingProposerDutyNextEpoch = &types.Duty{ Type: types.BNRoleProposer, PubKey: TestingValidatorPubKey, Slot: TestingDutySlot2, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 3, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
TestingProposerDutyNextEpoch testing for a second duty start
return &types.Share{ OperatorID: 1, ValidatorPubKey: keysSet.ValidatorPK.Serialize(), SharePubKey: keysSet.Shares[1].GetPublicKey().Serialize(), DomainType: types.PrimusTestnet, Quorum: keysSet.Threshold, PartialQuorum: keysSet.PartialThreshold, Committee: keysSet.Committee(), } }
var TestingSyncCommitteeBlockRoot = spec.Root{}
var TestingSyncCommitteeContributionDuty = &types.Duty{ Type: types.BNRoleSyncCommitteeContribution, PubKey: TestingValidatorPubKey, Slot: TestingDutySlot, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 3, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
var TestingSyncCommitteeContributionNexEpochDuty = &types.Duty{ Type: types.BNRoleSyncCommitteeContribution, PubKey: TestingValidatorPubKey, Slot: TestingDutySlot2, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 3, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
TestingSyncCommitteeContributionNexEpochDuty testing for a second duty start
var TestingSyncCommitteeContributions = []*altair.SyncCommitteeContribution{ { Slot: TestingDutySlot, BeaconBlockRoot: TestingSyncCommitteeBlockRoot, SubcommitteeIndex: 0, AggregationBits: bitfield.NewBitvector128(), Signature: spec.BLSSignature{}, }, { Slot: TestingDutySlot, BeaconBlockRoot: TestingSyncCommitteeBlockRoot, SubcommitteeIndex: 1, AggregationBits: bitfield.NewBitvector128(), Signature: spec.BLSSignature{}, }, { Slot: TestingDutySlot, BeaconBlockRoot: TestingSyncCommitteeBlockRoot, SubcommitteeIndex: 2, AggregationBits: bitfield.NewBitvector128(), Signature: spec.BLSSignature{}, }, }
var TestingSyncCommitteeDuty = &types.Duty{ Type: types.BNRoleSyncCommittee, PubKey: TestingValidatorPubKey, Slot: TestingDutySlot, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 3, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
var TestingUnknownDutyType = &types.Duty{ Type: UnknownDutyType, PubKey: TestingValidatorPubKey, Slot: 12, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 22, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
var TestingValidatorPubKey = func() spec.BLSPubKey { pk, _ := hex.DecodeString("8e80066551a81b318258709edaf7dd1f63cd686a0e4db8b29bbb7acfe65608677af5a527d9448ee47835485e02b50bc0") blsPK := spec.BLSPubKey{} copy(blsPK[:], pk) return blsPK }()
var TestingWithdrawalCredentials, _ = hex.DecodeString("010000000000000000000000535953b5a6040074948cf185eaa7d2abbd66808f")
var TestingWrongDutyPK = &types.Duty{ Type: types.BNRoleAttester, PubKey: TestingWrongValidatorPubKey, Slot: 12, ValidatorIndex: TestingValidatorIndex, CommitteeIndex: 3, CommitteesAtSlot: 36, CommitteeLength: 128, ValidatorCommitteeIndex: 11, }
var TestingWrongValidatorPubKey = func() spec.BLSPubKey { pk, _ := hex.DecodeString("948fb44582ce25336fdb17122eac64fe5a1afc39174ce92d6013becac116766dc5a778c880dd47de7dfff6a0f86ba42b") blsPK := spec.BLSPubKey{} copy(blsPK[:], pk) return blsPK }()
var ThirteenOperatorsInstance = func() *qbft.Instance { return baseInstance(TestingShare(Testing13SharesSet()), Testing13SharesSet(), []byte{1, 2, 3, 4}) }
var UnknownDutyTypeRunner = func(keySet *TestKeySet) ssv.Runner { return baseRunner(UnknownDutyType, UnknownDutyValueCheck(), keySet) }
Functions ¶
func NewTestingKeyManager ¶
func NewTestingKeyManager() *testingKeyManager
func NewTestingKeyManagerWithSlashableRoots ¶ added in v0.2.7
func NewTestingKeyManagerWithSlashableRoots(slashableDataRoots [][]byte) *testingKeyManager
func NewTestingStorage ¶
func NewTestingStorage() *testingStorage
func NewTestingTimer ¶
func TestingEncryption ¶ added in v0.2.7
func UnknownDutyValueCheck ¶ added in v0.2.7
func UnknownDutyValueCheck() qbft.ProposedValueCheckF
Types ¶
type TestKeySet ¶
func KeySetForShare ¶ added in v0.2.7
func KeySetForShare(share *types.Share) *TestKeySet
func Testing4SharesSet ¶
func Testing4SharesSet() *TestKeySet
func Testing7SharesSet ¶
func Testing7SharesSet() *TestKeySet
func Testing10SharesSet ¶
func Testing10SharesSet() *TestKeySet
func Testing13SharesSet ¶
func Testing13SharesSet() *TestKeySet
func (*TestKeySet) Committee ¶
func (ks *TestKeySet) Committee() []*types.Operator
func (*TestKeySet) KeyGenOutput ¶ added in v0.2.7
func (ks *TestKeySet) KeyGenOutput(opId types.OperatorID) *dkg.KeyGenOutput
func (*TestKeySet) SignedOutputBytes ¶ added in v0.2.7
func (ks *TestKeySet) SignedOutputBytes(requestID dkg.RequestID, opId types.OperatorID, root []byte) []byte
func (*TestKeySet) SignedOutputObject ¶ added in v0.2.7
func (ks *TestKeySet) SignedOutputObject(requestID dkg.RequestID, opId types.OperatorID, root []byte) *dkg.SignedOutput
type TestQBFTTimer ¶
type TestQBFTTimer struct {
}
func (*TestQBFTTimer) TimeoutForRound ¶
func (t *TestQBFTTimer) TimeoutForRound(round qbft.Round)
type TestingBeaconNode ¶ added in v0.2.7
type TestingBeaconNode struct {
// contains filtered or unexported fields
}
func NewTestingBeaconNode ¶
func NewTestingBeaconNode() *TestingBeaconNode
func (*TestingBeaconNode) DomainData ¶ added in v0.2.7
func (bn *TestingBeaconNode) DomainData(epoch spec.Epoch, domain spec.DomainType) (spec.Domain, error)
func (*TestingBeaconNode) GetAttestationData ¶ added in v0.2.7
func (bn *TestingBeaconNode) GetAttestationData(slot spec.Slot, committeeIndex spec.CommitteeIndex) (*spec.AttestationData, error)
GetAttestationData returns attestation data by the given slot and committee index
func (*TestingBeaconNode) GetBeaconBlock ¶ added in v0.2.7
func (bn *TestingBeaconNode) GetBeaconBlock(slot spec.Slot, committeeIndex spec.CommitteeIndex, graffiti, randao []byte) (*bellatrix.BeaconBlock, error)
GetBeaconBlock returns beacon block by the given slot and committee index
func (*TestingBeaconNode) GetBeaconNetwork ¶ added in v0.2.7
func (bn *TestingBeaconNode) GetBeaconNetwork() types.BeaconNetwork
GetBeaconNetwork returns the beacon network the node is on
func (*TestingBeaconNode) GetSyncCommitteeContribution ¶ added in v0.2.7
func (bn *TestingBeaconNode) GetSyncCommitteeContribution(slot spec.Slot, subnetID uint64, pubKey spec.BLSPubKey) (*altair.SyncCommitteeContribution, error)
GetSyncCommitteeContribution returns
func (*TestingBeaconNode) GetSyncMessageBlockRoot ¶ added in v0.2.7
func (bn *TestingBeaconNode) GetSyncMessageBlockRoot() (spec.Root, error)
GetSyncMessageBlockRoot returns beacon block root for sync committee
func (*TestingBeaconNode) GetSyncSubcommitteeIndex ¶ added in v0.2.7
func (bn *TestingBeaconNode) GetSyncSubcommitteeIndex(slot spec.Slot, pubKey spec.BLSPubKey) ([]uint64, error)
GetSyncSubcommitteeIndex returns sync committee indexes for aggregator
func (*TestingBeaconNode) IsSyncCommitteeAggregator ¶ added in v0.2.7
func (bn *TestingBeaconNode) IsSyncCommitteeAggregator(proof []byte) (bool, error)
IsSyncCommitteeAggregator returns tru if aggregator
func (*TestingBeaconNode) SetSyncCommitteeAggregatorRootHexes ¶ added in v0.2.7
func (bn *TestingBeaconNode) SetSyncCommitteeAggregatorRootHexes(roots map[string]bool)
SetSyncCommitteeAggregatorRootHexes FOR TESTING ONLY!! sets which sync committee aggregator roots will return true for aggregator
func (*TestingBeaconNode) SubmitAggregateSelectionProof ¶ added in v0.2.7
func (bn *TestingBeaconNode) SubmitAggregateSelectionProof(slot spec.Slot, committeeIndex spec.CommitteeIndex, slotSig []byte) (*spec.AggregateAndProof, error)
SubmitAggregateSelectionProof returns an AggregateAndProof object
func (*TestingBeaconNode) SubmitAttestation ¶ added in v0.2.7
func (bn *TestingBeaconNode) SubmitAttestation(attestation *spec.Attestation) error
SubmitAttestation submit the attestation to the node
func (*TestingBeaconNode) SubmitBeaconBlock ¶ added in v0.2.7
func (bn *TestingBeaconNode) SubmitBeaconBlock(block *bellatrix.SignedBeaconBlock) error
SubmitBeaconBlock submit the block to the node
func (*TestingBeaconNode) SubmitSignedAggregateSelectionProof ¶ added in v0.2.7
func (bn *TestingBeaconNode) SubmitSignedAggregateSelectionProof(msg *spec.SignedAggregateAndProof) error
SubmitSignedAggregateSelectionProof broadcasts a signed aggregator msg
func (*TestingBeaconNode) SubmitSignedContributionAndProof ¶ added in v0.2.7
func (bn *TestingBeaconNode) SubmitSignedContributionAndProof(contribution *altair.SignedContributionAndProof) error
SubmitSignedContributionAndProof broadcasts to the network
func (*TestingBeaconNode) SubmitSyncMessage ¶ added in v0.2.7
func (bn *TestingBeaconNode) SubmitSyncMessage(msg *altair.SyncCommitteeMessage) error
SubmitSyncMessage submits a signed sync committee msg
func (*TestingBeaconNode) SyncCommitteeSubnetID ¶ added in v0.2.7
func (bn *TestingBeaconNode) SyncCommitteeSubnetID(subCommitteeID uint64) (uint64, error)
SyncCommitteeSubnetID returns sync committee subnet ID from subcommittee index
type TestingKeygenProtocol ¶ added in v0.2.7
type TestingKeygenProtocol struct {
KeyGenOutput *dkg.KeyGenOutput
}
func (TestingKeygenProtocol) ProcessMsg ¶ added in v0.2.7
func (m TestingKeygenProtocol) ProcessMsg(msg *dkg.SignedMessage) (bool, *dkg.ProtocolOutcome, error)
func (TestingKeygenProtocol) Start ¶ added in v0.2.7
func (m TestingKeygenProtocol) Start() error
type TestingNetwork ¶
type TestingNetwork struct {
BroadcastedMsgs []*types.SSVMessage
DKGOutputs map[types.OperatorID]*dkg.SignedOutput
SyncHighestDecidedCnt int
SyncHighestChangeRoundCnt int
}
func NewTestingNetwork ¶
func NewTestingNetwork() *TestingNetwork
func (*TestingNetwork) Broadcast ¶
func (net *TestingNetwork) Broadcast(message *types.SSVMessage) error
func (*TestingNetwork) BroadcastDKGMessage ¶
func (net *TestingNetwork) BroadcastDKGMessage(msg *dkg.SignedMessage) error
BroadcastDKGMessage will broadcast a msg to the dkg network
func (*TestingNetwork) StreamDKGBlame ¶ added in v0.2.7
func (net *TestingNetwork) StreamDKGBlame(blame *dkg.BlameOutput) error
func (*TestingNetwork) StreamDKGOutput ¶
func (net *TestingNetwork) StreamDKGOutput(output map[types.OperatorID]*dkg.SignedOutput) error
StreamDKGOutput will stream to any subscriber the result of the DKG
func (*TestingNetwork) SyncHighestDecided ¶ added in v0.2.7
func (net *TestingNetwork) SyncHighestDecided(identifier types.MessageID) error