Merge pull request #20923 from holiman/fix_seckeybuf
trie: fix concurrent usage of secKeyBuf, ref #20920
This commit is contained in:
		
						commit
						79b68dd78d
					
				| @ -59,8 +59,11 @@ var ( | |||||||
| // secureKeyPrefix is the database key prefix used to store trie node preimages.
 | // secureKeyPrefix is the database key prefix used to store trie node preimages.
 | ||||||
| var secureKeyPrefix = []byte("secure-key-") | var secureKeyPrefix = []byte("secure-key-") | ||||||
| 
 | 
 | ||||||
|  | // secureKeyPrefixLength is the length of the above prefix
 | ||||||
|  | const secureKeyPrefixLength = 11 | ||||||
|  | 
 | ||||||
| // secureKeyLength is the length of the above prefix + 32byte hash.
 | // secureKeyLength is the length of the above prefix + 32byte hash.
 | ||||||
| const secureKeyLength = 11 + 32 | const secureKeyLength = secureKeyPrefixLength + 32 | ||||||
| 
 | 
 | ||||||
| // Database is an intermediate write layer between the trie data structures and
 | // Database is an intermediate write layer between the trie data structures and
 | ||||||
| // the disk database. The aim is to accumulate trie writes in-memory and only
 | // the disk database. The aim is to accumulate trie writes in-memory and only
 | ||||||
| @ -79,7 +82,6 @@ type Database struct { | |||||||
| 	newest  common.Hash                 // Newest tracked node, flush-list tail
 | 	newest  common.Hash                 // Newest tracked node, flush-list tail
 | ||||||
| 
 | 
 | ||||||
| 	preimages map[common.Hash][]byte // Preimages of nodes from the secure trie
 | 	preimages map[common.Hash][]byte // Preimages of nodes from the secure trie
 | ||||||
| 	seckeybuf [secureKeyLength]byte  // Ephemeral buffer for calculating preimage keys
 |  | ||||||
| 
 | 
 | ||||||
| 	gctime  time.Duration      // Time spent on garbage collection since last commit
 | 	gctime  time.Duration      // Time spent on garbage collection since last commit
 | ||||||
| 	gcnodes uint64             // Nodes garbage collected since last commit
 | 	gcnodes uint64             // Nodes garbage collected since last commit
 | ||||||
| @ -445,15 +447,15 @@ func (db *Database) preimage(hash common.Hash) ([]byte, error) { | |||||||
| 		return preimage, nil | 		return preimage, nil | ||||||
| 	} | 	} | ||||||
| 	// Content unavailable in memory, attempt to retrieve from disk
 | 	// Content unavailable in memory, attempt to retrieve from disk
 | ||||||
| 	return db.diskdb.Get(db.secureKey(hash[:])) | 	return db.diskdb.Get(secureKey(hash)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // secureKey returns the database key for the preimage of key, as an ephemeral
 | // secureKey returns the database key for the preimage of key (as a newly
 | ||||||
| // buffer. The caller must not hold onto the return value because it will become
 | // allocated byte-slice)
 | ||||||
| // invalid on the next call.
 | func secureKey(hash common.Hash) []byte { | ||||||
| func (db *Database) secureKey(key []byte) []byte { | 	buf := make([]byte, secureKeyLength) | ||||||
| 	buf := append(db.seckeybuf[:0], secureKeyPrefix...) | 	copy(buf, secureKeyPrefix) | ||||||
| 	buf = append(buf, key...) | 	copy(buf[secureKeyPrefixLength:], hash[:]) | ||||||
| 	return buf | 	return buf | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -596,12 +598,18 @@ func (db *Database) Cap(limit common.StorageSize) error { | |||||||
| 	size := db.dirtiesSize + common.StorageSize((len(db.dirties)-1)*cachedNodeSize) | 	size := db.dirtiesSize + common.StorageSize((len(db.dirties)-1)*cachedNodeSize) | ||||||
| 	size += db.childrenSize - common.StorageSize(len(db.dirties[common.Hash{}].children)*(common.HashLength+2)) | 	size += db.childrenSize - common.StorageSize(len(db.dirties[common.Hash{}].children)*(common.HashLength+2)) | ||||||
| 
 | 
 | ||||||
|  | 	// We reuse an ephemeral buffer for the keys. The batch Put operation
 | ||||||
|  | 	// copies it internally, so we can reuse it.
 | ||||||
|  | 	var keyBuf [secureKeyLength]byte | ||||||
|  | 	copy(keyBuf[:], secureKeyPrefix) | ||||||
|  | 
 | ||||||
| 	// If the preimage cache got large enough, push to disk. If it's still small
 | 	// If the preimage cache got large enough, push to disk. If it's still small
 | ||||||
| 	// leave for later to deduplicate writes.
 | 	// leave for later to deduplicate writes.
 | ||||||
| 	flushPreimages := db.preimagesSize > 4*1024*1024 | 	flushPreimages := db.preimagesSize > 4*1024*1024 | ||||||
| 	if flushPreimages { | 	if flushPreimages { | ||||||
| 		for hash, preimage := range db.preimages { | 		for hash, preimage := range db.preimages { | ||||||
| 			if err := batch.Put(db.secureKey(hash[:]), preimage); err != nil { | 			copy(keyBuf[secureKeyPrefixLength:], hash[:]) | ||||||
|  | 			if err := batch.Put(keyBuf[:], preimage); err != nil { | ||||||
| 				log.Error("Failed to commit preimage from trie database", "err", err) | 				log.Error("Failed to commit preimage from trie database", "err", err) | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| @ -692,9 +700,15 @@ func (db *Database) Commit(node common.Hash, report bool) error { | |||||||
| 	start := time.Now() | 	start := time.Now() | ||||||
| 	batch := db.diskdb.NewBatch() | 	batch := db.diskdb.NewBatch() | ||||||
| 
 | 
 | ||||||
|  | 	// We reuse an ephemeral buffer for the keys. The batch Put operation
 | ||||||
|  | 	// copies it internally, so we can reuse it.
 | ||||||
|  | 	var keyBuf [secureKeyLength]byte | ||||||
|  | 	copy(keyBuf[:], secureKeyPrefix) | ||||||
|  | 
 | ||||||
| 	// Move all of the accumulated preimages into a write batch
 | 	// Move all of the accumulated preimages into a write batch
 | ||||||
| 	for hash, preimage := range db.preimages { | 	for hash, preimage := range db.preimages { | ||||||
| 		if err := batch.Put(db.secureKey(hash[:]), preimage); err != nil { | 		copy(keyBuf[secureKeyPrefixLength:], hash[:]) | ||||||
|  | 		if err := batch.Put(keyBuf[:], preimage); err != nil { | ||||||
| 			log.Error("Failed to commit preimage from trie database", "err", err) | 			log.Error("Failed to commit preimage from trie database", "err", err) | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user