コード例 #1
0
  /**
   * Add a wallet to the BlockChain. Note that the wallet will be unaffected by any blocks received
   * while it was not part of this BlockChain. This method is useful if the wallet has just been
   * created, and its keys have never been in use, or if the wallet has been loaded along with the
   * BlockChain. Note that adding multiple wallets is not well tested!
   */
  public void addWallet(Wallet wallet) {
    addListener(wallet, Threading.SAME_THREAD);
    int walletHeight = wallet.getLastBlockSeenHeight();
    int chainHeight = getBestChainHeight();
    if (walletHeight != chainHeight) {
      log.warn("Wallet/chain height mismatch: {} vs {}", walletHeight, chainHeight);
      log.warn(
          "Hashes: {} vs {}", wallet.getLastBlockSeenHash(), getChainHead().getHeader().getHash());

      // This special case happens when the VM crashes because of a transaction received. It causes
      // the updated
      // block store to persist, but not the wallet. In order to fix the issue, we roll back the
      // block store to
      // the wallet height to make it look like as if the block has never been received.
      if (walletHeight < chainHeight && walletHeight > 0) {
        try {
          rollbackBlockStore(walletHeight);
          log.info("Rolled back block store to height {}.", walletHeight);
        } catch (BlockStoreException x) {
          log.warn(
              "Rollback of block store failed, continuing with mismatched heights. This can happen due to a replay.");
        }
      }
    }
  }
コード例 #2
0
 private void loadExtensions(
     Wallet wallet, WalletExtension[] extensionsList, Protos.Wallet walletProto)
     throws UnreadableWalletException {
   final Map<String, WalletExtension> extensions = new HashMap<String, WalletExtension>();
   for (WalletExtension e : extensionsList) extensions.put(e.getWalletExtensionID(), e);
   // The Wallet object, if subclassed, might have added some extensions to itself already. In that
   // case, don't
   // expect them to be passed in, just fetch them here and don't re-add.
   extensions.putAll(wallet.getExtensions());
   for (Protos.Extension extProto : walletProto.getExtensionList()) {
     String id = extProto.getId();
     WalletExtension extension = extensions.get(id);
     if (extension == null) {
       if (extProto.getMandatory()) {
         if (requireMandatoryExtensions)
           throw new UnreadableWalletException("Unknown mandatory extension in wallet: " + id);
         else log.error("Unknown extension in wallet {}, ignoring", id);
       }
     } else {
       log.info("Loading wallet extension {}", id);
       try {
         extension.deserializeWalletExtension(wallet, extProto.getData().toByteArray());
         wallet.addOrGetExistingExtension(extension);
       } catch (Exception e) {
         if (extProto.getMandatory() && requireMandatoryExtensions)
           throw new UnreadableWalletException(
               "Could not parse mandatory extension in wallet: " + id);
         else log.error("Error whilst reading extension {}, ignoring", id, e);
       }
     }
   }
 }
コード例 #3
0
 private void scanTransaction(StoredBlock block, Transaction tx, NewBlockType blockType)
     throws ScriptException, VerificationException {
   // Coinbase transactions don't have anything useful in their inputs (as they create coins out of
   // thin air).
   if (tx.isMine(wallet) && !tx.isCoinBase()) {
     System.out.println("======> RECEIVING" + tx.toString());
     wallet.receive(tx, block, blockType);
   }
 }
コード例 #4
0
 private static void populateExtensions(Wallet wallet, Protos.Wallet.Builder walletBuilder) {
   for (WalletExtension extension : wallet.getExtensions().values()) {
     Protos.Extension.Builder proto = Protos.Extension.newBuilder();
     proto.setId(extension.getWalletExtensionID());
     proto.setMandatory(extension.isWalletExtensionMandatory());
     proto.setData(ByteString.copyFrom(extension.serializeWalletExtension()));
     walletBuilder.addExtension(proto);
   }
 }
コード例 #5
0
 private void OrderFood() {
   choice = name.toLowerCase();
   int count = 0;
   while (!menu.menuList.contains(choice)
       || unavailableFood.contains(choice)
       || (menu.menuItems.get(choice) > wallet.getAmt() && !name.equalsIgnoreCase("bad"))) {
     if (count == menu.menuList.size()) {
       state = AgentState.Leaving;
       eatingSuccess = false;
       LeaveRestaurant();
       return;
     }
     //	Random rand = new Random(System.currentTimeMillis());
     //	int det = Math.abs(rand.nextInt()%(menu.menuList.size()));
     choice = menu.menuList.get(count++);
     Do("" + choice);
   }
   waiter.msgHereIsMyChoice(this, choice);
   customerGui.setText(choice + "?");
 }
コード例 #6
0
 /**
  * Called as part of connecting a block when the new block results in a different chain having
  * higher total work.
  */
 private void handleNewBestChain(StoredBlock newChainHead)
     throws BlockStoreException, VerificationException {
   // This chain has overtaken the one we currently believe is best. Reorganize is required.
   //
   // Firstly, calculate the block at which the chain diverged. We only need to examine the
   // chain from beyond this block to find differences.
   StoredBlock splitPoint = findSplit(newChainHead, chainHead);
   log.info("Re-organize after split at height {}", splitPoint.getHeight());
   log.info("Old chain head: {}", chainHead.getHeader().getHashAsString());
   log.info("New chain head: {}", newChainHead.getHeader().getHashAsString());
   log.info("Split at block: {}", splitPoint.getHeader().getHashAsString());
   // Then build a list of all blocks in the old part of the chain and the new part.
   List<StoredBlock> oldBlocks = getPartialChain(chainHead, splitPoint);
   List<StoredBlock> newBlocks = getPartialChain(newChainHead, splitPoint);
   // Now inform the wallet. This is necessary so the set of currently active transactions (that we
   // can spend)
   // can be updated to take into account the re-organize. We might also have received new coins we
   // didn't have
   // before and our previous spends might have been undone.
   wallet.reorganize(oldBlocks, newBlocks);
   // Update the pointer to the best known block.
   setChainHead(newChainHead);
 }
コード例 #7
0
  /**
   * Loads wallet data from the given protocol buffer and inserts it into the given Wallet object.
   * This is primarily useful when you wish to pre-register extension objects. Note that if loading
   * fails the provided Wallet object may be in an indeterminate state and should be thrown away.
   *
   * <p>A wallet can be unreadable for various reasons, such as inability to open the file, corrupt
   * data, internally inconsistent data, a wallet extension marked as mandatory that cannot be
   * handled and so on. You should always handle {@link UnreadableWalletException} and communicate
   * failure to the user in an appropriate manner.
   *
   * @throws UnreadableWalletException thrown in various error conditions (see description).
   */
  public Wallet readWallet(
      NetworkParameters params, @Nullable WalletExtension[] extensions, Protos.Wallet walletProto)
      throws UnreadableWalletException {
    if (walletProto.getVersion() > 1) throw new UnreadableWalletException.FutureVersion();
    if (!walletProto.getNetworkIdentifier().equals(params.getId()))
      throw new UnreadableWalletException.WrongNetwork();

    int sigsRequiredToSpend = walletProto.getSigsRequiredToSpend();

    // Read the scrypt parameters that specify how encryption and decryption is performed.
    KeyChainGroup chain;
    if (walletProto.hasEncryptionParameters()) {
      Protos.ScryptParameters encryptionParameters = walletProto.getEncryptionParameters();
      final KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(encryptionParameters);
      chain =
          KeyChainGroup.fromProtobufEncrypted(
              params, walletProto.getKeyList(), sigsRequiredToSpend, keyCrypter);
    } else {
      chain =
          KeyChainGroup.fromProtobufUnencrypted(
              params, walletProto.getKeyList(), sigsRequiredToSpend);
    }
    Wallet wallet = factory.create(params, chain);

    List<Script> scripts = Lists.newArrayList();
    for (Protos.Script protoScript : walletProto.getWatchedScriptList()) {
      try {
        Script script =
            new Script(
                protoScript.getProgram().toByteArray(), protoScript.getCreationTimestamp() / 1000);
        scripts.add(script);
      } catch (ScriptException e) {
        throw new UnreadableWalletException("Unparseable script in wallet");
      }
    }

    wallet.addWatchedScripts(scripts);

    if (walletProto.hasDescription()) {
      wallet.setDescription(walletProto.getDescription());
    }

    // Read all transactions and insert into the txMap.
    for (Protos.Transaction txProto : walletProto.getTransactionList()) {
      readTransaction(txProto, wallet.getParams());
    }

    // Update transaction outputs to point to inputs that spend them
    for (Protos.Transaction txProto : walletProto.getTransactionList()) {
      WalletTransaction wtx = connectTransactionOutputs(txProto);
      wallet.addWalletTransaction(wtx);
    }

    // Update the lastBlockSeenHash.
    if (!walletProto.hasLastSeenBlockHash()) {
      wallet.setLastBlockSeenHash(null);
    } else {
      wallet.setLastBlockSeenHash(byteStringToHash(walletProto.getLastSeenBlockHash()));
    }
    if (!walletProto.hasLastSeenBlockHeight()) {
      wallet.setLastBlockSeenHeight(-1);
    } else {
      wallet.setLastBlockSeenHeight(walletProto.getLastSeenBlockHeight());
    }
    // Will default to zero if not present.
    wallet.setLastBlockSeenTimeSecs(walletProto.getLastSeenBlockTimeSecs());

    if (walletProto.hasKeyRotationTime()) {
      wallet.setKeyRotationTime(new Date(walletProto.getKeyRotationTime() * 1000));
    }

    loadExtensions(wallet, extensions != null ? extensions : new WalletExtension[0], walletProto);

    for (Protos.Tag tag : walletProto.getTagsList()) {
      wallet.setTag(tag.getTag(), tag.getData());
    }

    for (Protos.TransactionSigner signerProto : walletProto.getTransactionSignersList()) {
      try {
        Class signerClass = Class.forName(signerProto.getClassName());
        TransactionSigner signer = (TransactionSigner) signerClass.newInstance();
        signer.deserialize(signerProto.getData().toByteArray());
        wallet.addTransactionSigner(signer);
      } catch (Exception e) {
        throw new UnreadableWalletException(
            "Unable to deserialize TransactionSigner instance: " + signerProto.getClassName(), e);
      }
    }

    if (walletProto.hasVersion()) {
      wallet.setVersion(walletProto.getVersion());
    }

    // Make sure the object can be re-used to read another wallet without corruption.
    txMap.clear();

    return wallet;
  }
コード例 #8
0
  /**
   * Converts the given wallet to the object representation of the protocol buffers. This can be
   * modified, or additional data fields set, before serialization takes place.
   */
  public Protos.Wallet walletToProto(Wallet wallet) {
    Protos.Wallet.Builder walletBuilder = Protos.Wallet.newBuilder();
    walletBuilder.setNetworkIdentifier(wallet.getNetworkParameters().getId());
    if (wallet.getDescription() != null) {
      walletBuilder.setDescription(wallet.getDescription());
    }

    for (WalletTransaction wtx : wallet.getWalletTransactions()) {
      Protos.Transaction txProto = makeTxProto(wtx);
      walletBuilder.addTransaction(txProto);
    }

    walletBuilder.addAllKey(wallet.serializeKeychainToProtobuf());

    for (Script script : wallet.getWatchedScripts()) {
      Protos.Script protoScript =
          Protos.Script.newBuilder()
              .setProgram(ByteString.copyFrom(script.getProgram()))
              .setCreationTimestamp(script.getCreationTimeSeconds() * 1000)
              .build();

      walletBuilder.addWatchedScript(protoScript);
    }

    // Populate the lastSeenBlockHash field.
    Sha256Hash lastSeenBlockHash = wallet.getLastBlockSeenHash();
    if (lastSeenBlockHash != null) {
      walletBuilder.setLastSeenBlockHash(hashToByteString(lastSeenBlockHash));
      walletBuilder.setLastSeenBlockHeight(wallet.getLastBlockSeenHeight());
    }
    if (wallet.getLastBlockSeenTimeSecs() > 0)
      walletBuilder.setLastSeenBlockTimeSecs(wallet.getLastBlockSeenTimeSecs());

    // Populate the scrypt parameters.
    KeyCrypter keyCrypter = wallet.getKeyCrypter();
    if (keyCrypter == null) {
      // The wallet is unencrypted.
      walletBuilder.setEncryptionType(EncryptionType.UNENCRYPTED);
    } else {
      // The wallet is encrypted.
      walletBuilder.setEncryptionType(keyCrypter.getUnderstoodEncryptionType());
      if (keyCrypter instanceof KeyCrypterScrypt) {
        KeyCrypterScrypt keyCrypterScrypt = (KeyCrypterScrypt) keyCrypter;
        walletBuilder.setEncryptionParameters(keyCrypterScrypt.getScryptParameters());
      } else {
        // Some other form of encryption has been specified that we do not know how to persist.
        throw new RuntimeException(
            "The wallet has encryption of type '"
                + keyCrypter.getUnderstoodEncryptionType()
                + "' but this WalletProtobufSerializer does not know how to persist this.");
      }
    }

    if (wallet.getKeyRotationTime() != null) {
      long timeSecs = wallet.getKeyRotationTime().getTime() / 1000;
      walletBuilder.setKeyRotationTime(timeSecs);
    }

    populateExtensions(wallet, walletBuilder);

    for (Map.Entry<String, ByteString> entry : wallet.getTags().entrySet()) {
      Protos.Tag.Builder tag =
          Protos.Tag.newBuilder().setTag(entry.getKey()).setData(entry.getValue());
      walletBuilder.addTags(tag);
    }

    for (TransactionSigner signer : wallet.getTransactionSigners()) {
      // do not serialize LocalTransactionSigner as it's being added implicitly
      if (signer instanceof LocalTransactionSigner) continue;
      Protos.TransactionSigner.Builder protoSigner = Protos.TransactionSigner.newBuilder();
      protoSigner.setClassName(signer.getClass().getName());
      protoSigner.setData(ByteString.copyFrom(signer.serialize()));
      walletBuilder.addTransactionSigners(protoSigner);
    }

    walletBuilder.setSigsRequiredToSpend(wallet.getSigsRequiredToSpend());

    // Populate the wallet version.
    walletBuilder.setVersion(wallet.getVersion());

    return walletBuilder.build();
  }
コード例 #9
0
  /** Scheduler. Determine what action is called for, and do it. */
  protected boolean pickAndExecuteAnAction() {
    //	CustomerAgent is a finite state machine
    try {
      if (state == AgentState.DoingNothing && event == AgentEvent.gotHungry) {
        if (host.isFull() && name.equalsIgnoreCase("wait")) {
          customerGui.setEnabled();
          customerGui.DoExitRestaurant();
          return true;
        }
        state = AgentState.Waiting;
        GoToRestaurant();
        return true;
      }
      if (state == AgentState.Waiting && event == AgentEvent.followHost) {
        state = AgentState.BeingSeated;
        SitDown();
        return true;
      }
      if (state == AgentState.BeingSeated && event == AgentEvent.seated) {
        state = AgentState.Seated;

        return true;
      }
      if (state == AgentState.Seated && event == AgentEvent.orderFood) {
        state = AgentState.Ordered;
        OrderFood();
        return true;
      }
      if (state == AgentState.Ordered && event == AgentEvent.orderTaken) {
        state = AgentState.WaitingForOrder;
        return true;
      }
      if (state == AgentState.WaitingForOrder && event == AgentEvent.foodArrived) {
        state = AgentState.Eating;
        EatFood();
        return true;
      }

      if (state == AgentState.Eating && event == AgentEvent.doneEating) {
        state = AgentState.WaitingForCheck;
        customerGui.setText("");
        waiter.msgDoneEating(this);
        return true;
      }
      if (state == AgentState.WaitingForCheck && event == AgentEvent.rcvdCheck) {
        state = AgentState.Paying;
        LeaveTableToGoPay();
        return true;
      }
      if (state == AgentState.Paying && event == AgentEvent.arrivedAtCashier) {
        host.cashier.msgHereIsMoney(this, wallet.getAmt());
        return true;
      }
      if (state == AgentState.Paying && event == AgentEvent.doDishes) {
        DoDishes();
        return true;
      }
      if (state == AgentState.Paying && event == AgentEvent.donePaying) {
        state = AgentState.Leaving;
        eatingSuccess = true;
        LeaveRestaurant();
        return true;
      }
      if (state == AgentState.Leaving && event == AgentEvent.doneLeaving) {
        state = AgentState.DoingNothing;
        //				person.msgDoneEating(eatingSuccess, wallet.getAmt()); // COMMENT THIS OUT IF THERE
        // AREN'T REAL PEOPLE IN THE RESTAURANT
        waiter.msgDoneLeaving(this);
        return true;
      }
      return false;
    } catch (ConcurrentModificationException e) {
      return false;
    }
  }
コード例 #10
0
 public void msgHereIsChange(double amt) {
   event = AgentEvent.donePaying;
   wallet.update(amt);
   stateChanged();
 }