您正在查看: 2019年5月

ScatterDesktop Backup

BackService 调用 saveFile

export default class BackupService {

    static async setBackupStrategy(strategy){
        const scatter = store.state.scatter.clone();
        scatter.settings.autoBackup = strategy;
        return store.dispatch(Actions.SET_SCATTER, scatter);
    }

    static async createBackup(){
        const location = getFolderLocation();
        if(! location) return false;

        await saveFile(location[0]);
    }

    static async setBackupLocation(){
        const location = getFolderLocation();
        if(!location) return false;
        const scatter = store.state.scatter.clone();
        scatter.settings.backupLocation = location[0];
        return store.dispatch(Actions.SET_SCATTER, scatter);
    }

    static async createAutoBackup(){
        if(!store.state.scatter || !store.state.scatter.settings) return;
        const strategy = store.state.scatter.settings.autoBackup;
        if(!strategy || !strategy.length || strategy === BACKUP_STRATEGIES.MANUAL) return;

        const backupLocation = store.state.scatter.settings.backupLocation;
        if(!backupLocation || !backupLocation.length) return false;


        await saveFile(backupLocation);
    }

}

写入备份文件

https://sourcegraph.com/github.com/GetScatter/ScatterDesktop@318ebfef6e383c6d2ca9d5016199b2b12a82c1a4/-/blob/src/services/BackupService.js#L12:18

const saveFile = (filepath) => {
    return new Promise(resolve => {
        const scatter = getLatestScatter();
        const date = new Date();
        const month = date.getUTCMonth();
        const year = date.getUTCFullYear();
        const salt = StorageService.getSalt();
        const file = scatter + '|SLT|' + salt;
        const name = `${filepath}/scatter__${store.state.scatter.hash.substr(0,4)}-${store.state.scatter.hash.slice(-4)}__${store.state.scatter.meta.version}__${month}-${year}.json`;
        try {
            fs.writeFileSync(name, file, 'utf-8');
            resolve(true);
        }
        catch(e) {
            console.error('Error saving file', e);
            resolve(false);
        }
    })
};

备份文件的内容

const scatter = getLatestScatter();
const salt = StorageService.getSalt();
const file = scatter + '|SLT|' + salt;
const getLatestScatter = () => StorageService.getScatter();

StorageService

https://sourcegraph.com/github.com/GetScatter/ScatterDesktop@318ebfef6e383c6d2ca9d5016199b2b12a82c1a4/-/blob/src/services/StorageService.js#L93

export default class StorageService {

    constructor(){}

    static async setScatter(scatter){
        return new Promise(async resolve => {
            clearSaveTimeouts();
            saveResolvers.push(resolve);
            safeSetScatter(scatter, resolve);
        })
    };

    static getScatter() {
        return scatterStorage().get('scatter');
    }

actions

https://sourcegraph.com/github.com/GetScatter/ScatterDesktop@318ebfef6e383c6d2ca9d5016199b2b12a82c1a4/-/blob/src/store/actions.js#L91

[Actions.SET_SCATTER]:async ({commit, state}, scatter) => {
        return new Promise(async resolve => {
            const process = Process.savingData();

            const seed = await ipcAsync('seed');
            const savable = AES.encrypt(scatter.savable(seed), seed);
            StorageService.setLocalScatter(savable);
            process.updateProgress(50);
            StorageService.setScatter(savable).then(() => {
                BackupService.createAutoBackup()
            });

            commit(Actions.SET_SCATTER, scatter);
            resolve(scatter);
            process.updateProgress(100);
        })
    },

其中的

const seed = await ipcAsync('seed');

是从

 [Actions.SET_SEED]:({commit}, password) => {
        return new Promise(async (resolve, reject) => {
            const [mnemonic, seed] = await PasswordService.seedPassword(password, true);
            resolve(mnemonic);
        })
    },

https://sourcegraph.com/github.com/GetScatter/ScatterDesktop@318ebfef6e383c6d2ca9d5016199b2b12a82c1a4/-/blob/src/services/PasswordService.js#L48

static async seedPassword(password, setToState = true){
        return new Promise(async (resolve, reject) => {
            try {
                let seed, mnemonic;
                if(password.split(' ').length >= 12) {
                    seed = await Mnemonic.mnemonicToSeed(password);
                    mnemonic = password;
                } else {
                    const [m, s] = await Mnemonic.generateMnemonic(password);
                    seed = s;
                    mnemonic = m;
                }

                if(setToState) ipcFaF('seeding', seed);
                resolve([mnemonic, seed]);
            } catch(e){
                resolve([null, null]);
            }
        })
    }

Scatter

https://sourcegraph.com/github.com/GetScatter/ScatterDesktop/-/blob/src/models/Scatter.js#L76:1

savable(seed){
        this.keychain.keypairs.map(keypair => keypair.encrypt(seed));

        const clone = this.clone();
        clone.keychain.identities.map(id => id.encrypt(seed));

        // Keychain is always stored encrypted.
        clone.encrypt(seed);

        return clone;
    }

Keychain

https://sourcegraph.com/github.com/GetScatter/ScatterDesktop@318ebfef6e383c6d2ca9d5016199b2b12a82c1a4/-/blob/src/models/Keychain.js#L20:1

static fromJson(json){
        let p = Object.assign(this.placeholder(), json);
        if(json.hasOwnProperty('keypairs')) p.keypairs = json.keypairs.map(x => Keypair.fromJson(x));
        if(json.hasOwnProperty('accounts')) p.accounts = json.accounts.map(x => Account.fromJson(x));
        if(json.hasOwnProperty('identities')) p.identities = json.identities.map(x => Identity.fromJson(x));
        if(json.hasOwnProperty('permissions')) p.permissions = json.permissions.map(x => Permission.fromJson(x));
        if(json.hasOwnProperty('apps')) p.apps = json.apps.map(x => AuthorizedApp.fromJson(x));
        return p;
    }

nodeos 输出log方式

https://github.com/EOSIO/fc/blob/a6f94bae0b2b4a0b68dc1db2677331cafa4716a5/src/log/logger_config.cpp#L24

 bool configure_logging( const logging_config& cfg )
   {
      try {
      static bool reg_console_appender = appender::register_appender<console_appender>( "console" );
      static bool reg_gelf_appender = appender::register_appender<gelf_appender>( "gelf" );
      get_logger_map().clear();
      get_appender_map().clear();

支持输出到 console 和 gelf 两种方式

gelf
https://sourcegraph.com/github.com/EOSIO/fc@a6f94bae0b2b4a0b68dc1db2677331cafa4716a5/-/blob/include/fc/log/gelf_appender.hpp

namespace fc 
{
  // Log appender that sends log messages in JSON format over UDP
  // https://www.graylog2.org/resources/gelf/specification
  class gelf_appender final : public appender 
  {
  public:
    struct config 
    {
      string endpoint = "127.0.0.1:12201";
      string host = "fc"; // the name of the host, source or application that sent this message (just passed through to GELF server)
    };

类似 https://github.com/mattwcole/gelf-extensions-logging

EOS 代币命名规则

constexpr explicit symbol_code( std::string_view str )
      :value(0)
      {
         if( str.size() > 7 ) {
            eosio::check( false, "string is too long to be a valid symbol_code" );
         }
         for( auto itr = str.rbegin(); itr != str.rend(); ++itr ) {
            if( *itr < 'A' || *itr > 'Z') {
               eosio::check( false, "only uppercase letters allowed in symbol_code string" );
            }
            value <<= 8;
            value |= *itr;
         }
      }

格式

<=7位,A-Z