Skip to content

Commit

Permalink
Merge pull request #3772 from Joystream/rhodes-update-1
Browse files Browse the repository at this point in the history
Rhodes update 1
  • Loading branch information
mnaamani committed Jun 16, 2022
2 parents 451ff7c + bdec855 commit 5fbe3b7
Show file tree
Hide file tree
Showing 17 changed files with 236 additions and 158 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/runtime-upgrade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ jobs:
name: ${{ steps.compute_shasum.outputs.shasum }}-joystream-node-docker-image.tar.gz
path: joystream-node-docker-image.tar.gz

runtime_upgrade_from_olympia:
runtime_upgrade:
# if: ${{ false }}
name: Runtime Upgrade From Olypia
name: Runtime Upgrade From Rhodes Spec 6
needs: build_images
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -101,7 +101,7 @@ jobs:
export HOME=${PWD}
mkdir -p ${HOME}/.local/share/joystream-cli
yarn joystream-cli api:setUri ws://localhost:9944
# Olympia release production runtime profile
export RUNTIME_TAG=6740a4ae2bf40fe7c670fb49943cbbe290277601
# Rhodes release (spec 6) production runtime profile
export RUNTIME_TAG=8c2e70abcb34a6892991355b61e804b7c1492290
export TARGET_RUNTIME_TAG=latest
tests/network-tests/run-migration-tests.sh
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ authors = ['Joystream contributors']
build = 'build.rs'
edition = '2018'
name = 'joystream-node'
version = '6.6.0'
version = '6.7.0'
default-run = "joystream-node"

[[bin]]
Expand Down
16 changes: 8 additions & 8 deletions runtime-modules/content/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1275,7 +1275,7 @@ decl_module! {
) -> DispatchResult {
let channel = Self::ensure_channel_exists(&item.channel_id)?;

let reward_account = Self::ensure_reward_account(&channel)?;
let reward_account = Self::ensure_channel_has_beneficiary_account(&channel)?;

ensure_actor_authorized_to_claim_payment::<T>(origin, &actor, &channel.owner)?;

Expand Down Expand Up @@ -1662,7 +1662,7 @@ decl_module! {
let royalty_payment = Self::build_royalty_payment(&video, nft.creator_royalty);
let updated_nft = Self::complete_auction(
nft,
video.in_channel,
&video,
royalty_payment,
participant_id,
buy_now_price,
Expand Down Expand Up @@ -1770,7 +1770,7 @@ decl_module! {
let royalty_payment = Self::build_royalty_payment(&video, nft.creator_royalty);
let updated_nft = Self::complete_auction(
nft,
video.in_channel,
&video,
royalty_payment,
participant_id,
buy_now_price,
Expand Down Expand Up @@ -1882,7 +1882,7 @@ decl_module! {
let royalty_payment = Self::build_royalty_payment(&video, nft.creator_royalty);
let updated_nft = Self::complete_auction(
nft,
video.in_channel,
&video,
royalty_payment,
top_bidder_id,
top_bid.amount
Expand Down Expand Up @@ -1935,7 +1935,7 @@ decl_module! {
let royalty_payment = Self::build_royalty_payment(&video, nft.creator_royalty);
let updated_nft = Self::complete_auction(
nft,
video.in_channel,
&video,
royalty_payment,
winner_id,
bid.amount,
Expand Down Expand Up @@ -2046,7 +2046,7 @@ decl_module! {
Self::ensure_new_pending_offer_available_to_proceed(&nft, &receiver_account_id)?;

// account_id where the nft offer price is deposited
let nft_owner_account = Self::ensure_owner_account_id(video.in_channel, &nft).ok();
let nft_owner_account = Self::ensure_nft_owner_has_beneficiary_account(&video, &nft).ok();
//
// == MUTATION SAFE ==
//
Expand Down Expand Up @@ -2122,7 +2122,7 @@ decl_module! {
Self::ensure_can_buy_now(&nft, &participant_account_id, price_commit)?;

// seller account
let old_nft_owner_account_id = Self::ensure_owner_account_id(video.in_channel, &nft).ok();
let old_nft_owner_account_id = Self::ensure_nft_owner_has_beneficiary_account(&video, &nft).ok();

//
// == MUTATION SAFE ==
Expand Down Expand Up @@ -2428,7 +2428,7 @@ impl<T: Trait> Module<T> {
Ok(())
}

pub(crate) fn ensure_reward_account(
pub(crate) fn ensure_channel_has_beneficiary_account(
channel: &Channel<T>,
) -> Result<T::AccountId, DispatchError> {
if let Some(reward_account) = &channel.reward_account {
Expand Down
41 changes: 20 additions & 21 deletions runtime-modules/content/src/nft/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,12 @@ impl<T: Trait> Module<T> {

pub(crate) fn complete_auction(
nft: Nft<T>,
in_channel: T::ChannelId,
video: &Video<T>,
royalty_payment: Option<(Royalty, T::AccountId)>,
winner_id: T::MemberId,
amount: BalanceOf<T>,
) -> Nft<T> {
let account_deposit_into = Self::ensure_owner_account_id(in_channel, &nft).ok();
let account_deposit_into = Self::ensure_nft_owner_has_beneficiary_account(video, &nft).ok();
let account_withdraw_from = ContentTreasury::<T>::module_account_id();

Self::complete_payment(
Expand All @@ -382,15 +382,25 @@ impl<T: Trait> Module<T> {
.with_member_owner(winner_id)
}

pub(crate) fn ensure_owner_account_id(
channel_id: T::ChannelId,
/// NFT owned by:
/// - Member: member controller account is used
/// - Channel: then if reward account is:
/// - `Some(acc)` -> use `acc` as reward account
/// - `None` -> then if channel owner is:
/// - `Member` -> use member controller account
/// - `CuratorGroup` -> Error
/// In order to statically guarantee that `video.in_channel` exists, by leveraging the
/// Runtime invariant: `video` exists => `video.in_channel` exists
pub(crate) fn ensure_nft_owner_has_beneficiary_account(
video: &Video<T>,
nft: &Nft<T>,
) -> Result<T::AccountId, DispatchError> {
match nft.owner {
NftOwner::Member(member_id) => T::MemberAuthenticator::controller_account_id(member_id),
NftOwner::ChannelOwner => Self::channel_by_id(channel_id)
.reward_account
.ok_or_else(|| Error::<T>::RewardAccountIsNotSet.into()),
NftOwner::ChannelOwner => {
let channel = Self::channel_by_id(&video.in_channel);
Self::ensure_channel_has_beneficiary_account(&channel)
}
}
}

Expand Down Expand Up @@ -462,20 +472,9 @@ impl<T: Trait> Module<T> {
// payment is none if there is no royalty
if let Some(royalty) = creator_royalty {
let channel = Self::channel_by_id(&video.in_channel);
// use reward account if specified
if let Some(creator_reward_account) = channel.reward_account {
Some((royalty, creator_reward_account))
} else {
// otherwise resort to controller account for member owned channels
if let ChannelOwner::Member(member_id) = channel.owner {
T::MemberAuthenticator::controller_account_id(member_id)
.ok()
.map(|reward_account| (royalty, reward_account))
} else {
// no royalty paid for curator owned channel with unspecified reward account
None
}
}
Self::ensure_channel_has_beneficiary_account(&channel)
.ok()
.map(|reward_acc| (royalty, reward_acc))
} else {
None
}
Expand Down
3 changes: 2 additions & 1 deletion runtime-modules/content/src/tests/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,8 @@ impl ClaimChannelRewardFixture {
pub fn call_and_assert(&self, expected_result: DispatchResult) {
let origin = Origin::signed(self.sender.clone());
let channel = Content::channel_by_id(self.item.channel_id);
let reward_account = Content::ensure_reward_account(&channel).unwrap_or_default();
let reward_account =
Content::ensure_channel_has_beneficiary_account(&channel).unwrap_or_default();
let balance_pre = Balances::<Test>::usable_balance(&reward_account);
let payout_earned_pre =
Content::channel_by_id(self.item.channel_id).cumulative_payout_earned;
Expand Down
72 changes: 39 additions & 33 deletions runtime-modules/content/src/tests/nft/accept_incoming_offer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#![cfg(test)]
use crate::tests::curators;
use crate::tests::fixtures::{
create_default_member_owned_channel_with_video, create_initial_storage_buckets_helper,
increase_account_balance_helper, UpdateChannelFixture,
increase_account_balance_helper, CreateChannelFixture, CreateVideoFixture,
};
use crate::tests::mock::*;
use crate::*;
Expand Down Expand Up @@ -180,45 +181,50 @@ fn accept_incoming_offer_no_incoming_offers() {
}

#[test]
fn accept_incoming_offer_reward_account_is_not_set_succeeds_with_member_owner_channel() {
fn accept_incoming_offer_ok_with_reward_account_not_set_succeeds_with_member_owner_channel() {
let video_id = 1u64;
with_default_mock_builder(|| {
// Run to block one to see emitted events
run_to_block(1);

let video_id = NextVideoId::<Test>::get();
create_initial_storage_buckets_helper();
increase_account_balance_helper(DEFAULT_MEMBER_ACCOUNT_ID, INITIAL_BALANCE);
create_default_member_owned_channel_with_video();

UpdateChannelFixture::default()
// channel with no reward account
CreateChannelFixture::default()
.with_sender(DEFAULT_MEMBER_ACCOUNT_ID)
.with_actor(ContentActor::Member(DEFAULT_MEMBER_ID))
.call();
CreateVideoFixture::default()
.with_sender(DEFAULT_MEMBER_ACCOUNT_ID)
.with_actor(ContentActor::Member(DEFAULT_MEMBER_ID))
.with_reward_account(Some(None))
.call_and_assert(Ok(()));
.call();

// Issue nft
assert_ok!(Content::issue_nft(
Origin::signed(DEFAULT_MEMBER_ACCOUNT_ID),
ContentActor::Member(DEFAULT_MEMBER_ID),
video_id,
NftIssuanceParameters::<Test>::default(),
));

increase_account_balance_helper(SECOND_MEMBER_ACCOUNT_ID, DEFAULT_NFT_PRICE);

// Offer nft
assert_ok!(Content::offer_nft(
Origin::signed(DEFAULT_MEMBER_ACCOUNT_ID),
video_id,
ContentActor::Member(DEFAULT_MEMBER_ID),
SECOND_MEMBER_ID,
None,
Some(100u64), // price
));

// Make an attempt to accept incoming nft offer if sender is owner and reward account is not set
let accept_incoming_offer_result =
Content::accept_incoming_offer(Origin::signed(SECOND_MEMBER_ACCOUNT_ID), video_id);
assert_ok!(Content::accept_incoming_offer(
Origin::signed(SECOND_MEMBER_ACCOUNT_ID),
video_id
));

// Failure checked
assert_ok!(accept_incoming_offer_result,);
// check owner balance increased by net profit
assert_eq!(
Balances::<Test>::usable_balance(DEFAULT_MEMBER_ACCOUNT_ID),
100u64 - (Content::platform_fee_percentage() * 100u64)
);
})
}

Expand All @@ -228,31 +234,31 @@ fn accept_incoming_offer_reward_account_burns_token_with_curator_owner_channel()
// Run to block one to see emitted events
run_to_block(1);

let video_id = NextVideoId::<Test>::get();
create_initial_storage_buckets_helper();
increase_account_balance_helper(DEFAULT_MEMBER_ACCOUNT_ID, INITIAL_BALANCE);
increase_account_balance_helper(SECOND_MEMBER_ACCOUNT_ID, DEFAULT_NFT_PRICE);
create_default_member_owned_channel_with_video();
let curator_group_id = curators::add_curator_to_new_group(DEFAULT_CURATOR_ID);
let video_id = Content::next_video_id();
let curator_actor = ContentActor::Curator(curator_group_id, DEFAULT_CURATOR_ID);
CreateChannelFixture::default()
.with_sender(DEFAULT_CURATOR_ACCOUNT_ID)
.with_actor(curator_actor)
.call();
CreateVideoFixture::default()
.with_sender(DEFAULT_CURATOR_ACCOUNT_ID)
.with_actor(ContentActor::Curator(curator_group_id, DEFAULT_CURATOR_ID))
.call();

UpdateChannelFixture::default()
.with_sender(DEFAULT_MEMBER_ACCOUNT_ID)
.with_actor(ContentActor::Member(DEFAULT_MEMBER_ID))
.with_reward_account(Some(None))
.call_and_assert(Ok(()));

// Issue nft
assert_ok!(Content::issue_nft(
Origin::signed(DEFAULT_MEMBER_ACCOUNT_ID),
ContentActor::Member(DEFAULT_MEMBER_ID),
Origin::signed(DEFAULT_CURATOR_ACCOUNT_ID),
curator_actor,
video_id,
NftIssuanceParameters::<Test>::default(),
));

increase_account_balance_helper(SECOND_MEMBER_ACCOUNT_ID, DEFAULT_NFT_PRICE);
// Offer nft
assert_ok!(Content::offer_nft(
Origin::signed(DEFAULT_MEMBER_ACCOUNT_ID),
Origin::signed(DEFAULT_CURATOR_ACCOUNT_ID),
video_id,
ContentActor::Member(DEFAULT_MEMBER_ID),
curator_actor,
SECOND_MEMBER_ID,
Some(DEFAULT_NFT_PRICE),
));
Expand Down

0 comments on commit 5fbe3b7

Please sign in to comment.