Skip to content

Commit 108ed20

Browse files
fakedev9999junha1
authored andcommitted
Implement create_extra_agenda_transaction
1 parent 3db817d commit 108ed20

File tree

1 file changed

+83
-2
lines changed

1 file changed

+83
-2
lines changed

repository/src/lib.rs

+83-2
Original file line numberDiff line numberDiff line change
@@ -766,8 +766,89 @@ impl<T: RawRepository> DistributedRepository<T> {
766766
/// Creates an extra-agenda transaction commit on top of the `work` branch.
767767
pub async fn create_extra_agenda_transaction(
768768
&mut self,
769-
_transaction: &ExtraAgendaTransaction,
769+
transaction: &ExtraAgendaTransaction,
770770
) -> Result<CommitHash, Error> {
771-
unimplemented!()
771+
let work_commit = self.raw.locate_branch(WORK_BRANCH_NAME.into()).await?;
772+
let last_header_commit = self.raw.locate_branch(FINALIZED_BRANCH_NAME.into()).await?;
773+
let reserved_state = self.get_reserved_state().await?;
774+
775+
// Check if the `work` branch is rebased on top of the `finalized` branch.
776+
if self
777+
.raw
778+
.find_merge_base(last_header_commit, work_commit)
779+
.await?
780+
!= last_header_commit
781+
{
782+
return Err(eyre!(
783+
"branch {} should be rebased on {}",
784+
WORK_BRANCH_NAME,
785+
FINALIZED_BRANCH_NAME
786+
));
787+
}
788+
789+
// Construct a commit list starting from the next commit of the last finalized block to the `branch_commit`(the most recent commit of the branch)
790+
let ancestor_commits = self.raw.list_ancestors(work_commit, Some(256)).await?;
791+
let position = ancestor_commits
792+
.iter()
793+
.position(|c| *c == last_header_commit)
794+
.expect("TODO: handle the case where it exceeds the limit.");
795+
let commits = stream::iter(ancestor_commits.iter().take(position).rev().cloned().map(
796+
|c| {
797+
let raw = &self.raw;
798+
async move { raw.read_semantic_commit(c).await.map(|x| (x, c)) }
799+
},
800+
))
801+
.buffered(256)
802+
.collect::<Vec<_>>()
803+
.await;
804+
let mut commits = commits.into_iter().collect::<Result<Vec<_>, _>>()?;
805+
// Add most recent commit of the branch to the list since it is not included in the ancestor commits
806+
commits.push((
807+
self.raw.read_semantic_commit(work_commit).await?,
808+
work_commit,
809+
));
810+
let commits = commits
811+
.into_iter()
812+
.map(|(commit, hash)| {
813+
from_semantic_commit(commit, reserved_state.clone())
814+
.map_err(|e| (e, hash))
815+
.map(|x| (x, hash))
816+
})
817+
.collect::<Result<Vec<_>, _>>()
818+
.map_err(|(error, hash)| eyre!("failed to convert the commit {}: {}", hash, error))?;
819+
820+
// Check the validity of the commit sequence
821+
let last_header = self.get_last_finalized_block_header().await?;
822+
let mut verifier = CommitSequenceVerifier::new(last_header.clone(), reserved_state.clone())
823+
.map_err(|e| eyre!("verification error on commit {}: {}", last_header_commit, e))?;
824+
for (commit, hash) in commits.iter() {
825+
verifier
826+
.apply_commit(commit)
827+
.map_err(|e| eyre!("verification error on commit {}: {}", hash, e))?;
828+
}
829+
830+
// Check whether the commit sequence is in agenda proof phase or extra-agenda transaction phase
831+
let (last_commit, _) = commits
832+
.last()
833+
.ok_or_else(|| eyre!("work branch does not contain any commit"))?;
834+
match last_commit {
835+
Commit::AgendaProof(_) => {}
836+
Commit::ExtraAgendaTransaction(_) => {}
837+
x => {
838+
return Err(eyre!(
839+
"an extra-agenda transaction commit cannot be created on top of a commit of type {:?}",
840+
x
841+
))
842+
}
843+
}
844+
845+
let extra_agenda_tx_commit = Commit::ExtraAgendaTransaction(transaction.clone());
846+
847+
let semantic_commit = to_semantic_commit(&extra_agenda_tx_commit, reserved_state)?;
848+
849+
self.raw.checkout_clean().await?;
850+
self.raw.checkout(WORK_BRANCH_NAME.into()).await?;
851+
let result = self.raw.create_semantic_commit(semantic_commit).await?;
852+
Ok(result)
772853
}
773854
}

0 commit comments

Comments
 (0)