STEEM internals #5: What Happens After You Press 'Promote' Button.

in #steem8 years ago (edited)

I wanted to understand how the post promotion works from the inside of the STEEM system and I followed the code to find it out. I hope that it will be also interesting for you. I will start the post from the point where you click the 'Promote' button on the 'Promote Post' pop up window.


Promote


When you click on the 'Promote' button the onSubmit() callback method is called with several parameters. This basically means: start doing something and return after some time when you finished. The 'back' suffix in callback means that another function will be called when the function that is called returns.

The full source code of the pop-up is available in PromotePost.jsx and I will just paste two fragments needed to understand the internals. Let's see what is inside of the onSubmit() callback:

onSubmit(e) {
        e.preventDefault(); <= prevent default browser operation (following the link)
        const {author, permlink, onClose} = this.props
        const {amount} = this.state
        this.setState({loading: true});
        console.log('-- PromotePost.onSubmit -->');
        this.props.dispatchSubmit({amount, asset: 'SBD', author, permlink, onClose,
            currentUser: this.props.currentUser, errorCallback: this.errorCallback});
    }

As you can see the amount of money to be transferred, author, permlink of the post and SBD currency values are extracted here from the window and passed as parameters to dispatchSubmit() function. Additionally the errorCallback is set. The errorCallback() function will be called when something bad happens. Let's look what is inside dispatchSubmit() function then:

dispatch => ({
        dispatchSubmit: ({amount, asset, author, permlink, currentUser, onClose, errorCallback}) => {
            const username = currentUser.get('username')
            const successCallback = () => {
                dispatch({type: 'global/GET_STATE', payload: {url: `@${username}/transfers`}}) // refresh transfer history
                onClose()
            }
            const operation = {
                from: username,
                to: 'null', amount: parseFloat(amount, 10).toFixed(3) + ' ' + asset,
                memo: `@${author}/${permlink}`,
                __config: {successMessage: 'You successfully promoted this post.'}
            }
            dispatch(transaction.actions.broadcastOperation({
                type: 'transfer',
                operation,
                successCallback,
                errorCallback
            }))
        }
    })

This may not be easy to follow I but what is the most important - a blockchain operation is defined here. This is an operation of transferring the funds in SBD currency to a @null account. This operation is then signed using your private key and broadcast to the STEEM network as a transaction. If a transaction is successful, the transfer history is immediately refreshed.

This was a submit part and now the STEEM node part. Please find below the code that detects that funds were transferred to the @null account:

 void operator()( const transfer_operation& op )const {
    if( op.to == STEEMIT_NULL_ACCOUNT && op.amount.symbol == SBD_SYMBOL )  {
       vector<string> part; part.reserve(4);
       auto path = op.memo; 
       boost::split( part, path, boost::is_any_of("/") );
       if( part[0].size() && part[0][0] == '@' ) {
          auto acnt = part[0].substr(1);
          auto perm = part[1];

          auto c = _db.find_comment( acnt, perm );
          if( c && c->parent_author.size() == 0 ) {
             const auto& comment_idx = _db.get_index_type<tag_index>().indices().get<by_comment>();
             auto citr = comment_idx.lower_bound( c->id );
             while( citr != comment_idx.end() && citr->comment == c->id ) {
                _db.modify( *citr, [&]( tag_object& t ) {
                    if( t.mode == first_payout )
                        t.promoted_balance += op.amount.amount;
                });
                ++citr; 
             }
          } else {
             ilog( "unable to find body" );
          }
       }
    }
 }

This may be also hard to follow therefore I will try to provide high level description. At first the code detects if transfer operation was submitted to the @null account and if the transfer currency is SBD. If this is the case decode 'memo' part of the operation. This is where the real destination account and post title are submitted. The format of the memo is:

account_name@the-post-that-will-be-promoted

This memo is split into two parts and the funds are added to the post directly in this part:

_db.modify( *citr, [&]( tag_object& t ) {
        if( t.mode == first_payout )
                t.promoted_balance += op.amount.amount;
        });

This is where the code modifies blockchain database and adds transaction amount to the promoted_balance instance variable. Here you can also see that the balance is only added when the first_payout is active. You have just seen how the post is promoted! ;)

If you see this code there is an interesting discovery to be made. The post can be also promoted by manually creating a blockchain transaction with SBD funds transfer operation to @null account. The transaction should contain properly formed operation memo section with account and post name separated by '@' and then be broadcast to the STEEM network for processing.

And I guess that is enough for today. I hope that you enjoyed my post.


DISCLAIMER: THE INFORMATION IS DELIVERED FREE OF CHARGE AND 'AS IS' WITHOUT WARRANTY OF ANY KIND. I HOPE IT IS ACCURATE AND FREE OF ERRORS AND YOU FIND IT USEFUL.

Coin Marketplace

STEEM 0.16
TRX 0.15
JST 0.028
BTC 56835.87
ETH 2399.86
USDT 1.00
SBD 2.39