List of usage examples for java.math BigInteger add
BigInteger add(long val)
From source file:com.netscape.cms.servlet.csadmin.ConfigurationUtils.java
public static void updateNextRanges() throws EBaseException, LDAPException { IConfigStore cs = CMS.getConfigStore(); String endRequestNumStr = cs.getString("dbs.endRequestNumber", ""); String endSerialNumStr = cs.getString("dbs.endSerialNumber", ""); String type = cs.getString("cs.type"); String basedn = cs.getString("internaldb.basedn"); BigInteger endRequestNum = new BigInteger(endRequestNumStr); BigInteger endSerialNum = new BigInteger(endSerialNumStr); BigInteger oneNum = new BigInteger("1"); // update global next range entries IConfigStore dbCfg = cs.getSubStore("internaldb"); ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory("ConfigurationUtils"); dbFactory.init(dbCfg);/*from ww w .j a v a2 s.co m*/ LDAPConnection conn = dbFactory.getConn(); String serialdn = ""; if (type.equals("CA")) { serialdn = "ou=certificateRepository,ou=" + LDAPUtil.escapeRDNValue(type.toLowerCase()) + "," + basedn; } else { serialdn = "ou=keyRepository,ou=" + LDAPUtil.escapeRDNValue(type.toLowerCase()) + "," + basedn; } LDAPAttribute attrSerialNextRange = new LDAPAttribute("nextRange", endSerialNum.add(oneNum).toString()); LDAPModification serialmod = new LDAPModification(LDAPModification.REPLACE, attrSerialNextRange); conn.modify(serialdn, serialmod); String requestdn = "ou=" + LDAPUtil.escapeRDNValue(type.toLowerCase()) + ",ou=requests," + basedn; LDAPAttribute attrRequestNextRange = new LDAPAttribute("nextRange", endRequestNum.add(oneNum).toString()); LDAPModification requestmod = new LDAPModification(LDAPModification.REPLACE, attrRequestNextRange); conn.modify(requestdn, requestmod); conn.disconnect(); }
From source file:org.proteomecommons.tranche.cacheupdater.CacheUpdater.java
private void populateHashesSet() { log.println("Discovering known servers"); // wait for bootup ServerUtil.waitForStartup();/* ww w .j a v a2 s .c o m*/ // add the servers for (ServerInfo server : ServerUtil.getServers()) { log.println("Adding server to list: " + server.getUrl()); servers.add(server.getUrl()); } // get the second level servers that haven't already been checked HashSet<String> secondaryServers = new HashSet<String>(); for (String server : servers) { ServerInfo si = ServerUtil.getServerInfo(server); secondaryServers.addAll(si.getKnownServers()); } // add all the secondary servers to the list of servers for (String url : secondaryServers) { if (!servers.contains(url)) { log.println("Adding secondary server to list: " + url); servers.add(url); } } log.println("Finished discovering servers."); Thread t = new Thread("Cache Updater Hash Finder") { public void run() { List<Thread> threadList = new ArrayList<Thread>(); for (final String server : servers) { Thread s = new Thread("Cache Updater Hash Finder: " + server) { public void run() { try { log.println("Connecting to " + server); // bootstrap ServerUtil.isServerOnline(server); // connect to the server TrancheServer ts = IOUtil.connect(server); try { // get all of the projects BigInteger limit = BigInteger.valueOf(100); BigInteger offset = BigInteger.ZERO; // get the hashes for (BigHash[] serverHashes = ts.getProjectHashes(offset, limit); serverHashes.length > 0; serverHashes = ts .getProjectHashes(offset, limit)) { // increment the offset offset = offset.add(BigInteger.valueOf(serverHashes.length)); // add each hash for (BigHash hash : serverHashes) { synchronized (hashesOnNetwork) { hashesOnNetwork.add(hash); } } } } finally { IOUtil.safeClose(ts); } } catch (Exception e) { log.println("ERROR: Could not get project hashes from " + server); err.println(server + ": " + e.getMessage()); } } }; s.start(); threadList.add(s); } for (Thread t : threadList) { try { t.join(); } catch (Exception e) { } } } }; t.start(); // move on after three minutes of looking try { t.join(3 * 60 * 1000); } catch (Exception e) { } log.println(hashesOnNetwork.size() + " project hashes discovered."); }
From source file:org.alfresco.mobile.android.api.network.NetworkHttpInvoker.java
protected Response invoke(UrlBuilder url, String method, String contentType, Map<String, String> headers, Output writer, BindingSession session, BigInteger offset, BigInteger length) { try {//from w w w. j a va2s. co m // log before connect //Log.d("URL", url.toString()); if (LOG.isDebugEnabled()) { LOG.debug(method + " " + url); } // connect HttpURLConnection conn = getHttpURLConnection(new URL(url.toString())); conn.setRequestMethod(method); conn.setDoInput(true); conn.setDoOutput(writer != null); conn.setAllowUserInteraction(false); conn.setUseCaches(false); conn.setRequestProperty(HTTP.USER_AGENT, ClientVersion.OPENCMIS_CLIENT); // timeouts int connectTimeout = session.get(SessionParameter.CONNECT_TIMEOUT, -1); if (connectTimeout >= 0) { conn.setConnectTimeout(connectTimeout); } int readTimeout = session.get(SessionParameter.READ_TIMEOUT, -1); if (readTimeout >= 0) { conn.setReadTimeout(readTimeout); } // set content type if (contentType != null) { conn.setRequestProperty(HTTP.CONTENT_TYPE, contentType); } // set other headers if (headers != null) { for (Map.Entry<String, String> header : headers.entrySet()) { conn.addRequestProperty(header.getKey(), header.getValue()); } } // authenticate AuthenticationProvider authProvider = CmisBindingsHelper.getAuthenticationProvider(session); if (authProvider != null) { Map<String, List<String>> httpHeaders = authProvider.getHTTPHeaders(url.toString()); if (httpHeaders != null) { for (Map.Entry<String, List<String>> header : httpHeaders.entrySet()) { if (header.getValue() != null) { for (String value : header.getValue()) { conn.addRequestProperty(header.getKey(), value); } } } } if (conn instanceof HttpsURLConnection) { SSLSocketFactory sf = authProvider.getSSLSocketFactory(); if (sf != null) { ((HttpsURLConnection) conn).setSSLSocketFactory(sf); } HostnameVerifier hv = authProvider.getHostnameVerifier(); if (hv != null) { ((HttpsURLConnection) conn).setHostnameVerifier(hv); } } } // range if ((offset != null) || (length != null)) { StringBuilder sb = new StringBuilder("bytes="); if ((offset == null) || (offset.signum() == -1)) { offset = BigInteger.ZERO; } sb.append(offset.toString()); sb.append("-"); if ((length != null) && (length.signum() == 1)) { sb.append(offset.add(length.subtract(BigInteger.ONE)).toString()); } conn.setRequestProperty("Range", sb.toString()); } // compression Object compression = session.get(AlfrescoSession.HTTP_ACCEPT_ENCODING); if (compression == null) { conn.setRequestProperty("Accept-Encoding", ""); } else { Boolean compressionValue; try { compressionValue = Boolean.parseBoolean(compression.toString()); if (compressionValue) { conn.setRequestProperty("Accept-Encoding", "gzip,deflate"); } else { conn.setRequestProperty("Accept-Encoding", ""); } } catch (Exception e) { conn.setRequestProperty("Accept-Encoding", compression.toString()); } } // locale if (session.get(AlfrescoSession.HTTP_ACCEPT_LANGUAGE) instanceof String && session.get(AlfrescoSession.HTTP_ACCEPT_LANGUAGE) != null) { conn.setRequestProperty("Accept-Language", session.get(AlfrescoSession.HTTP_ACCEPT_LANGUAGE).toString()); } // send data if (writer != null) { Object chunkTransfert = session.get(AlfrescoSession.HTTP_CHUNK_TRANSFERT); if (chunkTransfert != null && Boolean.parseBoolean(chunkTransfert.toString())) { conn.setRequestProperty(HTTP.TRANSFER_ENCODING, "chunked"); conn.setChunkedStreamingMode(0); } conn.setConnectTimeout(900000); OutputStream connOut = null; Object clientCompression = session.get(SessionParameter.CLIENT_COMPRESSION); if ((clientCompression != null) && Boolean.parseBoolean(clientCompression.toString())) { conn.setRequestProperty(HTTP.CONTENT_ENCODING, "gzip"); connOut = new GZIPOutputStream(conn.getOutputStream(), 4096); } else { connOut = conn.getOutputStream(); } OutputStream out = new BufferedOutputStream(connOut, BUFFER_SIZE); writer.write(out); out.flush(); } // connect conn.connect(); // get stream, if present int respCode = conn.getResponseCode(); InputStream inputStream = null; if ((respCode == HttpStatus.SC_OK) || (respCode == HttpStatus.SC_CREATED) || (respCode == HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION) || (respCode == HttpStatus.SC_PARTIAL_CONTENT)) { inputStream = conn.getInputStream(); } // log after connect if (LOG.isTraceEnabled()) { LOG.trace(method + " " + url + " > Headers: " + conn.getHeaderFields()); } // forward response HTTP headers if (authProvider != null) { authProvider.putResponseHeaders(url.toString(), respCode, conn.getHeaderFields()); } // get the response return new Response(respCode, conn.getResponseMessage(), conn.getHeaderFields(), inputStream, conn.getErrorStream()); } catch (Exception e) { throw new CmisConnectionException("Cannot access " + url + ": " + e.getMessage(), e); } }
From source file:org.apache.chemistry.opencmis.client.bindings.spi.http.AbstractApacheClientHttpInvoker.java
protected Response invoke(UrlBuilder url, String method, String contentType, Map<String, String> headers, final Output writer, final BindingSession session, BigInteger offset, BigInteger length) { int respCode = -1; try {/*from www . jav a 2 s. c o m*/ // log before connect if (LOG.isDebugEnabled()) { LOG.debug("Session {}: {} {}", session.getSessionId(), method, url); } // get HTTP client object from session DefaultHttpClient httpclient = (DefaultHttpClient) session.get(HTTP_CLIENT); if (httpclient == null) { session.writeLock(); try { httpclient = (DefaultHttpClient) session.get(HTTP_CLIENT); if (httpclient == null) { httpclient = createHttpClient(url, session); session.put(HTTP_CLIENT, httpclient, true); } } finally { session.writeUnlock(); } } HttpRequestBase request = null; if ("GET".equals(method)) { request = new HttpGet(url.toString()); } else if ("POST".equals(method)) { request = new HttpPost(url.toString()); } else if ("PUT".equals(method)) { request = new HttpPut(url.toString()); } else if ("DELETE".equals(method)) { request = new HttpDelete(url.toString()); } else { throw new CmisRuntimeException("Invalid HTTP method!"); } // set content type if (contentType != null) { request.setHeader("Content-Type", contentType); } // set other headers if (headers != null) { for (Map.Entry<String, String> header : headers.entrySet()) { request.addHeader(header.getKey(), header.getValue()); } } // authenticate AuthenticationProvider authProvider = CmisBindingsHelper.getAuthenticationProvider(session); if (authProvider != null) { Map<String, List<String>> httpHeaders = authProvider.getHTTPHeaders(url.toString()); if (httpHeaders != null) { for (Map.Entry<String, List<String>> header : httpHeaders.entrySet()) { if (header.getKey() != null && isNotEmpty(header.getValue())) { String key = header.getKey(); if (key.equalsIgnoreCase("user-agent")) { request.setHeader("User-Agent", header.getValue().get(0)); } else { for (String value : header.getValue()) { if (value != null) { request.addHeader(key, value); } } } } } } } // range if ((offset != null) || (length != null)) { StringBuilder sb = new StringBuilder("bytes="); if ((offset == null) || (offset.signum() == -1)) { offset = BigInteger.ZERO; } sb.append(offset.toString()); sb.append('-'); if ((length != null) && (length.signum() == 1)) { sb.append(offset.add(length.subtract(BigInteger.ONE)).toString()); } request.setHeader("Range", sb.toString()); } // compression Object compression = session.get(SessionParameter.COMPRESSION); if ((compression != null) && Boolean.parseBoolean(compression.toString())) { request.setHeader("Accept-Encoding", "gzip,deflate"); } // locale if (session.get(CmisBindingsHelper.ACCEPT_LANGUAGE) instanceof String) { request.setHeader("Accept-Language", session.get(CmisBindingsHelper.ACCEPT_LANGUAGE).toString()); } // send data if (writer != null) { Object clientCompression = session.get(SessionParameter.CLIENT_COMPRESSION); final boolean clientCompressionFlag = (clientCompression != null) && Boolean.parseBoolean(clientCompression.toString()); if (clientCompressionFlag) { request.setHeader("Content-Encoding", "gzip"); } AbstractHttpEntity streamEntity = new AbstractHttpEntity() { @Override public boolean isChunked() { return true; } @Override public boolean isRepeatable() { return false; } @Override public long getContentLength() { return -1; } @Override public boolean isStreaming() { return false; } @Override public InputStream getContent() throws IOException { throw new UnsupportedOperationException(); } @Override public void writeTo(final OutputStream outstream) throws IOException { OutputStream connOut = null; if (clientCompressionFlag) { connOut = new GZIPOutputStream(outstream, 4096); } else { connOut = outstream; } OutputStream out = new BufferedOutputStream(connOut, BUFFER_SIZE); try { writer.write(out); } catch (IOException ioe) { throw ioe; } catch (Exception e) { throw new IOException(e); } out.flush(); if (connOut instanceof GZIPOutputStream) { ((GZIPOutputStream) connOut).finish(); } } }; ((HttpEntityEnclosingRequestBase) request).setEntity(streamEntity); } // connect HttpResponse response = httpclient.execute(request); HttpEntity entity = response.getEntity(); // get stream, if present respCode = response.getStatusLine().getStatusCode(); InputStream inputStream = null; InputStream errorStream = null; if ((respCode == 200) || (respCode == 201) || (respCode == 203) || (respCode == 206)) { if (entity != null) { inputStream = entity.getContent(); } else { inputStream = new ByteArrayInputStream(new byte[0]); } } else { if (entity != null) { errorStream = entity.getContent(); } else { errorStream = new ByteArrayInputStream(new byte[0]); } } // collect headers Map<String, List<String>> responseHeaders = new HashMap<String, List<String>>(); for (Header header : response.getAllHeaders()) { List<String> values = responseHeaders.get(header.getName()); if (values == null) { values = new ArrayList<String>(); responseHeaders.put(header.getName(), values); } values.add(header.getValue()); } // log after connect if (LOG.isTraceEnabled()) { LOG.trace("Session {}: {} {} > Headers: {}", session.getSessionId(), method, url, responseHeaders.toString()); } // forward response HTTP headers if (authProvider != null) { authProvider.putResponseHeaders(url.toString(), respCode, responseHeaders); } // get the response return new Response(respCode, response.getStatusLine().getReasonPhrase(), responseHeaders, inputStream, errorStream); } catch (Exception e) { String status = (respCode > 0 ? " (HTTP status code " + respCode + ")" : ""); throw new CmisConnectionException("Cannot access \"" + url + "\"" + status + ": " + e.getMessage(), e); } }
From source file:com.flexive.core.storage.genericSQL.GenericTreeStorageSpreaded.java
protected long _reorganizeSpace(Connection con, SequencerEngine seq, FxTreeMode sourceMode, FxTreeMode destMode, long nodeId, boolean includeNodeId, BigInteger overrideSpacing, BigInteger overrideLeft, FxTreeNodeInfo insertParent, int insertPosition, BigInteger insertSpace, BigInteger insertBoundaries[], int depthDelta, Long destinationNode, boolean createMode, boolean createKeepIds, boolean disableSpaceOptimization) throws FxTreeException { long firstCreatedNodeId = -1; FxTreeNodeInfoSpreaded nodeInfo;/*from w ww . j a v a 2s .c o m*/ try { nodeInfo = (FxTreeNodeInfoSpreaded) getTreeNodeInfo(con, sourceMode, nodeId); } catch (Exception e) { return -1; } if (!nodeInfo.isSpaceOptimizable() && !disableSpaceOptimization) { // The Root node and cant be optimize any more ... so all we can do is fail :-/ // This should never really happen if (nodeId == ROOT_NODE) { return -1; } //System.out.println("### UP we go, depthDelta=" + depthDelta); return _reorganizeSpace(con, seq, sourceMode, destMode, nodeInfo.getParentId(), includeNodeId, overrideSpacing, overrideLeft, insertParent, insertPosition, insertSpace, insertBoundaries, depthDelta, destinationNode, createMode, createKeepIds, false); } BigInteger spacing = nodeInfo.getDefaultSpacing(); if (overrideSpacing != null && (overrideSpacing.compareTo(spacing) < 0 || overrideLeft != null)) { // override spacing unless it is greater OR overrideLeft is specified (in that case we // have to use the spacing for valid tree ranges) spacing = overrideSpacing; } else { if (spacing.compareTo(GO_UP) < 0 && !createMode && !disableSpaceOptimization) { return _reorganizeSpace(con, seq, sourceMode, destMode, nodeInfo.getParentId(), includeNodeId, overrideSpacing, overrideLeft, insertParent, insertPosition, insertSpace, insertBoundaries, depthDelta, destinationNode, createMode, createKeepIds, false); } } if (insertBoundaries != null && insertPosition == -1) { insertPosition = 0; // insertPosition cannot be negative } Statement stmt = null; PreparedStatement ps = null; ResultSet rs; BigInteger left = overrideLeft == null ? nodeInfo.getLeft() : overrideLeft; BigInteger right = null; String includeNode = includeNodeId ? "=" : ""; long counter = 0; long newId = -1; try { final long start = System.currentTimeMillis(); String createProps = createMode ? ",PARENT,REF,NAME,TEMPLATE" : ""; String sql = " SELECT ID," + StorageManager.getIfFunction( // compute total child count only when the node has children "CHILDCOUNT = 0", "0", "(SELECT COUNT(*) FROM " + getTable(sourceMode) + " WHERE LFT > NODE.LFT AND RGT < NODE.RGT)") + // 3 4 5 6 ", CHILDCOUNT, LFT AS LFTORD,RGT,DEPTH" + createProps + " FROM (SELECT ID,CHILDCOUNT,LFT,RGT,DEPTH" + createProps + " FROM " + getTable(sourceMode) + " WHERE " + "LFT>" + includeNode + nodeInfo.getLeft() + " AND LFT<" + includeNode + nodeInfo.getRight() + ") NODE " + "ORDER BY LFTORD ASC"; stmt = con.createStatement(); rs = stmt.executeQuery(sql); if (createMode) { // 1 2 3 4 5 6 7 8 ps = con.prepareStatement( "INSERT INTO " + getTable(destMode) + " (ID,PARENT,DEPTH,DIRTY,REF,TEMPLATE,LFT,RGT," + //9 10 11 "CHILDCOUNT,NAME,MODIFIED_AT) " + "VALUES (?,?,?,?,?,?,?,?,?,?,?)"); } else { ps = con.prepareStatement("UPDATE " + getTable(sourceMode) + " SET LFT=?,RGT=?,DEPTH=? WHERE ID=?"); } long id; int total_childs; int direct_childs; BigInteger nextLeft; int lastDepth = nodeInfo.getDepth() + (includeNodeId ? 0 : 1); int depth; BigInteger _rgt; BigInteger _lft; Long ref = null; String data = null; String name = ""; Stack<Long> currentParent = null; if (createMode) { currentParent = new Stack<Long>(); currentParent.push(destinationNode); } //System.out.println("Spacing:"+SPACING); while (rs.next()) { //System.out.println("------------------"); id = rs.getLong(1); total_childs = rs.getInt(2); direct_childs = rs.getInt(3); _lft = getNodeBounds(rs, 4); _rgt = getNodeBounds(rs, 5); depth = rs.getInt(6); if (createMode) { // Reading these properties is slow, only do it when needed ref = rs.getLong(8); if (rs.wasNull()) ref = null; name = rs.getString(9); data = rs.getString(10); if (rs.wasNull()) data = null; } left = left.add(spacing).add(BigInteger.ONE); // Handle depth differences if (lastDepth - depth > 0) { BigInteger depthDifference = spacing.add(BigInteger.ONE); left = left.add(depthDifference.multiply(BigInteger.valueOf(lastDepth - depth))); } if (createMode) { if (lastDepth < depth) { currentParent.push(newId); } else if (lastDepth > depth) { for (int p = 0; p < (lastDepth - depth); p++) currentParent.pop(); } } right = left.add(spacing).add(BigInteger.ONE); // add child space if needed if (total_childs > 0) { BigInteger childSpace = spacing.multiply(BigInteger.valueOf(total_childs * 2)); childSpace = childSpace.add(BigInteger.valueOf((total_childs * 2) - 1)); right = right.add(childSpace); nextLeft = left; } else { nextLeft = right; } if (insertBoundaries != null) { // insert gap at requested position // If we're past the gap, keep adding the insert space to left/right because the added // space is never "injected" into the loop, i.e. without adding it the left/right boundaries of // nodes after the gap would be too far to the left. if (_lft.compareTo(insertBoundaries[0]) > 0) { left = left.add(insertSpace); } if (_rgt.compareTo(insertBoundaries[0]) > 0) { right = right.add(insertSpace); } } // sanity checks if (left.compareTo(right) >= 0) { throw new FxTreeException(LOG, "ex.tree.reorganize.failed", counter, left, right, "left greater than right"); } if (insertParent != null && right.compareTo((BigInteger) insertParent.getRight()) > 0) { throw new FxTreeException(LOG, "ex.tree.reorganize.failed", counter, left, right, "wrote past parent node bounds"); } // Update the node if (createMode) { newId = createKeepIds ? id : seq.getId(destMode.getSequencer()); if (firstCreatedNodeId == -1) firstCreatedNodeId = newId; // Create the main entry ps.setLong(1, newId); ps.setLong(2, currentParent.peek()); ps.setLong(3, depth + depthDelta); ps.setBoolean(4, destMode != FxTreeMode.Live); //only flag non-live tree's dirty if (ref == null) { ps.setNull(5, java.sql.Types.NUMERIC); } else { ps.setLong(5, ref); } if (data == null) { ps.setNull(6, java.sql.Types.VARCHAR); } else { ps.setString(6, data); } // System.out.println("=> id:"+newId+" left:"+left+" right:"+right); setNodeBounds(ps, 7, left); setNodeBounds(ps, 8, right); ps.setInt(9, direct_childs); ps.setString(10, name); ps.setLong(11, System.currentTimeMillis()); ps.addBatch(); } else { setNodeBounds(ps, 1, left); setNodeBounds(ps, 2, right); ps.setInt(3, depth + depthDelta); ps.setLong(4, id); ps.addBatch(); // ps.executeBatch(); // ps.clearBatch(); } // Prepare variables for the next node left = nextLeft; lastDepth = depth; counter++; // Execute batch every 10000 items to avoid out of memory if (counter % 10000 == 0) { ps.executeBatch(); ps.clearBatch(); } } rs.close(); stmt.close(); stmt = null; ps.executeBatch(); if (LOG.isDebugEnabled()) { final long time = System.currentTimeMillis() - start; LOG.debug("Tree reorganization of " + counter + " items completed in " + time + " ms (spaceLen=" + spacing + ")"); } return firstCreatedNodeId; } catch (FxApplicationException e) { throw e instanceof FxTreeException ? (FxTreeException) e : new FxTreeException(e); } catch (SQLException e) { String next = ""; if (e.getNextException() != null) next = " next:" + e.getNextException().getMessage(); if (StorageManager.isDuplicateKeyViolation(e)) throw new FxTreeException(LOG, e, "ex.tree.reorganize.duplicateKey"); throw new FxTreeException(LOG, e, "ex.tree.reorganize.failed", counter, left, right, e.getMessage() + next); } catch (Exception e) { throw new FxTreeException(e); } finally { try { if (stmt != null) stmt.close(); } catch (Throwable t) { /*ignore*/} try { if (ps != null) ps.close(); } catch (Throwable t) { /*ignore*/} } }
From source file:com.google.bitcoin.core.Wallet.java
/** * Returns the balance of this wallet as calculated by the provided balanceType. *//*from w ww .java 2 s. co m*/ public BigInteger getBalance(BalanceType balanceType) { lock.lock(); try { if (balanceType == BalanceType.AVAILABLE) { return getBalance(coinSelector); } else if (balanceType == BalanceType.ESTIMATED) { LinkedList<TransactionOutput> all = calculateAllSpendCandidates(false); BigInteger value = BigInteger.ZERO; for (TransactionOutput out : all) value = value.add(out.getValue()); return value; } else { throw new AssertionError("Unknown balance type"); // Unreachable. } } finally { lock.unlock(); } }
From source file:com.google.bitcoin.core.Wallet.java
/** * <p>Don't call this directly. It's not intended for API users.</p> * * <p>Called by the {@link BlockChain} when the best chain (representing total work done) has changed. This can * cause the number of confirmations of a transaction to go higher, lower, drop to zero and can even result in * a transaction going dead (will never confirm) due to a double spend.</p> * * <p>The oldBlocks/newBlocks lists are ordered height-wise from top first to bottom last.</p> *///from w w w .j a v a 2s .c o m public void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks) throws VerificationException { lock.lock(); try { // This runs on any peer thread with the block chain locked. // // The reorganize functionality of the wallet is tested in ChainSplitTest.java // // receive() has been called on the block that is triggering the re-org before this is called, with type // of SIDE_CHAIN. // // Note that this code assumes blocks are not invalid - if blocks contain duplicated transactions, // transactions that double spend etc then we can calculate the incorrect result. This could open up // obscure DoS attacks if someone successfully mines a throwaway invalid block and feeds it to us, just // to try and corrupt the internal data structures. We should try harder to avoid this but it's tricky // because there are so many ways the block can be invalid. // Avoid spuriously informing the user of wallet/tx confidence changes whilst we're re-organizing. checkState(confidenceChanged.size() == 0); checkState(!insideReorg); insideReorg = true; checkState(onWalletChangedSuppressions == 0); onWalletChangedSuppressions++; // Map block hash to transactions that appear in it. We ensure that the map values are sorted according // to their relative position within those blocks. ArrayListMultimap<Sha256Hash, TxOffsetPair> mapBlockTx = ArrayListMultimap.create(); for (Transaction tx : getTransactions(true)) { Map<Sha256Hash, Integer> appearsIn = tx.getAppearsInHashes(); if (appearsIn == null) continue; // Pending. for (Map.Entry<Sha256Hash, Integer> block : appearsIn.entrySet()) mapBlockTx.put(block.getKey(), new TxOffsetPair(tx, block.getValue())); } for (Sha256Hash blockHash : mapBlockTx.keySet()) Collections.sort(mapBlockTx.get(blockHash)); List<Sha256Hash> oldBlockHashes = new ArrayList<Sha256Hash>(oldBlocks.size()); /* CSPK-mike START */ int MinHeight = -1; int MaxHeight = -1; /* CSPK-mike END */ log.info("Old part of chain (top to bottom):"); for (StoredBlock b : oldBlocks) { /* CSPK-mike START */ if (MinHeight == -1) { MinHeight = b.getHeight(); MaxHeight = b.getHeight(); } else { if (b.getHeight() < MinHeight) { MinHeight = b.getHeight(); } if (b.getHeight() > MaxHeight) { MaxHeight = b.getHeight(); } } /* CSPK-mike END */ log.info(" {}", b.getHeader().getHashAsString()); oldBlockHashes.add(b.getHeader().getHash()); } /* CSPK-mike START */ // Asset references for removed blocks should be cleared. CS.log.info("Blockchain reorganizing. Removing blocks " + MinHeight + " - " + MaxHeight); CS.clearAssetRefs(MinHeight, MaxHeight); /* CSPK-mike END */ log.info("New part of chain (top to bottom):"); for (StoredBlock b : newBlocks) { /* CSPK-mike START */ CS.log.info("New block " + b.getHeight() + ": " + b.getHeader().getHashAsString()); /* CSPK-mike END */ log.info(" {}", b.getHeader().getHashAsString()); } Collections.reverse(newBlocks); // Need bottom-to-top but we get top-to-bottom. // For each block in the old chain, disconnect the transactions in reverse order. LinkedList<Transaction> oldChainTxns = Lists.newLinkedList(); for (Sha256Hash blockHash : oldBlockHashes) { for (TxOffsetPair pair : mapBlockTx.get(blockHash)) { Transaction tx = pair.tx; final Sha256Hash txHash = tx.getHash(); if (tx.isCoinBase()) { // All the transactions that we have in our wallet which spent this coinbase are now invalid // and will never confirm. Hopefully this should never happen - that's the point of the maturity // rule that forbids spending of coinbase transactions for 100 blocks. // // This could be recursive, although of course because we don't have the full transaction // graph we can never reliably kill all transactions we might have that were rooted in // this coinbase tx. Some can just go pending forever, like the Satoshi client. However we // can do our best. // // TODO: Is it better to try and sometimes fail, or not try at all? killCoinbase(tx); } else { for (TransactionOutput output : tx.getOutputs()) { TransactionInput input = output.getSpentBy(); if (input != null) input.disconnect(); } for (TransactionInput input : tx.getInputs()) { input.disconnect(); } oldChainTxns.add(tx); unspent.remove(txHash); spent.remove(txHash); checkState(!pending.containsKey(txHash)); checkState(!dead.containsKey(txHash)); } } } // Put all the disconnected transactions back into the pending pool and re-connect them. for (Transaction tx : oldChainTxns) { // Coinbase transactions on the old part of the chain are dead for good and won't come back unless // there's another re-org. if (tx.isCoinBase()) continue; log.info(" ->pending {}", tx.getHash()); tx.getConfidence().setConfidenceType(ConfidenceType.PENDING); // Wipe height/depth/work data. confidenceChanged.put(tx, TransactionConfidence.Listener.ChangeReason.TYPE); addWalletTransaction(Pool.PENDING, tx); updateForSpends(tx, false); } // Note that dead transactions stay dead. Consider a chain that Finney attacks T1 and replaces it with // T2, so we move T1 into the dead pool. If there's now a re-org to a chain that doesn't include T2, it // doesn't matter - the miners deleted T1 from their mempool, will resurrect T2 and put that into the // mempool and so T1 is still seen as a losing double spend. // The old blocks have contributed to the depth and work done for all the transactions in the // wallet that are in blocks up to and including the chain split block. // The total depth and work done is calculated here and then subtracted from the appropriate transactions. int depthToSubtract = oldBlocks.size(); BigInteger workDoneToSubtract = BigInteger.ZERO; for (StoredBlock b : oldBlocks) { workDoneToSubtract = workDoneToSubtract.add(b.getHeader().getWork()); } log.info("depthToSubtract = " + depthToSubtract + ", workDoneToSubtract = " + workDoneToSubtract); // Remove depthToSubtract and workDoneToSubtract from all transactions in the wallet except for pending. subtractDepthAndWorkDone(depthToSubtract, workDoneToSubtract, spent.values()); subtractDepthAndWorkDone(depthToSubtract, workDoneToSubtract, unspent.values()); subtractDepthAndWorkDone(depthToSubtract, workDoneToSubtract, dead.values()); // The effective last seen block is now the split point so set the lastSeenBlockHash. setLastBlockSeenHash(splitPoint.getHeader().getHash()); // For each block in the new chain, work forwards calling receive() and notifyNewBestBlock(). // This will pull them back out of the pending pool, or if the tx didn't appear in the old chain and // does appear in the new chain, will treat it as such and possibly kill pending transactions that // conflict. for (StoredBlock block : newBlocks) { log.info("Replaying block {}", block.getHeader().getHashAsString()); for (TxOffsetPair pair : mapBlockTx.get(block.getHeader().getHash())) { log.info(" tx {}", pair.tx.getHash()); try { receive(pair.tx, block, BlockChain.NewBlockType.BEST_CHAIN, pair.offset); } catch (ScriptException e) { throw new RuntimeException(e); // Cannot happen as these blocks were already verified. } } notifyNewBestBlock(block); } checkState(isConsistent()); final BigInteger balance = getBalance(); log.info("post-reorg balance is {}", Utils.bitcoinValueToFriendlyString(balance)); // Inform event listeners that a re-org took place. queueOnReorganize(); insideReorg = false; onWalletChangedSuppressions--; maybeQueueOnWalletChanged(); checkBalanceFuturesLocked(balance); informConfidenceListenersIfNotReorganizing(); saveLater(); } finally { lock.unlock(); } }
From source file:com.google.bitcoin.core.Wallet.java
/** Reduce the value of the first output of a transaction to pay the given feePerKb as appropriate for its size. */ private boolean adjustOutputDownwardsForFee(Transaction tx, CoinSelection coinSelection, BigInteger baseFee, BigInteger feePerKb) {/* www . j av a 2s . co m*/ TransactionOutput output = tx.getOutput(0); // Check if we need additional fee due to the transaction's size int size = tx.bitcoinSerialize().length; size += estimateBytesForSigning(coinSelection); BigInteger fee = baseFee.add(BigInteger.valueOf((size / 1000) + 1).multiply(feePerKb)); output.setValue(output.getValue().subtract(fee)); // Check if we need additional fee due to the output's value if (output.getValue().compareTo(Utils.CENT) < 0 && fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0) output.setValue(output.getValue().subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(fee))); return output.getMinNonDustValue().compareTo(output.getValue()) <= 0; }
From source file:com.google.bitcoin.core.Wallet.java
/** * Given a spend request containing an incomplete transaction, makes it valid by adding outputs and signed inputs * according to the instructions in the request. The transaction in the request is modified by this method, as is * the fee parameter./*from w w w . j av a 2s.co m*/ * * @param req a SendRequest that contains the incomplete transaction and details for how to make it valid. * @throws InsufficientMoneyException if the request could not be completed due to not enough balance. * @throws IllegalArgumentException if you try and complete the same SendRequest twice, or if the given send request * cannot be completed without violating the protocol rules. */ public void completeTx(SendRequest req, boolean sign) throws InsufficientMoneyException, CSExceptions.CannotEncode { lock.lock(); try { checkArgument(!req.completed, "Given SendRequest has already been completed."); // Calculate the amount of value we need to import. BigInteger value = BigInteger.ZERO; for (TransactionOutput output : req.tx.getOutputs()) { value = value.add(output.getValue()); } BigInteger totalOutput = value; log.info("Completing send tx with {} outputs totalling {} satoshis (not including fees)", req.tx.getOutputs().size(), value); // If any inputs have already been added, we don't need to get their value from wallet BigInteger totalInput = BigInteger.ZERO; /* CSPK-mike START */ /* Code commented out, input value is calculated after asset inputs were added for (TransactionInput input : req.tx.getInputs()) if (input.getConnectedOutput() != null) totalInput = totalInput.add(input.getConnectedOutput().getValue()); else log.warn("SendRequest transaction already has inputs but we don't know how much they are worth - they will be added to fee."); value = value.subtract(totalInput); */ /* CSPK-mike START */ List<TransactionInput> originalInputs = new ArrayList<TransactionInput>(req.tx.getInputs()); // We need to know if we need to add an additional fee because one of our values are smaller than 0.01 BTC boolean needAtLeastReferenceFee = false; if (req.ensureMinRequiredFee && !req.emptyWallet) { // min fee checking is handled later for emptyWallet for (TransactionOutput output : req.tx.getOutputs()) if (output.getValue().compareTo(Utils.CENT) < 0) { if (output.getValue().compareTo(output.getMinNonDustValue()) < 0) throw new IllegalArgumentException( "Tried to send dust with ensureMinRequiredFee set - no way to complete this"); needAtLeastReferenceFee = true; break; } } // Calculate a list of ALL potential candidates for spending and then ask a coin selector to provide us // with the actual outputs that'll be used to gather the required amount of value. In this way, users // can customize coin selection policies. // // Note that this code is poorly optimized: the spend candidates only alter when transactions in the wallet // change - it could be pre-calculated and held in RAM, and this is probably an optimization worth doing. // Note that output.isMine(this) needs to test the keychain which is currently an array, so it's // O(candidate outputs ^ keychain.size())! There's lots of low hanging fruit here. LinkedList<TransactionOutput> candidates = calculateAllSpendCandidates(true); CoinSelection bestCoinSelection; TransactionOutput bestChangeOutput = null; if (!req.emptyWallet) { // This can throw InsufficientMoneyException. FeeCalculation feeCalculation; /* CSPK-mike START */ // feeCalculation = new FeeCalculation(req, value, originalInputs, needAtLeastReferenceFee, candidates); // Fee and inputs calculation /* CoinSparkMessagePart [] MessageParts=new CoinSparkMessagePart[1]; MessageParts[0]=new CoinSparkMessagePart(); MessageParts[0].mimeType="text/plain"; MessageParts[0].fileName=null; MessageParts[0].content="Hello World!".getBytes(); String [] DeliveryServers=new String [] {"assets1.coinspark.org/","assets1.coinspark.org/abc"};//,"144.76.175.228/" }; req.setMessage(MessageParts, DeliveryServers); CoinSparkPaymentRef paymentRef=new CoinSparkPaymentRef(125); req.setPaymentRef(paymentRef); */ if (CS.createAssetTransfers(req, originalInputs, candidates)) { totalInput = BigInteger.ZERO; for (TransactionInput input : req.tx.getInputs()) { if (input.getConnectedOutput() != null) { totalInput = totalInput.add(input.getConnectedOutput().getValue()); } else { log.warn( "SendRequest transaction already has inputs but we don't know how much they are worth - they will be added to fee."); } } value = totalOutput; value = value.subtract(totalInput); originalInputs = new ArrayList<TransactionInput>(req.tx.getInputs()); // Coinspark transaction has to have change output even if there are no explicit transfers. feeCalculation = new FeeCalculation(req, value, originalInputs, needAtLeastReferenceFee, candidates, Transaction.MIN_NONDUST_OUTPUT); } else { throw new InsufficientMoneyException.CouldNotAdjustDownwards(); } /* CSPK-mike END */ bestCoinSelection = feeCalculation.bestCoinSelection; bestChangeOutput = feeCalculation.bestChangeOutput; } else { // We're being asked to empty the wallet. What this means is ensuring "tx" has only a single output // of the total value we can currently spend as determined by the selector, and then subtracting the fee. checkState(req.tx.getOutputs().size() == 1, "Empty wallet TX must have a single output only."); CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector; bestCoinSelection = selector.select(NetworkParameters.MAX_MONEY, candidates); req.tx.getOutput(0).setValue(bestCoinSelection.valueGathered); totalOutput = bestCoinSelection.valueGathered; } for (TransactionOutput output : bestCoinSelection.gathered) req.tx.addInput(output); /* CSPK-mike START */ if (!CS.preparePaymentRef(req)) { throw new CSExceptions.CannotEncode("Cannot prepare payment reference"); } if (!CS.prepareMessage(req)) { throw new CSExceptions.CannotEncode("Cannot prepare message"); } /* CSPK-mike END */ if (req.ensureMinRequiredFee && req.emptyWallet) { final BigInteger baseFee = req.fee == null ? BigInteger.ZERO : req.fee; final BigInteger feePerKb = req.feePerKb == null ? BigInteger.ZERO : req.feePerKb; Transaction tx = req.tx; if (!adjustOutputDownwardsForFee(tx, bestCoinSelection, baseFee, feePerKb)) throw new InsufficientMoneyException.CouldNotAdjustDownwards(); } /* CSPK-mike START */ // Input calculation for "Empty wallet" request if (req.emptyWallet) { Transaction tx = req.tx; TransactionOutput output = tx.getOutput(0); if (CS.createAssetTransfersForEmptyWallet(req, output.getValue().subtract(output.getMinNonDustValue()))) { if (req.ensureMinRequiredFee) { final BigInteger baseFee = req.fee == null ? BigInteger.ZERO : req.fee; final BigInteger feePerKb = req.feePerKb == null ? BigInteger.ZERO : req.feePerKb; totalOutput = bestCoinSelection.valueGathered; output.setValue(totalOutput); if (!adjustOutputDownwardsForFee(tx, bestCoinSelection, baseFee, feePerKb, req.assetFee)) { CS.log.warning("Empty wallet: not enough bitcoins to transfer assets."); tx.getOutputs().clear(); output.setValue(totalOutput); tx.addOutput(output); req.assetsEncoded = null; req.assetFee = BigInteger.ZERO; if (!adjustOutputDownwardsForFee(tx, bestCoinSelection, baseFee, feePerKb)) { throw new InsufficientMoneyException.CouldNotAdjustDownwards(); } } totalOutput = output.getValue(); bestChangeOutput = null; } } totalOutput = output.getValue(); bestChangeOutput = null; } /* CSPK-mike END */ totalInput = totalInput.add(bestCoinSelection.valueGathered); if (bestChangeOutput != null) { req.tx.addOutput(bestChangeOutput); totalOutput = totalOutput.add(bestChangeOutput.getValue()); log.info(" with {} coins change", bitcoinValueToFriendlyString(bestChangeOutput.getValue())); } final BigInteger calculatedFee = totalInput.subtract(totalOutput); if (calculatedFee.compareTo(BigInteger.ZERO) > 0) { log.info(" with a fee of {}", bitcoinValueToFriendlyString(calculatedFee)); } // Now sign the inputs, thus proving that we are entitled to redeem the connected outputs. if (sign) { sign(req); } // Check size. int size = req.tx.bitcoinSerialize().length; if (size > Transaction.MAX_STANDARD_TX_SIZE) { throw new IllegalArgumentException( String.format("Transaction could not be created without exceeding max size: %d vs %d", size, Transaction.MAX_STANDARD_TX_SIZE)); } // Label the transaction as being self created. We can use this later to spend its change output even before // the transaction is confirmed. We deliberately won't bother notifying listeners here as there's not much // point - the user isn't interested in a confidence transition they made themselves. req.tx.getConfidence().setSource(TransactionConfidence.Source.SELF); // Keep a track of the date the tx was created (used in MultiBitService // to work out the block it appears in). req.tx.setUpdateTime(new Date()); // Label the transaction as being a user requested payment. This can be used to render GUI wallet // transaction lists more appropriately, especially when the wallet starts to generate transactions itself // for internal purposes. req.tx.setPurpose(Transaction.Purpose.USER_PAYMENT); req.completed = true; req.fee = calculatedFee; log.info(" completed: {}", req.tx); } finally { lock.unlock(); } }
From source file:com.google.bitcoin.core.Wallet.java
private boolean adjustOutputDownwardsForFee(Transaction tx, CoinSelection coinSelection, BigInteger baseFee, BigInteger feePerKb, BigInteger minFee) { TransactionOutput output = tx.getOutput(0); // Check if we need additional fee due to the transaction's size int size = tx.bitcoinSerialize().length; size += estimateBytesForSigning(coinSelection); BigInteger fee = baseFee.add(BigInteger.valueOf((size / 1000) + 1).multiply(feePerKb)); if (fee.compareTo(minFee) < 0) { fee = minFee;//ww w .j a va2 s . c o m } output.setValue(output.getValue().subtract(fee)); // Check if we need additional fee due to the output's value if (output.getValue().compareTo(Utils.CENT) < 0 && fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0) { output.setValue(output.getValue().subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(fee))); } return output.getMinNonDustValue().compareTo(output.getValue()) <= 0; }