Zum Inhalt springen

Threast

Mitglied
  • Gesamte Inhalte

    10
  • Benutzer seit

  • Letzter Besuch

Reputation in der Community

2 Neutral
  1. Danke für den Link, ich werd mir das mal ansehen👍
  2. @skunkAlso ich hab mir das ganze jetzt nochmal anhand meines Beispiels angesehen und kann die Verifikation jetzt auch ganz gut nachvollziehen. Das einzige was ich noch nicht verstehe ist die Sache mit dem Hash den ich der Methode übergebe: public static boolean verify(byte[] hash, byte[] signature, byte[] publicKey) { boolean result; try(ASN1InputStream asn1 = new ASN1InputStream(signature)) { ECDSASigner signer = new ECDSASigner(); signer.init(false, new ECPublicKeyParameters(CURVE.getCurve().decodePoint(publicKey), DOMAIN)); DLSequence seq = (DLSequence) asn1.readObject(); BigInteger r = ((ASN1Integer) seq.getObjectAt(0)).getPositiveValue(); BigInteger s = ((ASN1Integer) seq.getObjectAt(1)).getPositiveValue(); result = signer.verifySignature(hash, r, s); } catch (Exception e) { result = false; } return result; } Denn übergeben tu ich der obigen Methode folgendes: public static boolean verifySignature(Transaction transaction) { boolean result; try { logger.debug(transaction.asJSONString()); result = SignatureHelper.verify(transaction.asJSONString().getBytes("UTF-8"), transaction.getSignature(), transaction.getSender()); logger.debug("signature verification result: " + result); } catch (Exception e) { result = false; } return result; } Nämlich die JSON Repräsentation meiner Transaktion... Aber die JSON Repräsentation ist doch nicht der Hash??? Das wäre noch die "asJSONString" -Methode: public String asJSONString( ) { DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); df.setMaximumFractionDigits(340); return "{" + "\"sender\":\"" + SHA3Helper.digestToHex( sender ) + '\"' + ",\"receiver\":\"" + SHA3Helper.digestToHex( receiver ) + '\"' + ",\"amount\":\"" + amount + "\"" + // ",\"nonce\":" + nonce + ",\"transactionFeeBasePrice\":\"" + df.format( transactionFeeBasePrice ) + "\"" + ",\"transactionFeeLimit\":\"" + transactionFeeLimit + "\"" + '}'; } Ich glaub als nächstes muss ich mich mal intensiv mit den ganzen Codierungen und Konvertierungen auseinandersetzen weil da haperts noch ziemlich😅
  3. Ahh jetzt kommen wir der Sache schon näher😅 Also zusammengefasst entstehen R und S durch die Signierung mit dem privateKey und aus den beiden Punkten lässt sich wiederum der publicKey des Senders berechnen welcher dann wiederum zur Verifizierung der Transaktion verwendet wird oder?
  4. @skunk Ja normalerweise schon aber die Autoren des Buches haben das denk ich mal aus Vereinfachungsgründen weggelassen und stattdessen einfach den PubKey auch noch abfragen lassen. Ich dachte die Punkt R und S ergeben sich durch die Verschlüsselung des Senders mit seinem PrivateKey die dann der Empfänger wiederum mit dem PublicKey des Senders verifizieren muss oder nicht?
  5. Hallo zusammen, ich arbeite gegenwärtig ich Buch zum Thema Blockchain-Entwicklung durch und bin mittlerweile beim letzten Kapitel angekommen allerdings ist mir hier das ein oder andere nicht ganz verständlich, vielleicht kann mir hier ja nochmal wer weiterhelfen. Im letzten Kapitel geht es u.A darum Transaktionen zu signieren und anschießend zu verifizieren aber ich tu mich noch etwas schwer das ganze zu verstehen. Ich poste euch unten die entsprechenden Seiten im Buch damit ihr mir besser folgen könnt. Und zwar ausgangssituation ist folgende: Ich habe einen Block Explorer erstellt über den es möglich ist die Blockchain zu durchsuchen und auch Transaktionen zu versenden. Um das versenden zu ermöglichen muss der User unter Anderem seinen privaten und öffentlichen Schlüssel eingeben. Diese werden dann im Frontend mittels JavaScript benutzt um die Transaktion zu signieren. Im Backend soll das ganze dann mittels der Methoden „verify()“ verifiziert werden. Im Buch heißt es das Frontend und das Backend müssen die exakt gleiche Repräsentation einer Transaktionen verwenden. Ist damit die JSON Repräsentation gemeint oder der Hash oder beides? Ebenfalls heißt es dann bei der Methode verify dass die Signatur selbst nur aus den Punkten R und S besteht. Diese „sind im ASN1 Format codiert und müssen aus dem Hex-String der Signatur ermittelt werden. Anschließend kann mit der Library von Bouncy Castle die Transaktion verifiziert werden“. Kann mir bitte wer in eigenen Worten erklären wie ich mit diesen 2 Punkten (und dem Hash der Transaktionen und dem Public Key) die Transaktion verifizieren soll? Ich habe den gestrigen Tag bereits damit verbracht mich mit elliptischen Kurven auseinanderzusetzen, einige Uni-Vorlesungen dazu angesehen usw. Also mit dem Grundlegenden Prinzip davon bin ich vertraut, auch mit Gruppenoperationen usw. Aber wirklich verstehen tu ich diesen Schritt im Buch trotzdem noch nicht, villeicht kann mit ja wer helfen 😊 ``` //Methoden public static boolean verify(byte[] hash, byte[] signature, byte[] publicKey) { boolean result; try(ASN1InputStream asn1 = new ASN1InputStream(signature)) { ECDSASigner signer = new ECDSASigner(); signer.init(false, new ECPublicKeyParameters(CURVE.getCurve().decodePoint(publicKey), DOMAIN)); DLSequence seq = (DLSequence) asn1.readObject(); BigInteger r = ((ASN1Integer) seq.getObjectAt(0)).getPositiveValue(); BigInteger s = ((ASN1Integer) seq.getObjectAt(1)).getPositiveValue(); result = signer.verifySignature(hash, r, s); } catch (Exception e) { result = false; } return result; } ``` Buchseiten: https://ibb.co/0Xk36rp https://ibb.co/drML2VQ https://ibb.co/6vHbcYv https://ibb.co/TT5cMKZ https://ibb.co/hVktpLf
  6. Das Buch heißt Blockchain für Entwickler🙂
  7. Ahh ich verstehe, vielen Dank für die ausführliche Erklärung👍 Es kommt noch ein Kapitel zum Thema Optimierung am Ende vielleicht wird da diese Problematik ja nochmal angesprochen mal sehen😅
  8. Ich denke ich verstehe was du meinst das ganze ist wirklich sehr schlecht beschrieben... Aber würde die Methode bzw die Methoden dann rein technisch gesehen so funktionieren und nie null zurückgeben?
  9. Nabend euch, ich habe die Frage auch noch in einem anderen Forum gestellt und dazu folgende Antwort erhalten: "Es gibt immer mindestens eine Chain mit mindestens einem (Genesis) Block. Alle Chains haben damit mindestens einen gemeinsamen Block. "getChainForBlock" muss deshalb für einen ansonsten gültigen Block (Vorgänger Hash etc.) immer ein Chain Objekt zurückgeben. " Und im Buch wird ja auch beschrieben das die getChainForBlock() Methode auch die Vorvorgänger überprüft und dieser Methode ja auch nicht der Hash des aktuellen Blocks sondern der seines Vorgängers übergeben wird. Dieser muss ja quasi dann irgendwo vorhanden sein, wenn es notfalls auch erst der GenesisBlock ist oder wie seht ihr das?
  10. Hallo zusammen, ich arbeite gegenwärtig ein Buch zum Thema Blockchain Entwicklung durch weil ich mich mit dem Thema genauer befassen möchte. Allerdings bin ich auf ein kleines Verständnisproblem gestoßen... Das Ganze ist in Java geschrieben und im aktuellen Kapitel geht es darum, wie die Blockchain mit parallelen Chains umgehen soll, also was passieren soll, wenn beispielsweise zwei Miner gleichzeitig einen Block finden. Allerdings kann ich eine Methode logisch nicht ganz nachvollziehen, vielleicht könnt ihr mir helfen. Ich kann die erste Methode noch verstehen: https://ibb.co/fYdZSnr (Link zum Code-Bild von ImgBB) Hier geht es darum, für einen neu ankommenden Block die richtige Chain zu finden, also zu prüfen, ob der Block tatsächlich zur aktuell längsten Chain (im Code „chain“) gehört. Dazu wird überprüft, ob sich in diesem der Index des Blocks befindet. Wenn dies der Fall ist, wird diese Kette von der Methode zurückgegeben. Ist dies nicht der Fall, werden die alternativen Chains (altChains im Code) geprüft und bei einem Treffer zurückgegeben. Findet sich nirgendwo ein Match, heißt es im Buch „in diesem Fall ist davon auszugehen, dass es noch eine weitere Kette im Netz gibt, die man noch selbst erstellen muss“. Die Methode gibt also "null" zurück. (Fühlt euch frei mich zu korrigieren, wenn ich falsch liege). Bei der zweiten Methode geht es nun darum, diese Chain zu erstellen, wenn keine Übereinstimmung gefunden wurde. Und ich kann das folgende Verfahren nicht ganz verstehen ... https://ibb.co/hM2PVsx Zunächst ruft die Methode die eben erwähnte Methode getChainForBlock auf und ermittelt die Chain des neu angekommenen Blocks (bzw. übergeben wird der Hash des Vorgängerblocks des neu geminten Blocks). Dann wird anhand dieser Vorgänger-ID des neuen Blocks der Index ermittelt, an dem sich der Vorgängerblock befindet. Anschließend werden sowohl der Vorgängerblock als auch alle Vorgänger in eine neue Liste kopiert. Der neue Block muss dann dieser Liste hinzugefügt werden . Dann kann eine neue Chain erstellt werden, die zu den alternativen Chains hinzugefügt wird..." Was ich hier also nicht verstehe ist folgendes: Die Methode "getChainForBlock" gibt "null" zurück, wenn die Kette bei mir noch nicht existiert, oder? Wie ist es dann möglich über die Liste vom Rückgabetyp "null" zu iterieren, der die vorherigen Blöcke kopiert und so weiter? Hier findet ihr einen Link zu den entsprechenden Seiten im Buch die das ganze erklären sollen: https://ibb.co/YZDRkQL https://ibb.co/8bzpbVV https://ibb.co/VDFfPD5 https://ibb.co/fDvvKKb Und hier wäre meine Klasse Blockchain mit den entsprechenden Methoden (die beiden speziell erwähnten finden sich ganz unten unter der Kommentierung "AltChains"): public class Blockchain { private static Logger logger = Logger.getLogger( Blockchain.class ); public final static int MAX_BLOCK_SIZE_IN_BYTES = 1120; public final static int NETWORK_ID = 1; private BigInteger difficulty; private Chain chain; private Map<String, Block> blockCache; private Map<String, Transaction> transactionCache; private List<Chain> altChains; private Block bestBlock; public Blockchain( ) { this.chain = new Chain( NETWORK_ID ); this.blockCache = new ConcurrentHashMap<>( ); this.transactionCache = new ConcurrentHashMap<>( ); this.altChains = new CopyOnWriteArrayList<Chain>(); altChains.add(chain); this.bestBlock = chain.getLast(); this.difficulty = new BigInteger( "-578950000000000000000000000000000000000000000000000000000000000" ); } public Blockchain( BigInteger difficulty, List<Chain> altChains ) { this.difficulty = difficulty; this.altChains = altChains; this.blockCache = new ConcurrentHashMap<>( ); this.transactionCache = new ConcurrentHashMap<>( ); int max = 0; Chain chain = null; for ( Chain altChain : altChains ) { if ( max < altChain.size( ) ) { max = altChain.size( ); chain = altChain; } for ( Block block : altChain.getChain( ) ) { this.blockCache.put( SHA3Helper.digestToHex( block.getBlockHash( ) ), block ); for ( Transaction transaction : block.getTransactions( ) ) { this.transactionCache.put( transaction.getTxIdAsString( ), transaction ); } } } this.chain = chain; this.bestBlock = chain.getLast( ); } public synchronized void addBlock( Block block ) { byte[] previousBlockHash = block.getBlockHeader().getPreviousHash(); if(previousBlockIsBestBlock(previousBlockHash)) { logger.debug( "previous block was best block" ); chain.add(block); bestBlock = block; } else { logger.debug( "previous block wasnt best block: available Chains: " + altChains.size( ) ); checkAltChains(previousBlockHash, block); } blockCache.put( SHA3Helper.digestToHex( block.getBlockHash( ) ), block ); for ( Transaction transaction : block.getTransactions( ) ) { transactionCache.put( transaction.getTxIdAsString( ), transaction ); } } public List<Chain> getAltChains( ) { return altChains; } public boolean fulfillsDifficulty( byte[] digest ) { BigInteger temp = new BigInteger( digest ); return temp.compareTo( difficulty ) <= 0; } public BigInteger getDifficulty( ) { return difficulty; } public void setDifficulty( BigInteger difficulty ) { this.difficulty = difficulty; } public byte[] getPreviousHash( ) { return chain.getLast( ).getBlockHash( ); } public int size( ) { return chain.size( ); } public Transaction getTransactionByHash( String hex ) { return transactionCache.get( hex ); } public Block getBlockByHash( String hex ) { return blockCache.get( hex ); } public Block getBlockByHash( byte[] hash ) { return blockCache.get( SHA3Helper.digestToHex( hash ) ); } public Block getLatestBlock( ) { return chain.getLast( ); } public List<Block> getLatestBlocks( int size, int offset ) { List<Block> blocks = new ArrayList<>( ); Block block = this.getLatestBlock( ); for ( int i = 0; i < ( size + offset ); i++ ) { if ( block != null ) { if ( i >= offset ) { blocks.add( block ); } String previousHash = SHA3Helper.digestToHex( block.getBlockHeader( ).getPreviousHash( ) ); block = this.getBlockByHash( previousHash ); } } return blocks; } public Block getChildOfBlock( Block block ) { return chain.get( chain.getChain( ).indexOf( block ) + 1 ); } //AltChains private Chain getChainForBlock(Block block) { Chain result = null; int index = chain.getChain().indexOf(block); if(index == -1) { for(Chain altChain: altChains) { if(altChain.getChain().indexOf(block) > -1) { result = altChain; } } } else { result = chain; } return result; } private void createNewChain(byte[] previousBlockHash, Block block) { Chain chain = getChainForBlock(getBlockByHash(previousBlockHash)); for(int i = chain.getChain().size() - 1; i >= 0; i--) { if(Arrays.equals(chain.get(i).getBlockHash(), previousBlockHash)) { List<Block> blockList = new CopyOnWriteArrayList<Block>(chain.getChain().subList(0, i + 1)); blockList.add(block); Chain newChain = new Chain(NETWORK_ID, blockList); altChains.add(newChain); i = -1; switchChainsIfNecessary(newChain); } } } private void switchChainsIfNecessary(Chain chain) { logger.debug("Chains switched"); if(chain.size() > this.chain.size()) { this.chain = chain; this.bestBlock = chain.getLast(); } } private void checkAltChains(byte[] previousHash, Block block) { boolean isNotABlockOfAnAltChain = true; for(Chain altChain : altChains) { if(Arrays.equals(altChain.getLast().getBlockHash(), previousHash)) { altChain.add(block); switchChainsIfNecessary(altChain); isNotABlockOfAnAltChain = false; break; } } if(isNotABlockOfAnAltChain) { createNewChain(previousHash, block); } } private boolean previousBlockIsBestBlock(byte [] BlockHash) { return Arrays.equals(DependencyManager.getBlockchain().getPreviousHash(), BlockHash); } }
×
×
  • Neu erstellen...

Wichtige Information

Wir haben Cookies auf Deinem Gerät platziert. Das hilft uns diese Webseite zu verbessern. Du kannst die Cookie-Einstellungen anpassen, andernfalls gehen wir davon aus, dass Du damit einverstanden bist, weiterzumachen.