@@ -654,59 +654,17 @@ func GetWithdrawalProofForSlot(c *cli.Context, slot uint64, validatorIndex uint6
654654 blockToRequest = fmt .Sprintf ("%d" , recentBlock .Slot - 1 )
655655 }
656656
657- // Find the most recent withdrawal to slot.
658- // Keep track of 404s- if we get 24 missing slots in a row, assume we don't have full history.
659- notFounds := 0
660- var foundWithdrawal bool
661- var block eth2.SignedBeaconBlock
662- for candidateSlot := slot ; candidateSlot <= slot + MAX_WITHDRAWAL_SLOT_DISTANCE ; candidateSlot ++ {
663- // Get the block at the candidate slot.
664- blockResponse , found , err := bc .GetBeaconBlockSSZ (candidateSlot )
665- if err != nil {
666- return megapool.FinalBalanceProof {}, 0 , nil , err
667- }
668- if ! found {
669- notFounds ++
670- if notFounds >= 64 {
671- return megapool.FinalBalanceProof {}, 0 , nil , fmt .Errorf ("2 epochs of missing slots detected. It is likely that the Beacon Client was checkpoint synced after the most recent withdrawal to slot %d, and does not have the history required to generate a withdrawal proof" , slot )
672- }
673- continue
674- } else {
675- notFounds = 0
676- }
677-
678- beaconBlock , err := eth2 .NewSignedBeaconBlock (blockResponse .Data , blockResponse .Fork )
679- if err != nil {
680- return megapool.FinalBalanceProof {}, 0 , nil , err
681- }
682-
683- if ! beaconBlock .HasExecutionPayload () {
684- continue
685- }
686-
687- // Check the block for a withdrawal for the given validator index.
688- for i , withdrawal := range beaconBlock .Withdrawals () {
689- if withdrawal .ValidatorIndex != validatorIndex {
690- continue
691- }
692- response .WithdrawalSlot = candidateSlot
693- response .Amount = big .NewInt (0 ).SetUint64 (withdrawal .Amount )
694- foundWithdrawal = true
695- response .IndexInWithdrawalsArray = uint (i )
696- response .WithdrawalIndex = withdrawal .Index
697- response .WithdrawalAddress = withdrawal .Address
698- break
699- }
700-
701- if foundWithdrawal {
702- block = beaconBlock
703- break
704- }
657+ withdrawalSlot , block , indexInWithdrawalsArray , withdrawal , err := FindWithdrawalBlockAndArrayPosition (slot , validatorIndex , bc )
658+ if err != nil {
659+ return megapool.FinalBalanceProof {}, 0 , nil , err
705660 }
706661
707- if ! foundWithdrawal {
708- return megapool.FinalBalanceProof {}, 0 , nil , fmt .Errorf ("no withdrawal found for validator index %d within %d slots of slot %d" , validatorIndex , MAX_WITHDRAWAL_SLOT_DISTANCE , slot )
709- }
662+ response .WithdrawalSlot = withdrawalSlot
663+ response .Amount = ConvertWithdrawalAmount (withdrawal .Amount )
664+ response .Amount = big .NewInt (0 ).SetUint64 (withdrawal .Amount )
665+ response .IndexInWithdrawalsArray = uint (indexInWithdrawalsArray )
666+ response .WithdrawalIndex = withdrawal .Index
667+ response .WithdrawalAddress = withdrawal .Address
710668
711669 // Start by proving from the withdrawal to the block_root
712670 proof , err := block .ProveWithdrawal (uint64 (response .IndexInWithdrawalsArray ))
@@ -770,6 +728,56 @@ func GetWithdrawalProofForSlot(c *cli.Context, slot uint64, validatorIndex uint6
770728 return response , recentBlock .Slot , state , nil
771729}
772730
731+ func ConvertWithdrawalAmount (amount uint64 ) * big.Int {
732+ amountBigInt := big .NewInt (int64 (amount ))
733+
734+ // amount is in Gwei, but we want wei
735+ amountBigInt .Mul (amountBigInt , big .NewInt (1e9 ))
736+ return amountBigInt
737+ }
738+
739+ func FindWithdrawalBlockAndArrayPosition (slot uint64 , validatorIndex uint64 , bc beacon.Client ) (uint64 , eth2.SignedBeaconBlock , int , * generic.Withdrawal , error ) {
740+
741+ // Find the most recent withdrawal to slot.
742+ // Keep track of 404s- if we get 24 missing slots in a row, assume we don't have full history.
743+ notFounds := 0
744+ for candidateSlot := slot ; candidateSlot <= slot + MAX_WITHDRAWAL_SLOT_DISTANCE ; candidateSlot ++ {
745+ // Get the block at the candidate slot.
746+ blockResponse , found , err := bc .GetBeaconBlockSSZ (candidateSlot )
747+ if err != nil {
748+ return 0 , nil , 0 , nil , err
749+ }
750+ if ! found {
751+ notFounds ++
752+ if notFounds >= 64 {
753+ return 0 , nil , 0 , nil , fmt .Errorf ("2 epochs of missing slots detected. It is likely that the Beacon Client was checkpoint synced after the most recent withdrawal to slot %d, and does not have the history required to generate a withdrawal proof" , slot )
754+ }
755+ continue
756+ } else {
757+ notFounds = 0
758+ }
759+
760+ beaconBlock , err := eth2 .NewSignedBeaconBlock (blockResponse .Data , blockResponse .Fork )
761+ if err != nil {
762+ return 0 , nil , 0 , nil , err
763+ }
764+
765+ if ! beaconBlock .HasExecutionPayload () {
766+ continue
767+ }
768+
769+ // Check the block for a withdrawal for the given validator index.
770+ for i , withdrawal := range beaconBlock .Withdrawals () {
771+ if withdrawal .ValidatorIndex != validatorIndex {
772+ continue
773+ }
774+
775+ return candidateSlot , beaconBlock , i , withdrawal , nil
776+ }
777+ }
778+ return 0 , nil , 0 , nil , fmt .Errorf ("no withdrawal found for validator index %d within %d slots of slot %d" , validatorIndex , MAX_WITHDRAWAL_SLOT_DISTANCE , slot )
779+ }
780+
773781func GetChildBlockTimestampForSlot (c * cli.Context , slot uint64 ) (uint64 , error ) {
774782 bc , err := GetBeaconClient (c )
775783 if err != nil {
0 commit comments